├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── app-release.apk
├── build.gradle
├── libs
│ ├── armeabi-v7a
│ │ ├── libiconv.so
│ │ └── libzbarjni.so
│ ├── armeabi
│ │ ├── libiconv.so
│ │ └── libzbarjni.so
│ ├── jsoup-1.8.1.jar
│ ├── x86
│ │ ├── libiconv.so
│ │ └── libzbarjni.so
│ └── zbar.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── dict
│ │ └── hm
│ │ └── dictionary
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── dict
│ │ └── hm
│ │ └── dictionary
│ │ ├── async
│ │ ├── HttpDownload.java
│ │ ├── LoadDictionary.java
│ │ ├── UnGzipThread.java
│ │ ├── UserAsyncWorkerHandler.java
│ │ └── WordAsyncQueryHandler.java
│ │ ├── dict
│ │ ├── DictContentProvider.java
│ │ ├── DictFormat.java
│ │ ├── DictItem.java
│ │ ├── DictManager.java
│ │ ├── DictSQLiteDatabase.java
│ │ ├── DictSQLiteDefine.java
│ │ ├── DictSQLiteHelper.java
│ │ ├── UserDictSQLiteHelper.java
│ │ └── parse
│ │ │ ├── DictParser.java
│ │ │ ├── IdxParser.java
│ │ │ └── IfoFormat.java
│ │ ├── lib
│ │ ├── CustomGZIPInputStream.java
│ │ ├── ScrimInsetsFrameLayout.java
│ │ └── ZBarActivity.java
│ │ ├── paper
│ │ ├── JsonEntry.java
│ │ ├── PaperErrorCode.java
│ │ ├── PaperJsonReader.java
│ │ ├── PaperJsonWriter.java
│ │ ├── PaperParser.java
│ │ └── PaperWorkerHandler.java
│ │ └── ui
│ │ ├── BaseManagerActivity.java
│ │ ├── DialogExPreference.java
│ │ ├── DictManagerActivity.java
│ │ ├── FileListFragment.java
│ │ ├── MainActivity.java
│ │ ├── PaperArchiveFragment.java
│ │ ├── PaperManagerActivity.java
│ │ ├── PaperViewerFragment.java
│ │ ├── SettingsFragment.java
│ │ ├── UserDictFragment.java
│ │ ├── adapter
│ │ ├── NavigationDrawerAdapter.java
│ │ ├── PaperJsonAdapter.java
│ │ ├── PaperViewerAdapter.java
│ │ └── UserDictAdapter.java
│ │ └── dialog
│ │ ├── AboutDialog.java
│ │ ├── AlertDialogFragment.java
│ │ ├── DefinitionDialog.java
│ │ ├── EditDialog.java
│ │ ├── NotificationDialog.java
│ │ ├── ProgressDialog.java
│ │ ├── SelectDialog.java
│ │ └── SwitchDictDialog.java
│ └── res
│ ├── drawable-xxhdpi
│ ├── ic_action_archive_white_24dp.png
│ ├── ic_action_edit_white_24dp.png
│ ├── ic_action_new_attachment.png
│ ├── ic_action_next_item.png
│ ├── ic_action_previous_item.png
│ ├── ic_action_qrcode.png
│ ├── ic_action_search.png
│ ├── ic_add_black_24dp.png
│ ├── ic_close_white_18dp.png
│ ├── ic_favorite_black_48dp.png
│ ├── ic_favorite_outline_black_48dp.png
│ ├── ic_launcher.png
│ ├── ic_sort_white_24dp.png
│ └── ic_wallpaper.png
│ ├── drawable
│ ├── drawer_divider.xml
│ ├── favorite_selector.xml
│ ├── floating_button.xml
│ └── list_selector.xml
│ ├── layout
│ ├── activity_camera.xml
│ ├── activity_main.xml
│ ├── activity_manager.xml
│ ├── definition_item.xml
│ ├── drawer_item.xml
│ ├── edit_text.xml
│ ├── fragment_file.xml
│ ├── paper_json_item.xml
│ ├── paper_viewer_item.xml
│ ├── progress.xml
│ ├── progress_circle.xml
│ ├── snackbar.xml
│ ├── textview_item.xml
│ └── user_word_item.xml
│ ├── menu
│ ├── menu_archive.xml
│ ├── menu_main.xml
│ ├── menu_paper_manager.xml
│ └── menu_user_dict.xml
│ ├── values-v21
│ └── styles.xml
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values-zh
│ └── strings.xml
│ ├── values
│ ├── attrs.xml
│ ├── custom_color.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ ├── preferences.xml
│ └── searchable.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshot
└── dict.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | *.iml
8 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Dictionary
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 想法
2 | 问题:
3 |
4 | 在你英语阅读能力不足前,是时常需要查阅单词的,但当你中断阅读后,你又容易忘记之前看的内容了。
5 |
6 | 解决方案:
7 |
8 | **解析你所需要阅读的英文文章,基于你的单词词库过滤出文章内的生词,集中显示生词解释**
9 |
10 | *基础:* 个人单词库
11 |
12 | *难题:* 解析文章,Text性质的文档解析容易,其他的格式看OCR。对非 text 数据则通过云端提供的 OCR 服务解析。
13 |
14 | - 情景一:还记得当年做阅读理解的痛苦吗?如果拍照下阅读理解的内容进而解析过滤出生词,便可快速查阅生词意思。
15 | - 情景二:浏览器提供插件,解析当前网页内容,根据个人词库过滤出生词,也可快速查阅生词意思。
16 |
17 |
18 | *核心:* 个人词库(分通用与专业)。
19 |
20 | *终极形态:* 得到每个用户的专业性词库数据,提供用户可能感兴趣的单词。
21 |
22 | *云端同步个人词库*
23 |
24 | 以上是基于一个词典应用,你想得到生词的什么解释就看你拥有怎样的词典,不限于英英,英汉,英日,英韩等等,都是针对英语,英语容易分词。
25 |
26 | Android 通过 Intent 提供接口,接收 text 数据,解析内容过滤出生词。但这里面没统一格式,怎么实现?
27 |
28 | 下面是我的部分实现 (Android 应用)
29 |
30 | ---------------
31 |
32 | [下载](app/app-release.apk)
33 | 
34 |
35 | ## 基本功能
36 | 词典功能。
37 | 不包含词典,需自己添加。实现了 stardict 2.4.2 格式的字典, 还没增加音频图像的支持。后续增加字典格式。
38 | 一词典 = 一张FTS表一张索引表一项词典信息记录。(还是所有单词一张FTS表?)
39 |
40 | FTS 表提高搜索速度,会建立大量索引,空间使用量大增。不存放非搜索数据。
41 | 全文搜索表(FTS):
42 |
43 | | rowid | word |
44 | | :--------- | --------:|
45 |
46 | 根据不同词典格式建立不同的索引表。
47 | 单词索引表:
48 |
49 | | rowid | offset | size |
50 | | :-------- | :-------: | -------: |
51 |
52 | 记录词典信息表:
53 |
54 | | rowid | name | type | data | active | table_name |
55 | | :---- | :----:| :---: | :---: | :-------: | ----------: |
56 |
57 |
58 | name: 词典名
59 | type: 词典格式
60 | data: 词典相关信息,如相关文件路径等,自定义
61 | active: 激活词典。
62 | table_name: 词典对应的表名,目前是 table_name = name
63 |
64 | 通用个人词库表:
65 |
66 | | rowid | word | count | time |
67 | | :---- | :---:| :----:| ----:|
68 |
69 | 专业个人词库表:
70 |
71 | | rowid | word | count | time | explain |
72 | | :---- | :---: | :---: | :---: | -------: |
73 |
74 |
75 | word: 词
76 | count: 归档次数
77 | time: 初始归档时间
78 | explain: 说明
79 |
80 | ## 文章管理
81 | 你可以添加 text,html 格式的文章,解析器会分析出单词,统计各个单词的出现次数,按次数排序存储。提供三种方法归档文章单词,归档即是把单词存放到你的单词库里。
82 | - 全部归档,把全部单词归档。
83 | - 过滤归档,把已存在词库里面的单词归档(只是增加了归档次数),过滤出生词。
84 | - 手动归档,手动选择归档单词。
85 |
86 | 存储格式 JSON ,Key_Value 形式,单词为 key ,次数为 value 。
87 |
88 | ## 个人词库
89 | 分两种类型,通用词库和专业词库。专业词库可以添加解释。(未完全完成)
90 | - 词库记录初始归档时间,同时会记录单词的总统计次数。专业词库多一个个人解释项。
91 | - 根据统计次数、归档时间展示个人词库。
92 |
93 | ## TODO
94 | 单词变形纠正(如复数),去掉非单词,添加 OCR 云端解析支持,词库云端同步,浏览器插件支持...
95 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 |
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/app-release.apk
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | signingConfigs {
5 | }
6 | compileSdkVersion 23
7 | buildToolsVersion '23.0.2'
8 | defaultConfig {
9 | applicationId "com.dict.hm.dictionary"
10 | minSdkVersion 16
11 | targetSdkVersion 23
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | productFlavors {
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(dir: 'libs', include: ['*.jar'])
27 | compile files('libs/zbar.jar')
28 | compile 'com.android.support:support-v13:23.1.1'
29 | compile 'com.android.support:appcompat-v7:23.1.1'
30 | compile 'com.android.support:design:23.1.1'
31 | compile 'com.android.support:recyclerview-v7:23.1.1'
32 | }
33 |
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libiconv.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/armeabi-v7a/libiconv.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libzbarjni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/armeabi-v7a/libzbarjni.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libiconv.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/armeabi/libiconv.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libzbarjni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/armeabi/libzbarjni.so
--------------------------------------------------------------------------------
/app/libs/jsoup-1.8.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/jsoup-1.8.1.jar
--------------------------------------------------------------------------------
/app/libs/x86/libiconv.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/x86/libiconv.so
--------------------------------------------------------------------------------
/app/libs/x86/libzbarjni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/x86/libzbarjni.so
--------------------------------------------------------------------------------
/app/libs/zbar.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/libs/zbar.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/hm/android-sdk-linux/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/dict/hm/dictionary/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
36 |
37 |
40 |
41 |
44 |
45 |
49 |
50 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/async/HttpDownload.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.async;
2 |
3 | import android.os.AsyncTask;
4 | import android.util.Log;
5 |
6 | import com.dict.hm.dictionary.ui.BaseManagerActivity;
7 |
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.net.HttpURLConnection;
12 | import java.net.URL;
13 |
14 | /**
15 | * Created by hm on 15-4-28.
16 | */
17 | public class HttpDownload extends AsyncTask {
18 | BaseManagerActivity activity;
19 |
20 | public HttpDownload(BaseManagerActivity activity) {
21 | super();
22 | this.activity = activity;
23 | activity.initProgressDialog("Download dict file", 100);
24 | }
25 |
26 | @Override
27 | protected Long doInBackground(String... params) {
28 | HttpURLConnection connection = null;
29 | InputStream in = null;
30 | FileOutputStream out = null;
31 | long total = 0;
32 | if (params.length != 2) {
33 | return ((long) -1);
34 | }
35 | try {
36 | URL url = new URL(params[0]);
37 | connection = (HttpURLConnection) url.openConnection();
38 | connection.connect();
39 | if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
40 | return ((long) -1);
41 | }
42 | int fileLength = connection.getContentLength();
43 | in = connection.getInputStream();
44 | out = new FileOutputStream(params[1]);
45 | byte[] bytes = new byte[4096];
46 | int read;
47 | while ((read = in.read(bytes)) != -1) {
48 | total += read;
49 | out.write(bytes, 0, read);
50 | if (fileLength > 0) {
51 | publishProgress((int) total *100 / fileLength);
52 | }
53 | }
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | } finally {
57 | try {
58 | if (connection != null) {
59 | connection.disconnect();
60 | }
61 | if (in != null) {
62 | in.close();
63 | }
64 | if (out != null) {
65 | out.close();
66 | }
67 | } catch (IOException e) {
68 | e.printStackTrace();
69 | }
70 | }
71 |
72 | return total;
73 | }
74 |
75 | @Override
76 | protected void onProgressUpdate(Integer... values) {
77 | Log.d("Download process", values[0] + "%");
78 | activity.setProgress(values[0]);
79 | // super.onProgressUpdate(values);
80 | }
81 |
82 | @Override
83 | protected void onPostExecute(Long aLong) {
84 | Log.d("Download success", "download size " + aLong);
85 | activity.dismissProgressDialog();
86 | // super.onPostExecute(aLong);
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/async/LoadDictionary.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.async;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | import com.dict.hm.dictionary.ui.DictManagerActivity;
7 | import com.dict.hm.dictionary.dict.DictSQLiteHelper;
8 | import com.dict.hm.dictionary.dict.parse.IdxParser;
9 |
10 | import java.io.File;
11 | import java.io.IOException;
12 | import java.util.ArrayList;
13 |
14 | /**
15 | * Created by hm on 15-5-12.
16 | */
17 | public class LoadDictionary extends Thread{
18 | File idxFile;
19 | Handler handler;
20 | String bookName;
21 | DictSQLiteHelper helper;
22 |
23 | public LoadDictionary(String bookName, File idxFile, DictSQLiteHelper helper, Handler handler) {
24 | super();
25 | this.idxFile = idxFile;
26 | this.handler = handler;
27 | this.bookName = bookName;
28 | this.helper = helper;
29 | }
30 |
31 | @Override
32 | public void run() {
33 | try {
34 | helper.createTable(bookName);
35 | loadWords(idxFile);
36 | } catch (IOException e) {
37 | throw new RuntimeException(e);
38 | }
39 | }
40 |
41 | private void loadWords(File idxFile) throws IOException {
42 | IdxParser parser = new IdxParser(idxFile);
43 | ArrayList list;
44 | int count = 0;
45 |
46 | while (true) {
47 | list = parser.getWordEntries();
48 | if (list == null || list.size() == 0) {
49 | break;
50 | }
51 | helper.addWords(list);
52 | count += list.size();
53 | Message message = handler.obtainMessage(DictManagerActivity.PROCESSING);
54 | message.arg1 = count;
55 | handler.sendMessage(message);
56 | }
57 | Message message = handler.obtainMessage(DictManagerActivity.OK);
58 | message.obj = bookName;
59 | handler.sendMessage(message);
60 | }
61 |
62 | }
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/async/UnGzipThread.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.async;
2 |
3 | import android.os.Handler;
4 | import android.util.Log;
5 |
6 | import com.dict.hm.dictionary.lib.CustomGZIPInputStream;
7 | import com.dict.hm.dictionary.ui.DictManagerActivity;
8 |
9 | import java.io.BufferedInputStream;
10 | import java.io.BufferedOutputStream;
11 | import java.io.File;
12 | import java.io.FileInputStream;
13 | import java.io.FileOutputStream;
14 | import java.io.IOException;
15 |
16 | /**
17 | * Created by hm on 15-1-31.
18 | */
19 | public class UnGzipThread extends Thread {
20 | File zip;
21 | File out;
22 | Handler handler;
23 |
24 | public UnGzipThread(File zip, File out, Handler handler) {
25 | this.zip = zip;
26 | this.out = out;
27 | this.handler = handler;
28 | }
29 |
30 | @Override
31 | public void run() {
32 | unzipFile(zip, out);
33 | }
34 |
35 | private boolean unzipFile(File gzipInputFile, File outputFile) {
36 | BufferedInputStream in = null;
37 | BufferedOutputStream out = null;
38 | CustomGZIPInputStream zin = null;
39 | int BUF_SIZE = 4096;
40 | try {
41 | in = new BufferedInputStream(new FileInputStream(gzipInputFile));
42 | out = new BufferedOutputStream(new FileOutputStream(outputFile));
43 | zin = new CustomGZIPInputStream(in);
44 | byte[] bytes = new byte[BUF_SIZE];
45 | int read;
46 | // int count = 0;
47 | Log.d("in", "" + in.available());
48 | while ((read = zin.read(bytes, 0, BUF_SIZE)) >= 0) {
49 | out.write(bytes, 0, read);
50 | // count += read;
51 | // Message message = handler.obtainMessage(BaseManagerActivity.PROCESSING);
52 | // message.arg1 = count;
53 | // handler.sendMessage(message);
54 | }
55 | handler.sendEmptyMessage(DictManagerActivity.DECOMPRESS);
56 | } catch (IOException e) {
57 | outputFile.delete();
58 | handler.sendEmptyMessage(DictManagerActivity.DECOMPRESS_ERR);
59 | e.printStackTrace();
60 | return false;
61 | } finally {
62 | try {
63 | if (in != null) {
64 | in.close();
65 | }
66 | if (out != null) {
67 | out.close();
68 | }
69 | if (zin != null) {
70 | zin .close();
71 | }
72 | } catch (IOException e) {
73 | e.printStackTrace();
74 | }
75 | }
76 | return true;
77 | }
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/async/UserAsyncWorkerHandler.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.async;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.os.Handler;
6 | import android.os.HandlerThread;
7 | import android.os.Looper;
8 | import android.os.Message;
9 |
10 | import com.dict.hm.dictionary.dict.DictFormat;
11 | import com.dict.hm.dictionary.dict.UserDictSQLiteHelper;
12 |
13 | import java.io.File;
14 | import java.lang.ref.WeakReference;
15 | import java.util.ArrayList;
16 |
17 | /**
18 | * Created by hm on 15-5-6.
19 | */
20 | public class UserAsyncWorkerHandler extends Handler {
21 | private static final int EVENT_ARG_QUERY = 1;
22 | private static final int EVENT_ARG_INSERT = 2;
23 | private static final int EVENT_ARG_UPDATE = 3;
24 | private static final int EVENT_ARG_DELETE = 4;
25 | private static final int EVENT_USER_QUERY = 5;
26 | private static final int EVENT_PAPER_LIST = 6;
27 |
28 | private static Looper sLooper = null;
29 | private Handler mWorkerThreadHandler;
30 |
31 | WeakReference listenerWeakReference;
32 | DictManagerCallback callback;
33 | UserDictSQLiteHelper helper;
34 |
35 | static UserAsyncWorkerHandler handler = null;
36 |
37 | protected static final class WorkerArgs {
38 | Handler handler;
39 | long rowid;
40 | Cursor result;
41 | DictFormat format;
42 | //paper list
43 | File dir;
44 | ArrayList files;
45 | }
46 |
47 | protected class WorkerHandler extends Handler {
48 |
49 | public WorkerHandler(Looper looper) {
50 | super(looper);
51 | }
52 |
53 | @Override
54 | public void handleMessage(Message msg) {
55 | if (helper == null) {
56 | return;
57 | }
58 | WorkerArgs args = (WorkerArgs) msg.obj;
59 | Message message = args.handler.obtainMessage(msg.what);
60 | switch (msg.what) {
61 | case EVENT_ARG_QUERY:
62 | args.result = helper.queryDictionaries();
63 | break;
64 | case EVENT_ARG_INSERT:
65 | args.rowid = helper.insertDictionary(args.format);
66 | break;
67 | case EVENT_ARG_UPDATE:
68 | args.rowid = helper.updateDictionary(args.rowid, msg.arg1);
69 | break;
70 | case EVENT_ARG_DELETE:
71 | args.rowid = helper.deleteDictionary(args.rowid);
72 | break;
73 | case EVENT_USER_QUERY:
74 | args.result = helper.getWordsOrderBy(msg.arg1);
75 | break;
76 | case EVENT_PAPER_LIST:
77 | if (args.dir.isDirectory()) {
78 | String[] names = args.dir.list();
79 | ArrayList list = new ArrayList<>(names.length);
80 | for (String name : args.dir.list()) {
81 | list.add(name);
82 | }
83 | args.files = list;
84 | } else {
85 | args.files = null;
86 | }
87 | break;
88 | default:
89 | return;
90 | }
91 | message.obj = args;
92 | message.sendToTarget();
93 | }
94 | }
95 |
96 | public static UserAsyncWorkerHandler getInstance(Context context, DictManagerCallback mCallback) {
97 | if (handler == null) {
98 | handler = new UserAsyncWorkerHandler(context.getApplicationContext(), mCallback);
99 | }
100 | return handler;
101 | }
102 |
103 | public UserAsyncWorkerHandler(Context context, DictManagerCallback callback) {
104 | synchronized (UserAsyncWorkerHandler.class) {
105 | if (sLooper == null) {
106 | HandlerThread thread = new HandlerThread("AsyncQueryWorker");
107 | thread.start();
108 |
109 | sLooper = thread.getLooper();
110 | }
111 | }
112 | mWorkerThreadHandler = new WorkerHandler(sLooper);
113 | helper = UserDictSQLiteHelper.getInstance(context);
114 | this.callback = callback;
115 | }
116 |
117 | public void setUserDictQueryListener(UserDictQueryListener listener) {
118 | listenerWeakReference = new WeakReference<>(listener);
119 | }
120 |
121 | @Override
122 | public void handleMessage(Message msg) {
123 | WorkerArgs args = (WorkerArgs) msg.obj;
124 |
125 | switch (msg.what) {
126 | case EVENT_ARG_QUERY:
127 | callback.onQueryComplete(args.result);
128 | break;
129 | case EVENT_ARG_INSERT:
130 | callback.onInsertComplete(args.rowid);
131 | break;
132 | case EVENT_ARG_UPDATE:
133 | callback.onUpdateComplete(args.rowid);
134 | break;
135 | case EVENT_ARG_DELETE:
136 | callback.onDeleteComplete(args.rowid);
137 | break;
138 | case EVENT_USER_QUERY:
139 | if (listenerWeakReference == null) {
140 | return;
141 | }
142 | UserDictQueryListener listener = listenerWeakReference.get();
143 | if (listener == null) {
144 | return;
145 | }
146 | listener.onUserDictQueryComplete(args.result);
147 | break;
148 | case EVENT_PAPER_LIST:
149 | callback.onUserPaperListComplete(args.files);
150 | break;
151 | }
152 | }
153 |
154 | /**
155 | * start to get a list names of papers
156 | */
157 | public void startList(File paperDir) {
158 | WorkerArgs args = new WorkerArgs();
159 | args.handler = this;
160 | args.dir = paperDir;
161 | Message message = mWorkerThreadHandler.obtainMessage(EVENT_PAPER_LIST);
162 | message.obj = args;
163 | message.sendToTarget();
164 | }
165 |
166 |
167 | public void startQuery() {
168 | WorkerArgs args = new WorkerArgs();
169 | args.handler = this;
170 | Message message = mWorkerThreadHandler.obtainMessage(EVENT_ARG_QUERY);
171 | message.obj = args;
172 | message.sendToTarget();
173 | }
174 |
175 | public void startInsert(DictFormat dictFormat) {
176 | WorkerArgs args = new WorkerArgs();
177 | args.handler = this;
178 | args.format = dictFormat;
179 | Message message = mWorkerThreadHandler.obtainMessage(EVENT_ARG_INSERT);
180 | message.obj = args;
181 | message.sendToTarget();
182 | }
183 |
184 | public void startUpdate(long rowid, int on) {
185 | WorkerArgs args = new WorkerArgs();
186 | args.handler = this;
187 | args.rowid = rowid;
188 | Message message = mWorkerThreadHandler.obtainMessage(EVENT_ARG_UPDATE);
189 | message.obj = args;
190 | message.arg1 = on;
191 | message.sendToTarget();
192 | }
193 |
194 | public void startDelete(long rowid) {
195 | WorkerArgs args = new WorkerArgs();
196 | args.handler = this;
197 | args.rowid = rowid;
198 | Message message = mWorkerThreadHandler.obtainMessage(EVENT_ARG_DELETE);
199 | message.obj = args;
200 | message.sendToTarget();
201 | }
202 |
203 | /**
204 | * get user dict's words
205 | * @param which
206 | */
207 | public void startQuery(int which) {
208 | WorkerArgs args = new WorkerArgs();
209 | args.handler = this;
210 |
211 | Message message = mWorkerThreadHandler.obtainMessage(EVENT_USER_QUERY);
212 | message .obj = args;
213 | message.arg1 = which;
214 | message.sendToTarget();
215 | }
216 |
217 | public interface UserDictQueryListener {
218 | void onUserDictQueryComplete(Cursor result);
219 | }
220 |
221 | public interface DictManagerCallback {
222 | void onQueryComplete(Cursor result);
223 | void onInsertComplete(long id);
224 | void onUpdateComplete(long id);
225 | void onDeleteComplete(long id);
226 | void onUserPaperListComplete(ArrayList list);
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/async/WordAsyncQueryHandler.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.async;
2 |
3 | import android.content.AsyncQueryHandler;
4 | import android.content.ContentResolver;
5 | import android.database.Cursor;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.util.Log;
9 |
10 | import java.lang.ref.WeakReference;
11 |
12 | /**
13 | * Created by hm on 15-5-4.
14 | */
15 | public class WordAsyncQueryHandler extends AsyncQueryHandler{
16 | WeakReference listenerWeakReference;
17 | Handler worker = null;
18 |
19 | public interface AsyncQueryListener {
20 | void onQueryComplete(int token, Object cookie, Cursor cursor);
21 | }
22 |
23 | public WordAsyncQueryHandler(ContentResolver cr, AsyncQueryListener listener) {
24 | super(cr);
25 | listenerWeakReference = new WeakReference<>(listener);
26 | }
27 |
28 | @Override
29 | protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
30 | final AsyncQueryListener listener = listenerWeakReference.get();
31 | if (listener != null) {
32 | listener.onQueryComplete(token, cookie, cursor);
33 | } else if (cursor != null) {
34 | cursor.close();
35 | }
36 | }
37 |
38 | @Override
39 | protected Handler createHandler(Looper looper) {
40 | worker = super.createHandler(looper);
41 | Log.d("thread id", "" + looper.getThread().getId());
42 | return worker;
43 | }
44 |
45 | //TODO:does need to quit the worker thread?
46 | public void quit() {
47 | if (worker != null) {
48 | worker.getLooper().quit();
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/DictContentProvider.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict;
2 |
3 |
4 | import android.app.SearchManager;
5 | import android.content.ContentProvider;
6 | import android.content.ContentResolver;
7 | import android.content.ContentValues;
8 | import android.content.UriMatcher;
9 | import android.database.Cursor;
10 | import android.net.Uri;
11 | import android.provider.BaseColumns;
12 | import android.text.TextUtils;
13 | import android.util.Log;
14 |
15 | /**
16 | * Created by hm on 15-1-7.
17 | */
18 | public class DictContentProvider extends ContentProvider{
19 | String TAG = "DictContentProvider";
20 | public static String AUTHORITY = "com.dict.hm.dictionary.provider";
21 | public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/dictionary");
22 | public static final String WORDS_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +
23 | "/vnd.com.dict.hm.provider";
24 | public static final String DEFINITION_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE +
25 | "/vnd.com.dict.hm.provider";
26 |
27 | private String[] suggestionColumns = new String[] {
28 | BaseColumns._ID,
29 | DictSQLiteDefine.COLUMN_KEY_WORD,
30 | /**
31 | * alias of COLUMN_KEY_WORD
32 | * This column allows suggestions to provide additional data that is included
33 | * as an extra in the intent’s EXTRA_DATA_KEY key.
34 | */
35 | SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
36 | /* SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
37 | (only if you want to refresh shortcuts) */
38 | SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};
39 |
40 | private String[] wordColumns = new String[] {
41 | BaseColumns._ID,
42 | DictSQLiteDefine.COLUMN_KEY_WORD};
43 |
44 | //UriMatcher stuff
45 | private static final int SEARCH_WORDS = 0;
46 | private static final int GET_WORD = 1;
47 | private static final int SEARCH_SUGGEST = 2;
48 | private static final int REFRESH_SHORTCUT = 3;
49 | private static final int GET_INDEX_BY_WORD = 4;
50 | private static final UriMatcher uriMatcher = buildUriMatcher();
51 |
52 | private DictSQLiteDatabase mDictionary;
53 |
54 | public boolean onCreate() {
55 | mDictionary = new DictSQLiteDatabase(getContext());
56 | Log.d(TAG, "onCreate");
57 | return true;
58 | }
59 |
60 | private static UriMatcher buildUriMatcher() {
61 | UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
62 | matcher.addURI(AUTHORITY, "dictionary", SEARCH_WORDS);
63 | matcher.addURI(AUTHORITY, "dictionary/#", GET_WORD);
64 | matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
65 | matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
66 | matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, REFRESH_SHORTCUT);
67 | matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", REFRESH_SHORTCUT);
68 | /**
69 | * this is for the PaperViewAdapter
70 | */
71 | matcher.addURI(AUTHORITY, "dictionary/word", GET_INDEX_BY_WORD);
72 | return matcher;
73 | }
74 |
75 | @Override
76 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
77 | String sortOrder) {
78 | switch (uriMatcher.match(uri)) {
79 | case SEARCH_SUGGEST:
80 | if (selectionArgs == null) {
81 | throw new IllegalArgumentException(
82 | "selectionArgs must be provided for the Uri: " + uri);
83 | }
84 | return getSuggestions(selectionArgs[0]);
85 | case SEARCH_WORDS:
86 | if (selectionArgs == null) {
87 | throw new IllegalArgumentException(
88 | "selectionArgs must be provided for the Uri: " + uri);
89 | }
90 | return search(selectionArgs[0]);
91 | case GET_INDEX_BY_WORD:
92 | if (selectionArgs == null) {
93 | throw new IllegalArgumentException(
94 | "selectionArgs must be provided for the Uri: " + uri);
95 | }
96 | return getWordIndex(selectionArgs[0]);
97 | case GET_WORD:
98 | return getWordIndex(uri);
99 | case REFRESH_SHORTCUT:
100 | return refreshShortcut(uri);
101 | default:
102 | throw new IllegalArgumentException("Unknown Uri: " + uri);
103 | }
104 | }
105 |
106 | /**
107 | *
108 | * @param query
109 | * @return
110 | * TODO: getSuggestions() can only get the suggest words without offset and size.
111 | */
112 | private Cursor getSuggestions(String query) {
113 | Log.d(TAG, "getSuggestions:" + query);
114 | if (TextUtils.isEmpty(query)) {
115 | return null;
116 | }
117 | query = query.toLowerCase();
118 |
119 | // return mDictionary.getWordMatches(query, columns);
120 | return mDictionary.getWordMatchesInLength(query, suggestionColumns);
121 | }
122 |
123 | private Cursor search(String query) {
124 | Log.d(TAG, "search:" + query);
125 | if (TextUtils.isEmpty(query)) {
126 | return null;
127 | }
128 | query = query.toLowerCase();
129 | return mDictionary.getWordMatches(query, wordColumns);
130 | }
131 |
132 | /**
133 | * get the word's index by word
134 | *
135 | * @param word word to query
136 | * @return word's index to return
137 | */
138 | private Cursor getWordIndex(String word) {
139 | Log.d(TAG, "getWord:" + word);
140 | if (TextUtils.isEmpty(word)) {
141 | return null;
142 | }
143 | word = word.toLowerCase();
144 | return mDictionary.getIndexByWord(word);
145 | }
146 |
147 | /**
148 | * get word's index by word's id
149 | *
150 | * @param uri
151 | * @return
152 | */
153 | private Cursor getWordIndex(Uri uri) {
154 | Log.d(TAG, "getWord:" + uri.toString());
155 | String rowId = uri.getLastPathSegment();
156 | return mDictionary.getIndexByRowId(rowId);
157 | }
158 |
159 | private Cursor refreshShortcut(Uri uri) {
160 | Log.d(TAG, "refreshShortcut:" + uri.toString());
161 | /* This won't be called with the current implementation, but if we include
162 | * {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} as a column in our suggestions table, we
163 | * could expect to receive refresh queries when a shortcutted suggestion is displayed in
164 | * Quick Search Box. In which case, this method will query the table for the specific
165 | * word, using the given item Uri and provide all the columns originally provided with the
166 | * suggestion query.
167 | */
168 | String rowId = uri.getLastPathSegment();
169 | String[] columns = new String[] {
170 | BaseColumns._ID,
171 | DictSQLiteDefine.COLUMN_KEY_WORD,
172 | SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
173 | SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID};
174 |
175 | return mDictionary.getWord(rowId, columns);
176 | }
177 |
178 | @Override
179 | public Uri insert(Uri uri, ContentValues values) {
180 | throw new UnsupportedOperationException();
181 | }
182 |
183 | @Override
184 | public int delete(Uri uri, String selection, String[] selectionArgs) {
185 | throw new UnsupportedOperationException();
186 | }
187 |
188 | @Override
189 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
190 | throw new UnsupportedOperationException();
191 | }
192 |
193 | @Override
194 | public String getType(Uri uri) {
195 | switch (uriMatcher.match(uri)) {
196 | case SEARCH_WORDS:
197 | return WORDS_MIME_TYPE;
198 | case GET_WORD:
199 | return DEFINITION_MIME_TYPE;
200 | case SEARCH_SUGGEST:
201 | return SearchManager.SUGGEST_MIME_TYPE;
202 | case REFRESH_SHORTCUT:
203 | return SearchManager.SHORTCUT_MIME_TYPE;
204 | default:
205 | throw new IllegalArgumentException("Unknown URI " + uri);
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/DictFormat.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict;
2 |
3 | /**
4 | * Created by hm on 15-5-20.
5 | */
6 | public class DictFormat {
7 | /**
8 | * dictionary type
9 | */
10 | public static final int STAR_DICT = 0;
11 |
12 | String name;
13 | int type;
14 | int on;
15 | String data;
16 | String mTableName;
17 |
18 | public DictFormat(String name, int type, int on, String data, String mTableName) {
19 | this.name = name;
20 | this.type = type;
21 | this.on = on;
22 | this.data = data;
23 | this.mTableName = mTableName;
24 | }
25 |
26 | public void setOn(int on) {
27 | this.on = on;
28 | }
29 |
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public String getData() {
35 | return data;
36 | }
37 |
38 | public int getType() {
39 | return type;
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | return name;
45 | }
46 |
47 | public int getOn() {
48 | return on;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/DictItem.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict;
2 |
3 | /**
4 | * Created by hm on 15-6-16.
5 | */
6 | public class DictItem {
7 | Long id;
8 | String text;
9 |
10 | public DictItem(Long id, String text) {
11 | this.id = id;
12 | this.text = text;
13 | }
14 |
15 | @Override
16 | public String toString() {
17 | return text;
18 | }
19 |
20 | public Long getId() {
21 | return id;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/DictSQLiteDatabase.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict;
2 |
3 | import android.app.SearchManager;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.database.sqlite.SQLiteDatabase;
7 | import android.database.sqlite.SQLiteQueryBuilder;
8 | import android.provider.BaseColumns;
9 |
10 | import java.util.HashMap;
11 |
12 | /**
13 | * Created by hm on 15-1-8.
14 | */
15 | public class DictSQLiteDatabase {
16 | private final SQLiteDatabase database;
17 | private static final HashMap columnMap = buildColumnMap();
18 | DictManager manager;
19 |
20 | public DictSQLiteDatabase(Context context) {
21 | DictSQLiteHelper helper = DictSQLiteHelper.getInstance(context);
22 | database = helper.getReadableDatabase();
23 | manager = DictManager.getInstance(context);
24 | }
25 |
26 | public Cursor getWord(String rowId, String[] columns){
27 | String selection = "rowid = ?";
28 | String[] selectionArgs = new String[] {rowId};
29 | return getWord(selection, selectionArgs, columns);
30 | }
31 |
32 | public Cursor getIndexByRowId(String rowId) {
33 | String mTableName = getActiveTableName();
34 | if (mTableName == null) {
35 | return null;
36 | }
37 | String selection = "rowid = ?";
38 | String[] selectionArgs = new String[] {rowId};
39 | String mIndexTable = "[" + mTableName + "]";
40 | return database.query(mIndexTable, null, selection, selectionArgs, null, null, null);
41 | }
42 |
43 | /**
44 | * PageViewerAdapter will this function
45 | * need inner join
46 | *
47 | * @param word
48 | * @return
49 | */
50 | public Cursor getIndexByWord(String word) {
51 | String mTableName = getActiveTableName();
52 | if (mTableName == null) {
53 | return null;
54 | }
55 | String mIndexTable = "[" + mTableName + "]";
56 | String mWordTable = DictSQLiteDefine.getWordFtsTable(mTableName);
57 | int len = word.length();
58 | String sql = DictSQLiteDefine.getInnerJoinSql(mIndexTable, mWordTable, len);
59 | return database.rawQuery(sql, new String[]{word});
60 | }
61 |
62 | public Cursor getWordMatches(String query, String[] columns) {
63 | String selection = DictSQLiteDefine.COLUMN_KEY_WORD + " MATCH ?";
64 | String[] selectionArgs = new String[] {"^"+query+"*"};
65 | return query(selection, selectionArgs, columns);
66 | }
67 |
68 | public Cursor getWordMatchesInLength(String word, String[] columns) {
69 | int length = word.length();
70 | String selection = DictSQLiteDefine.COLUMN_KEY_WORD + " MATCH ? AND length("
71 | + DictSQLiteDefine.COLUMN_KEY_WORD + ")=" + length;
72 | String[] selectionArgs = new String[] {"^"+word};
73 | return query(selection, selectionArgs, columns);
74 | }
75 |
76 | private Cursor query(String selection, String[] selectionArgs, String[] columns) {
77 | String mTableName = getActiveTableName();
78 | if (mTableName == null) {
79 | return null;
80 | }
81 | String table = DictSQLiteDefine.getWordFtsTable(mTableName);
82 | SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
83 | builder.setTables(table);
84 | builder.setProjectionMap(columnMap);
85 |
86 | Cursor cursor = builder.query(database,
87 | columns, selection, selectionArgs, null, null, DictSQLiteDefine.sortOrder);
88 | if (cursor == null) {
89 | return null;
90 | } else if (!cursor.moveToFirst()) {
91 | cursor.close();
92 | return null;
93 | }
94 | return cursor;
95 | }
96 |
97 | private Cursor getWord(String selection, String[] selectionArgs, String[] columns) {
98 | String mTableName = getActiveTableName();
99 | if (mTableName == null) {
100 | return null;
101 | }
102 | String table = "[" + mTableName + "]";
103 | SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
104 | builder.setTables(table);
105 | builder.setProjectionMap(columnMap);
106 |
107 | Cursor cursor = builder.query(database,
108 | columns, selection, selectionArgs, null, null, null);
109 | if (cursor == null) {
110 | return null;
111 | } else if (!cursor.moveToFirst()) {
112 | cursor.close();
113 | return null;
114 | }
115 | return cursor;
116 | }
117 |
118 | private String getActiveTableName() {
119 | int i = manager.getActiveDict();
120 | if (i < 0) {
121 | return null;
122 | } else {
123 | DictFormat format = manager.getDictFormat(i);
124 | return format.mTableName;
125 | }
126 | }
127 |
128 | private static HashMap buildColumnMap() {
129 | HashMap map = new HashMap<>();
130 | map.put(DictSQLiteDefine.COLUMN_KEY_WORD, DictSQLiteDefine.COLUMN_KEY_WORD);
131 | map.put(BaseColumns._ID, "rowid AS " + BaseColumns._ID);
132 | map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " +
133 | SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
134 | map.put(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, DictSQLiteDefine.COLUMN_KEY_WORD + " AS " +
135 | SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
136 | return map;
137 | }
138 |
139 | }
140 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/DictSQLiteDefine.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict;
2 |
3 | import android.app.SearchManager;
4 |
5 | /**
6 | * Created by hm on 15-5-4.
7 | */
8 | public class DictSQLiteDefine {
9 | /** ------------------------------------------------------------------------------------------*
10 | * ------------------------ FTS3 table defined for word -------------------------------------*
11 | *
12 | * define dictionary's word table.
13 | * this table will be created as FTS3 table in SQLiteDatabase.
14 | */
15 | public static final String COLUMN_KEY_WORD = SearchManager.SUGGEST_COLUMN_TEXT_1;
16 |
17 | /**
18 | * define word table
19 | */
20 | public static final String WORD_FTS_TABLE =
21 | "CREATE VIRTUAL TABLE %s USING fts3 (" + COLUMN_KEY_WORD + " TEXT)";
22 |
23 | public static final String sortOrder = COLUMN_KEY_WORD + " ASC"; //"ASC"
24 |
25 | public static final String FTS_PREFIX = "fts3-";
26 |
27 | /**-------------------------------------------------------------------------------------------*
28 | * ------------------------- normal table defined for word index -----------------------------*
29 | *
30 | * define dictionary's word indexing.
31 | * this table will be created as normal table in SQLiteDatabase.
32 | */
33 | public static final String COLUMN_OFFSET = "offset";
34 | public static final String COLUMN_SIZE = "size";
35 |
36 | /**
37 | * define index table
38 | */
39 | public static final String WORD_INDEX_TABLE = "CREATE TABLE %s (" +
40 | COLUMN_OFFSET + " INTEGER, " + COLUMN_SIZE + " INTEGER)";
41 |
42 | /** ------------------------------------------------------------------------------------------*
43 | * define SQLiteDatabase name and version
44 | */
45 | public static final String DATABASE_NAME = "dictionary.db";
46 | public static final int VERSION = 3;
47 |
48 | /** ------------------------------------------------------------------------------------------*
49 | * define a inner join sql
50 | */
51 | private static final String inner_join_sql = "select * from %s a inner join %s b" +
52 | " ON a.rowid = b.rowid WHERE b." + COLUMN_KEY_WORD + " MATCH ? AND length(" + COLUMN_KEY_WORD + ")=%d";
53 |
54 |
55 | public static String getCreateFTSTable(String name) {
56 | return String.format(WORD_FTS_TABLE, name);
57 | }
58 |
59 | public static String getCreateTable(String name) {
60 | return String.format(WORD_INDEX_TABLE, name);
61 | }
62 |
63 | public static String getInnerJoinSql(String mIndexTable, String mWordTable, int wordLength) {
64 | return String.format(inner_join_sql, mIndexTable, mWordTable, wordLength);
65 | }
66 |
67 | public static String getWordFtsTable(String mTableName) {
68 | return "[" + FTS_PREFIX + mTableName + "]";
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/DictSQLiteHelper.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict;
2 |
3 | import android.content.ContentValues;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.database.sqlite.SQLiteDatabase;
7 | import android.database.sqlite.SQLiteOpenHelper;
8 | import android.util.Log;
9 |
10 | import com.dict.hm.dictionary.dict.parse.IdxParser;
11 |
12 | import java.io.File;
13 | import java.util.ArrayList;
14 |
15 | /**
16 | * Created by hm on 15-5-12.
17 | * Every normal table has a corresponding fts3 table.
18 | * Define the fts3 table name to "fts3- + 'normal table name'", like: table1 ---> fts3-table1
19 | */
20 | public class DictSQLiteHelper extends SQLiteOpenHelper{
21 | private static final String TAG = "DictSQLiteHelper";
22 | private SQLiteDatabase database = null;
23 | private String wordTableName;
24 | private String indexTableName;
25 | private static DictSQLiteHelper helper;
26 |
27 | public static DictSQLiteHelper getInstance(Context context) {
28 | if (helper == null) {
29 | File externalDir = context.getExternalFilesDir(null);
30 | String databaseName;
31 | if (externalDir != null) {
32 | databaseName = externalDir.getAbsolutePath() + File.separator + DictSQLiteDefine.DATABASE_NAME;
33 | } else {
34 | databaseName = DictSQLiteDefine.DATABASE_NAME;
35 | }
36 | helper = new DictSQLiteHelper(context.getApplicationContext(), databaseName);
37 | }
38 | return helper;
39 | }
40 |
41 | public DictSQLiteHelper(Context context, String mDatabaseName) {
42 | super(context, mDatabaseName, null, DictSQLiteDefine.VERSION);
43 | }
44 |
45 | @Override
46 | public void onCreate(SQLiteDatabase db) {
47 | database = db;
48 | }
49 |
50 | @Override
51 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
52 | database = db;
53 | }
54 |
55 | public void dropTable(String table) {
56 | if (table != null) {
57 | database = getWritableDatabase();
58 | database.execSQL("DROP TABLE IF EXISTS [" + table + "]");
59 | database.execSQL("DROP TABLE IF EXISTS [" + DictSQLiteDefine.FTS_PREFIX + table + "]");
60 | }
61 | }
62 |
63 | public Cursor getTables() {
64 | database = getWritableDatabase();
65 | return database.rawQuery("SELECT * FROM sqlite_master WHERE TYPE='table'", null);
66 | }
67 |
68 | private long addWord(String word) {
69 | ContentValues values = new ContentValues();
70 | values.put(DictSQLiteDefine.COLUMN_KEY_WORD, word);
71 | return database.insert(wordTableName, null, values);
72 | }
73 |
74 | private long addWord(int offset, int size) {
75 | ContentValues values = new ContentValues();
76 | values.put(DictSQLiteDefine.COLUMN_OFFSET, offset);
77 | values.put(DictSQLiteDefine.COLUMN_SIZE, size);
78 | return database.insert(indexTableName, null, values);
79 | }
80 |
81 | private void deleteWord(String mTableName, long id) {
82 | database.delete(mTableName, "rowid = ?", new String[]{Long.toString(id)});
83 | }
84 |
85 | public void addWords(ArrayList list) {
86 | if (database == null) {
87 | return;
88 | }
89 | database.beginTransaction();
90 | long id0, id1;
91 |
92 | for (IdxParser.WordEntry entry : list) {
93 | id0 = addWord(new String(entry.word));
94 | id1 = addWord(entry.offset, entry.size);
95 | if (id0 < 0 || id1 < 0 || id0 != id1) {
96 | Log.e(TAG, "unable to add word:" + new String(entry.word).trim());
97 | if (id0 >= 0) {
98 | deleteWord(wordTableName, id0);
99 | }
100 | if (id1 >= 0) {
101 | deleteWord(indexTableName, id1);
102 | }
103 | }
104 | }
105 | database.setTransactionSuccessful();
106 | database.endTransaction();
107 | }
108 |
109 | public void createTable(String bookName) {
110 | wordTableName = "[" + DictSQLiteDefine.FTS_PREFIX + bookName + "]";
111 | indexTableName = "[" + bookName + "]";
112 | String createWordTableSQL = DictSQLiteDefine.getCreateFTSTable(wordTableName);
113 | String createIndexTableSQL = DictSQLiteDefine.getCreateTable(indexTableName);
114 | database = getWritableDatabase();
115 | database.execSQL(createWordTableSQL);
116 | database.execSQL(createIndexTableSQL);
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/parse/DictParser.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict.parse;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.File;
6 | import java.io.FileNotFoundException;
7 | import java.io.IOException;
8 | import java.io.RandomAccessFile;
9 |
10 | /**
11 | * Created by hm on 15-1-17.
12 | */
13 | public class DictParser {
14 | File dictFile;
15 | RandomAccessFile randomAccessFile;
16 |
17 | public DictParser(File dictFile) {
18 | this.dictFile = dictFile;
19 | try {
20 | randomAccessFile = new RandomAccessFile(dictFile, "r");
21 | } catch (FileNotFoundException e) {
22 | randomAccessFile = null;
23 | e.printStackTrace();
24 | }
25 | }
26 |
27 | public String getWordDefinition(int offset, int size) {
28 | try {
29 | if (randomAccessFile != null && offset <= randomAccessFile.length()) {
30 | randomAccessFile.seek(offset);
31 | byte[] bytes = new byte[size];
32 | int actuallySize = randomAccessFile.read(bytes);
33 | if (actuallySize != size) {
34 | return null;
35 | }
36 | return new String(bytes);
37 | }
38 | } catch (IOException e) {
39 | e.printStackTrace();
40 | }
41 | return null;
42 | }
43 |
44 | public void closeFile() {
45 | Log.d("RandomAccessFile", "closed");
46 | try {
47 | if (randomAccessFile != null) {
48 | randomAccessFile.close();
49 | }
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/parse/IdxParser.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict.parse;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.BufferedInputStream;
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.util.ArrayList;
11 | import java.util.zip.GZIPInputStream;
12 |
13 | /**
14 | * Created by hm on 15-1-11.
15 | */
16 | public class IdxParser {
17 | InputStream in;
18 | byte[] bytes = new byte[256];
19 |
20 | public IdxParser(File idxFile) {
21 | try {
22 | if (idxFile.getName().endsWith(".idx.gz")) {
23 | in = new GZIPInputStream(new BufferedInputStream(new FileInputStream(idxFile)));
24 | } else {
25 | in = new BufferedInputStream(new FileInputStream(idxFile));
26 | }
27 |
28 | } catch (IOException e) {
29 | e.printStackTrace();
30 | }
31 | }
32 |
33 | /**
34 | * @return 10000 WordEntries
35 | *
36 | */
37 | public ArrayList getWordEntries() {
38 | ArrayList list = new ArrayList<>(10000);
39 | WordEntry entry;
40 | int i = 0;
41 | try {
42 | if (in == null) {
43 | return null;
44 | }
45 | if (in.available() <= 0) {
46 | in.close();
47 | return null;
48 | }
49 | Log.d("loading dictionary", "" + in.available());
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 | while ((entry = getNextWordEntry()) != null && i < 10000) {
54 | list.add(entry);
55 | i++;
56 | }
57 | return list;
58 | }
59 |
60 | private WordEntry getNextWordEntry() {
61 | WordEntry entry = new WordEntry();
62 | int i = 0;
63 | int[] tmp = new int[4];
64 |
65 | try {
66 | if (in.available() <= 0) {
67 | return null;
68 | }
69 | while ((bytes[i] = (byte)in.read()) != '\0') {
70 | i++;
71 | }
72 | byte[] word = new byte[i];
73 | for (int j = 0; j < i; j++) {
74 | word[j] = bytes[j];
75 | }
76 | entry.word = word;
77 | for (i = 0; i < 4; i++) {
78 | tmp[i] = in.read();
79 | }
80 | entry.offset = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];
81 | for (i = 0; i < 4; i++) {
82 | tmp[i] = in.read();
83 | }
84 | entry.size = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];
85 | } catch (IOException e) {
86 | e.printStackTrace();
87 | }
88 | return entry;
89 | }
90 |
91 | public class WordEntry {
92 | public byte[] word;
93 | public int offset;
94 | public int size;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/dict/parse/IfoFormat.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.dict.parse;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 |
8 | /**
9 | * Created by hm on 15-1-22.
10 | */
11 | public class IfoFormat {
12 | String version;
13 | String bookName;
14 | int wordCount;
15 | int idxFileSize;
16 | int sameTypeSequence;
17 |
18 | public IfoFormat(File ifo) {
19 | if (ifo.isFile()) {
20 | getIfoFormat(ifo);
21 | } else {
22 | bookName = "The file " + ifo.getName() + " not found";
23 | }
24 | }
25 |
26 | private void getIfoFormat(File ifo) {
27 | BufferedReader reader = null;
28 | try {
29 | reader = new BufferedReader(new FileReader(ifo));
30 | String line;
31 | String name;
32 | while ((line = reader.readLine()) != null) {
33 | int index = line.indexOf('=');
34 | if (index > 0) {
35 | name = line.substring(index + 1);
36 | name = name.trim();
37 |
38 | if (line.contains("bookname")) {
39 | bookName = name;
40 | } else if (line.contains("wordcount")) {
41 | wordCount = Integer.parseInt(name);
42 | } else if (line.contains("idxfilesize")) {
43 | idxFileSize = Integer.parseInt(name);
44 | } else if (line.contains("version")) {
45 | version = name;
46 | } else if (line.contains("sametypesequence")) {
47 | setSameTypeSequence(name);
48 | }
49 | }
50 | }
51 | } catch (IOException e) {
52 | e.printStackTrace();
53 | } finally {
54 | if (reader != null) {
55 | try {
56 | reader.close();
57 | } catch (IOException e) {
58 | e.printStackTrace();
59 | }
60 | }
61 | }
62 | }
63 |
64 | /**
65 | * sameTypeSequence meaning:
66 | * 0x1 : 'm'
67 | * 0x2 : 'l'
68 | * 0x4 : 'g'
69 | * 0x8 : 't'
70 | * 0x10: 'y'
71 | * 0x20: 'W'
72 | * 0x40: 'P'
73 | * 0x80: 'X'
74 | */
75 | private void setSameTypeSequence(String name) {
76 | sameTypeSequence = 0;
77 | if (name.contains("m")) {
78 | sameTypeSequence |= 0x1;
79 | } else if (name.contains("l")) {
80 | sameTypeSequence |= 0x2;
81 | } else if (name.contains("g")) {
82 | sameTypeSequence |= 0x4;
83 | } else if (name.contains("t")) {
84 | sameTypeSequence |= 0x8;
85 | } else if (name.contains("y")) {
86 | sameTypeSequence |= 0x10;
87 | } else if (name.contains("W")) {
88 | sameTypeSequence |= 0x20;
89 | } else if (name.contains("P")) {
90 | sameTypeSequence |= 0x40;
91 | } else if (name.contains("X")) {
92 | sameTypeSequence |= 0x80;
93 | }
94 | }
95 |
96 | public String getVersion() {
97 | return version;
98 | }
99 |
100 | public String getBookName() {
101 | return bookName;
102 | }
103 |
104 | public int getWordCount() {
105 | return wordCount;
106 | }
107 |
108 | public int getIdxFileSize() {
109 | return idxFileSize;
110 | }
111 |
112 | public int getSameTypeSequence() {
113 | return sameTypeSequence;
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/lib/ScrimInsetsFrameLayout.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.dict.hm.dictionary.lib;
18 |
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 | import android.graphics.Canvas;
22 | import android.graphics.Rect;
23 | import android.graphics.drawable.Drawable;
24 | import android.support.v4.view.ViewCompat;
25 | import android.util.AttributeSet;
26 | import android.widget.FrameLayout;
27 |
28 | import com.dict.hm.dictionary.R;
29 |
30 |
31 | /**
32 | * A layout that draws something in the insets passed to {@link #fitSystemWindows(Rect)}, i.e. the area above UI chrome
33 | * (status and navigation bars, overlay action bars).
34 | */
35 | public class ScrimInsetsFrameLayout extends FrameLayout {
36 | private Drawable mInsetForeground;
37 |
38 | private Rect mInsets;
39 | private Rect mTempRect = new Rect();
40 | private OnInsetsCallback mOnInsetsCallback;
41 |
42 | public ScrimInsetsFrameLayout(Context context) {
43 | super(context);
44 | init(context, null, 0);
45 | }
46 |
47 | public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {
48 | super(context, attrs);
49 | init(context, attrs, 0);
50 | }
51 |
52 | public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
53 | super(context, attrs, defStyle);
54 | init(context, attrs, defStyle);
55 | }
56 |
57 | private void init(Context context, AttributeSet attrs, int defStyle) {
58 | final TypedArray a = context.obtainStyledAttributes(attrs,
59 | R.styleable.ScrimInsetsView, defStyle, 0);
60 | if (a == null) {
61 | return;
62 | }
63 | mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsView_mInsetForeground);
64 | a.recycle();
65 |
66 | setWillNotDraw(true);
67 | }
68 |
69 | @Override
70 | protected boolean fitSystemWindows(Rect insets) {
71 | mInsets = new Rect(insets);
72 | setWillNotDraw(mInsetForeground == null);
73 | ViewCompat.postInvalidateOnAnimation(this);
74 | if (mOnInsetsCallback != null) {
75 | mOnInsetsCallback.onInsetsChanged(insets);
76 | }
77 | return true; // consume insets
78 | }
79 |
80 | @Override
81 | public void draw(Canvas canvas) {
82 | super.draw(canvas);
83 |
84 | int width = getWidth();
85 | int height = getHeight();
86 | if (mInsets != null && mInsetForeground != null) {
87 | int sc = canvas.save();
88 | canvas.translate(getScrollX(), getScrollY());
89 |
90 | // Top
91 | mTempRect.set(0, 0, width, mInsets.top);
92 | mInsetForeground.setBounds(mTempRect);
93 | mInsetForeground.draw(canvas);
94 |
95 | // Bottom
96 | mTempRect.set(0, height - mInsets.bottom, width, height);
97 | mInsetForeground.setBounds(mTempRect);
98 | mInsetForeground.draw(canvas);
99 |
100 | // Left
101 | mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom);
102 | mInsetForeground.setBounds(mTempRect);
103 | mInsetForeground.draw(canvas);
104 |
105 | // Right
106 | mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom);
107 | mInsetForeground.setBounds(mTempRect);
108 | mInsetForeground.draw(canvas);
109 |
110 | canvas.restoreToCount(sc);
111 | }
112 | }
113 |
114 | @Override
115 | protected void onAttachedToWindow() {
116 | super.onAttachedToWindow();
117 | if (mInsetForeground != null) {
118 | mInsetForeground.setCallback(this);
119 | }
120 | }
121 |
122 | @Override
123 | protected void onDetachedFromWindow() {
124 | super.onDetachedFromWindow();
125 | if (mInsetForeground != null) {
126 | mInsetForeground.setCallback(null);
127 | }
128 | }
129 |
130 | /**
131 | * Allows the calling container to specify a callback for custom processing when insets change (i.e. when
132 | * {@link #fitSystemWindows(Rect)} is called. This is useful for setting padding on UI elements based on
133 | * UI chrome insets (e.g. a Google Map or a ListView). When using with ListView or GridView, remember to set
134 | * clipToPadding to false.
135 | */
136 | public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) {
137 | mOnInsetsCallback = onInsetsCallback;
138 | }
139 |
140 | public static interface OnInsetsCallback {
141 | public void onInsetsChanged(Rect insets);
142 | }
143 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/lib/ZBarActivity.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.lib;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.content.pm.ActivityInfo;
6 | import android.content.pm.PackageManager;
7 | import android.hardware.Camera;
8 | import android.os.Bundle;
9 | import android.os.Handler;
10 | import android.util.Log;
11 | import android.view.MotionEvent;
12 | import android.view.SurfaceHolder;
13 | import android.view.SurfaceView;
14 | import android.view.View;
15 | import android.widget.CheckBox;
16 | import android.widget.CompoundButton;
17 | import android.widget.Toast;
18 |
19 | import com.dict.hm.dictionary.R;
20 |
21 | import net.sourceforge.zbar.Config;
22 | import net.sourceforge.zbar.Image;
23 | import net.sourceforge.zbar.ImageScanner;
24 | import net.sourceforge.zbar.Symbol;
25 | import net.sourceforge.zbar.SymbolSet;
26 |
27 | import java.io.IOException;
28 | import java.util.ArrayList;
29 | import java.util.List;
30 |
31 |
32 | /**
33 | * Created by hm on 15-3-16.
34 | */
35 | public class ZBarActivity extends Activity{
36 | private static final String TAG = "ZBar";
37 | public static final String RESULT = "result";
38 | private Camera mCamera;
39 | private ImageScanner scanner;
40 |
41 | private SurfaceView mPreview;
42 | private Handler autoFocusHandler;
43 | // boolean scanned = false;
44 | boolean previewing = true;
45 | boolean isSurfaceViewDestroyed = true;
46 | boolean autoFocus;
47 | // boolean reverse;
48 | private int count = 0;
49 |
50 | static {
51 | System.loadLibrary("iconv");
52 | }
53 |
54 | @Override
55 | protected void onCreate(Bundle savedInstanceState) {
56 | super.onCreate(savedInstanceState);
57 | setContentView(R.layout.activity_camera);
58 |
59 | if (checkCameraHardware() && safeCameraOpen(0)) {
60 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
61 |
62 | autoFocus = checkCameraAutoFocus();
63 | mPreview = (SurfaceView) findViewById(R.id.camera_preview);
64 | mPreview.getHolder().addCallback(holderCallback);
65 | autoFocusHandler = new Handler();
66 | scanner = new ImageScanner();
67 | scanner.setConfig(0, Config.X_DENSITY, 3);
68 | scanner.setConfig(0, Config.Y_DENSITY, 3);
69 |
70 | // CheckBox checkBox = (CheckBox) findViewById(R.id.camera_checkbox);
71 | // checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
72 | // @Override
73 | // public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
74 | // reverse = isChecked;
75 | // }
76 | // });
77 |
78 | mPreview.setOnTouchListener(new View.OnTouchListener() {
79 | @Override
80 | public boolean onTouch(View v, MotionEvent event) {
81 | if (!previewing) {
82 | previewing = true;
83 | mCamera.setPreviewCallback(previewCallback);
84 | mCamera.startPreview();
85 | }
86 | return true;
87 | }
88 | });
89 | } else {
90 | Toast.makeText(this, "failed to open Camera", Toast.LENGTH_LONG).show();
91 | finish();
92 | }
93 | // Log.d(TAG, "onCreate");
94 | }
95 |
96 | @Override
97 | protected void onDestroy() {
98 | super.onDestroy();
99 | releaseCameraAndPreview();
100 | // Log.d(TAG, "onDestroy");
101 | }
102 |
103 | @Override
104 | protected void onStop() {
105 | super.onStop();
106 | if (previewing) {
107 | mCamera.stopPreview();
108 | }
109 | // Log.d(TAG, "onStop");
110 | }
111 |
112 | @Override
113 | protected void onStart() {
114 | super.onStart();
115 | if (previewing && !isSurfaceViewDestroyed) {
116 | mCamera.startPreview();
117 | }
118 | // Log.d(TAG, "onStart");
119 | }
120 |
121 | private boolean safeCameraOpen(int id) {
122 | boolean bOpened = false;
123 | try {
124 | releaseCameraAndPreview();
125 | mCamera = Camera.open(id);
126 | bOpened = (mCamera != null);
127 | } catch (Exception e) {
128 | e.printStackTrace();
129 | }
130 | if (!bOpened) {
131 | Log.e(TAG, "failed to open Camera");
132 | // Log.d(TAG, "Numbers " + Camera.getNumberOfCameras());
133 | }
134 | return bOpened;
135 | }
136 |
137 | private void releaseCameraAndPreview() {
138 | if (mCamera != null) {
139 | previewing = false;
140 | mCamera.setPreviewCallback(null);
141 | mCamera.release();
142 | mCamera = null;
143 | }
144 | // Log.d(TAG, "releaseCameraAndPreview");
145 | }
146 |
147 | Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
148 | @Override
149 | public void onPreviewFrame(byte[] data, Camera camera) {
150 | //every three times reverse image data once
151 | count++;
152 | if (count > 3) {
153 | reverseImageData(data);
154 | count = 0;
155 | }
156 | Camera.Parameters parameters = camera.getParameters();
157 | Camera.Size size = parameters.getPreviewSize();
158 | Image image = new Image(size.width, size.height, "Y800");
159 | image.setData(data);
160 | int result = scanner.scanImage(image);
161 | if (result != 0) {
162 | previewing = false;
163 | mCamera.setPreviewCallback(null);
164 | mCamera.stopPreview();
165 | SymbolSet symbolSet = scanner.getResults();
166 | ArrayList list = new ArrayList<>();
167 | for (Symbol symbol : symbolSet) {
168 | list.add(symbol.getData());
169 | // scanned = true;
170 | Log.v(TAG, symbol.getData());
171 | }
172 | finishAndSetResult(list);
173 | }
174 | }
175 | };
176 |
177 | Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
178 | @Override
179 | public void onAutoFocus(boolean success, Camera camera) {
180 | autoFocusHandler.post(doAutoFocus);
181 | // Log.d(TAG, "auto focus");
182 | }
183 | };
184 |
185 | private Runnable doAutoFocus = new Runnable() {
186 | @Override
187 | public void run() {
188 | if (previewing) {
189 | mCamera.autoFocus(autoFocusCallback);
190 | }
191 | }
192 | };
193 |
194 | SurfaceHolder.Callback holderCallback = new SurfaceHolder.Callback() {
195 | @Override
196 | public void surfaceCreated(SurfaceHolder holder) {
197 | try {
198 | mCamera.setPreviewDisplay(holder);
199 | } catch (IOException e) {
200 | e.printStackTrace();
201 | }
202 | isSurfaceViewDestroyed = false;
203 | // Log.d(TAG, "surfaceCreated");
204 | }
205 |
206 | @Override
207 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
208 | if (holder.getSurface() == null) {
209 | return;
210 | }
211 | mCamera.stopPreview();
212 | mCamera.setDisplayOrientation(90);
213 | mCamera.setPreviewCallback(previewCallback);
214 | mCamera.startPreview();
215 | if (autoFocus) {
216 | mCamera.autoFocus(autoFocusCallback);
217 | }
218 | // Log.d(TAG, "surfaceChanged");
219 | }
220 |
221 | @Override
222 | public void surfaceDestroyed(SurfaceHolder holder) {
223 | isSurfaceViewDestroyed = true;
224 | // Log.d(TAG, "surfaceDestroy");
225 | }
226 | };
227 |
228 | private boolean checkCameraHardware() {
229 | PackageManager manager = getPackageManager();
230 | if (manager.hasSystemFeature(PackageManager.FEATURE_CAMERA)
231 | || manager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
232 | return true;
233 | }
234 | // Log.d(TAG, "No Camera Found");
235 | return false;
236 | }
237 |
238 | private boolean checkCameraAutoFocus() {
239 | Camera.Parameters parameters = mCamera.getParameters();
240 | List modes = parameters.getSupportedFocusModes();
241 | if (modes.contains(Camera.Parameters.FOCUS_MODE_AUTO) ||
242 | modes.contains(Camera.Parameters.FOCUS_MODE_MACRO)) {
243 | return true;
244 | }
245 | return false;
246 | }
247 |
248 | private void finishAndSetResult(ArrayList resultList) {
249 | Intent intent = new Intent();
250 | intent.putStringArrayListExtra(RESULT, resultList);
251 | setResult(Activity.RESULT_OK, intent);
252 | finish();
253 | }
254 |
255 | private void reverseImageData(byte[] data) {
256 | for (int i = 0; i < data.length; i++) {
257 | // data[i] = (byte) (~data[i] & 0xff);
258 | data[i] = (byte) (255 - data[i]);
259 | }
260 | }
261 |
262 | }
263 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/paper/JsonEntry.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.paper;
2 |
3 | /**
4 | * Created by hm on 15-5-24.
5 | */
6 | public class JsonEntry {
7 | String word;
8 | long count;
9 |
10 | public JsonEntry(String word, int count) {
11 | this.word = word;
12 | this.count = count;
13 | }
14 |
15 | public String getWord() {
16 | return word;
17 | }
18 |
19 | public long getCount() {
20 | return count;
21 | }
22 |
23 | @Override
24 | public String toString() {
25 | return word;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/paper/PaperErrorCode.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.paper;
2 |
3 | /**
4 | * Created by hm on 15-6-3.
5 | */
6 | public class PaperErrorCode {
7 | public static final int ERR_GEN = -1;
8 | public static final int ERR_NET = -2;
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/paper/PaperJsonReader.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.paper;
2 |
3 | import android.util.JsonReader;
4 | import android.util.JsonWriter;
5 | import android.util.Log;
6 |
7 | import java.io.File;
8 | import java.io.FileNotFoundException;
9 | import java.io.FileReader;
10 | import java.io.FileWriter;
11 | import java.io.IOException;
12 | import java.util.ArrayList;
13 |
14 | /**
15 | * Created by hm on 15-3-25.
16 | */
17 | public class PaperJsonReader {
18 | JsonReader reader;
19 |
20 | public PaperJsonReader(File json) {
21 | try {
22 | reader = new JsonReader(new FileReader(json));
23 | } catch (FileNotFoundException e) {
24 | reader = null;
25 | e.printStackTrace();
26 | }
27 | }
28 |
29 | public void openJson() {
30 | try {
31 | reader.beginObject();
32 | } catch (IOException e) {
33 | e.printStackTrace();
34 | }
35 | }
36 |
37 | public JsonEntry getNextJsonEntry() {
38 | JsonEntry entry = null;
39 | if (reader != null) {
40 | try {
41 | if (reader.hasNext()) {
42 | entry = new JsonEntry(reader.nextName(), reader.nextInt());
43 | }
44 | } catch (IOException e) {
45 | e.printStackTrace();
46 | Log.d("PaperJsonReader", "read json error");
47 | }
48 | }
49 | return entry;
50 | }
51 |
52 | public void closeJson() {
53 | try {
54 | reader.close();
55 | reader = null;
56 | } catch (IOException e) {
57 | e.printStackTrace();
58 | }
59 | }
60 |
61 | /**
62 | * when you call endObject() at last, and you call hasNext() again, it will return true,
63 | * mark down and test it if needed.
64 | */
65 | public ArrayList readAll() {
66 | ArrayList list = new ArrayList<>();
67 | if (reader != null) {
68 | try {
69 | reader.beginObject();
70 | while (reader.hasNext()) {
71 | list.add(new JsonEntry(reader.nextName(), reader.nextInt()));
72 | }
73 | reader.endObject();
74 | } catch (IOException e) {
75 | e.printStackTrace();
76 | Log.d("PaperJsonReader", "read json error");
77 | } finally {
78 | try {
79 | reader.close();
80 | reader = null;
81 | } catch (IOException e) {
82 | e.printStackTrace();
83 | }
84 | }
85 | }
86 | return list;
87 | }
88 |
89 | }
90 |
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/paper/PaperJsonWriter.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.paper;
2 |
3 | import android.util.JsonWriter;
4 | import android.util.Log;
5 |
6 | import java.io.File;
7 | import java.io.FileWriter;
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 |
11 | /**
12 | * Created by hm on 15-6-3.
13 | */
14 | public class PaperJsonWriter {
15 | File json;
16 |
17 | public PaperJsonWriter(File json) {
18 | this.json = json;
19 | }
20 |
21 | public boolean storePaper(ArrayList sortedList) {
22 | if (json == null || json.isDirectory() || sortedList == null) {
23 | return false;
24 | }
25 | JsonWriter jsonWriter = null;
26 | try {
27 | try {
28 | json.createNewFile();
29 | } catch (IOException e) {
30 | Log.d("error", "failed to create new file");
31 | return false;
32 | }
33 | jsonWriter = new JsonWriter(new FileWriter(json));
34 | jsonWriter.beginObject();
35 | for (int i = 0; i < sortedList.size(); i++) {
36 | JsonEntry entry = sortedList.get(i);
37 | jsonWriter.name(entry.getWord())
38 | .value(entry.getCount());
39 | }
40 | jsonWriter.endObject();
41 | jsonWriter.flush();
42 | } catch (IOException e) {
43 | e.printStackTrace();
44 | } finally {
45 | try {
46 | if (jsonWriter != null) {
47 | jsonWriter.close();
48 | }
49 | } catch (IOException e) {
50 | e.printStackTrace();
51 | }
52 | }
53 | return true;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/paper/PaperParser.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.paper;
2 |
3 | import android.util.Log;
4 | import org.jsoup.Jsoup;
5 | import org.jsoup.helper.StringUtil;
6 | import org.jsoup.nodes.Document;
7 | import org.jsoup.nodes.Node;
8 | import org.jsoup.nodes.TextNode;
9 | import org.jsoup.select.NodeTraversor;
10 | import org.jsoup.select.NodeVisitor;
11 | import java.io.File;
12 | import java.io.FileNotFoundException;
13 | import java.io.IOException;
14 | import java.util.ArrayList;
15 | import java.util.Collections;
16 | import java.util.Comparator;
17 | import java.util.HashMap;
18 | import java.util.Map;
19 | import java.util.Scanner;
20 |
21 | /**
22 | * Created by hm on 15-3-3.
23 | */
24 | public class PaperParser{
25 | public static final int TXT = 0;
26 | public static final int HTML = 1;
27 | public static final int URL = 2;
28 |
29 | HashMap hashMap;
30 | File in;
31 | String url;
32 | String charset;
33 | int type;
34 | int error;
35 |
36 | public PaperParser(File in, String charset, int type) {
37 | this.in = in;
38 | this.charset = charset;
39 | this.type = type;
40 | }
41 |
42 | public PaperParser(String url) {
43 | if (url.startsWith("http://") || url.startsWith("https://")) {
44 | this.url = url;
45 | } else {
46 | this.url = "http://" + url;
47 | }
48 | this.type = URL;
49 | }
50 |
51 | public ArrayList parse() {
52 | hashMap = new HashMap<>();
53 | boolean success = false;
54 | String text;
55 | switch (type) {
56 | case TXT:
57 | success = parseText(in, charset);
58 | break;
59 | case HTML:
60 | text = parseHtml(in, charset);
61 | success = parseText(text);
62 | break;
63 | case URL:
64 | if (url == null) {
65 | success = false;
66 | } else {
67 | text = parseURL(url);
68 | success = parseText(text);
69 | }
70 | break;
71 | }
72 |
73 | if (success) {
74 | return sort(hashMap);
75 | }
76 | return null;
77 | }
78 |
79 | public int getError() {
80 | return error;
81 | }
82 |
83 | private boolean parseText(File txt, String charset) {
84 | Scanner scanner;
85 | try {
86 | scanner = new Scanner(txt, charset);
87 | scanner.useDelimiter("[^a-zA-Z]+");
88 | } catch (FileNotFoundException e) {
89 | e.printStackTrace();
90 | return false;
91 | }
92 | return parseText(scanner);
93 | }
94 |
95 | private boolean parseText(String txt) {
96 | if (txt == null) {
97 | return false;
98 | }
99 | Scanner scanner;
100 | scanner = new Scanner(txt);
101 | scanner.useDelimiter("[^a-zA-Z]+");
102 | return parseText(scanner);
103 | }
104 |
105 | private boolean parseText(Scanner scanner) {
106 | while (scanner.hasNext()) {
107 | String s = scanner.next();
108 | s = s.toLowerCase();
109 | if (hashMap.containsKey(s)) {
110 | Integer integer = hashMap.get(s);
111 | hashMap.put(s, integer + 1);
112 | } else {
113 | hashMap.put(s, 1);
114 | }
115 | }
116 | scanner.close();
117 | return true;
118 | }
119 |
120 | private String parseHtml(File html, String charset) {
121 | String text = null;
122 | try {
123 | Document doc = Jsoup.parse(html, charset);
124 | FormattingVisitor formattingVisitor = new FormattingVisitor();
125 | NodeTraversor nodeTraversor = new NodeTraversor(formattingVisitor);
126 | nodeTraversor.traverse(doc);
127 | text = formattingVisitor.toString();
128 | } catch (IOException e) {
129 | e.printStackTrace();
130 | }
131 | return text;
132 | }
133 |
134 | private String parseURL(String url) {
135 | String text;
136 | try {
137 | Document doc = Jsoup.connect(url).timeout(5000).get();
138 | Log.d("parseURL", "return parsed doc");
139 | FormattingVisitor formattingVisitor = new FormattingVisitor();
140 | NodeTraversor nodeTraversor = new NodeTraversor(formattingVisitor);
141 | nodeTraversor.traverse(doc);
142 | text = formattingVisitor.toString();
143 | } catch (IOException e) {
144 | error = PaperErrorCode.ERR_NET;
145 | e.printStackTrace();
146 | text = null;
147 | }
148 | return text;
149 | }
150 |
151 | private ArrayList sort(HashMap hashMap) {
152 | ArrayList arrayList = new ArrayList<>();
153 | for (Map.Entry entry : hashMap.entrySet()) {
154 | arrayList.add(new JsonEntry(entry.getKey(), entry.getValue()));
155 | }
156 | Collections.sort(arrayList, new Comparator() {
157 | @Override
158 | public int compare(JsonEntry lhs, JsonEntry rhs) {
159 | if (lhs.getCount() > rhs.getCount()) {
160 | return -1;
161 | } else if (lhs.getCount() < rhs.getCount()) {
162 | return 1;
163 | }
164 | return 0;
165 | }
166 | });
167 | return arrayList;
168 | }
169 |
170 | private class FormattingVisitor implements NodeVisitor {
171 | private static final int maxWidth = 80;
172 | private int width = 0;
173 | private StringBuilder builder = new StringBuilder();
174 | @Override
175 | public void head(Node node, int i) {
176 | String name = node.nodeName();
177 | if (node instanceof TextNode) {
178 | append(((TextNode) node).text());
179 | } else if (name.equals("li")) {
180 | append("\n * ");
181 | }
182 | }
183 |
184 | @Override
185 | public void tail(Node node, int i) {
186 | String name = node.nodeName();
187 | if (name.equals("br")) {
188 | append("\n");
189 | } else if (StringUtil.in(name, "p")) {
190 | append("\n\n");
191 | // } else if (name.equals("a")) {
192 | // append(String.format(" <%s>", node.absUrl("href")));
193 | }
194 | }
195 |
196 | private void append(String text) {
197 | if (text.startsWith("\n")) {
198 | width = 0;
199 | }
200 |
201 | if (text.equals(" ") && (builder.length() ==0 ||
202 | StringUtil.in(builder.substring(builder.length() -1), " ", "\n"))) {
203 | return;
204 | }
205 | if (text.length() + width > maxWidth) {
206 | String words[] = text.split("\\s+");
207 | for (int i = 0; i < words.length; i++) {
208 | String word = words[i];
209 | boolean last = i == words.length -1;
210 | if (!last) {
211 | word = word + " ";
212 | }
213 | if (word.length() + width > maxWidth) {
214 | builder.append("\n").append(word);
215 | width = word.length();
216 | } else {
217 | builder.append(word);
218 | width = word.length();
219 | }
220 | }
221 | } else {
222 | builder.append(text);
223 | width += text.length();
224 | }
225 | }
226 |
227 | @Override
228 | public String toString() {
229 | return builder.toString();
230 | }
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/BaseManagerActivity.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.app.Fragment;
4 | import android.app.FragmentTransaction;
5 | import android.os.Bundle;
6 | import android.support.design.widget.FloatingActionButton;
7 | import android.support.design.widget.Snackbar;
8 | import android.support.v7.app.ActionBar;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.support.v7.widget.Toolbar;
11 | import android.util.TypedValue;
12 | import android.view.MenuItem;
13 | import android.view.View;
14 | import android.widget.ImageView;
15 | import android.widget.ListView;
16 | import android.widget.TextView;
17 |
18 | import com.dict.hm.dictionary.R;
19 | import com.dict.hm.dictionary.ui.dialog.AlertDialogFragment;
20 | import com.dict.hm.dictionary.ui.dialog.EditDialog;
21 | import com.dict.hm.dictionary.ui.dialog.NotificationDialog;
22 | import com.dict.hm.dictionary.ui.dialog.ProgressDialog;
23 |
24 | import java.io.File;
25 |
26 | /**
27 | * Created by hm on 15-3-18.
28 | */
29 | public abstract class BaseManagerActivity extends AppCompatActivity
30 | implements FileListFragment.FileSelectedListener,
31 | AlertDialogFragment.ConfirmDialogListener,
32 | EditDialog.EditDialogListener {
33 |
34 | public static final String FRAGMENT_TAG = "top";
35 | ActionBar actionBar;
36 | Toolbar toolbar;
37 | ListView listView;
38 | TextView empty;
39 | FloatingActionButton fab;
40 | FileListFragment fileListFragment;
41 |
42 | File selectedFile;
43 | String title = null;
44 |
45 | int action = -1;
46 | static final int ADD = 0;
47 | static final int DEL = 1;
48 |
49 | String notification = null;
50 | boolean isStop;
51 |
52 | @Override
53 | protected void onCreate(Bundle savedInstanceState) {
54 | super.onCreate(savedInstanceState);
55 |
56 | setContentView(R.layout.activity_manager);
57 | toolbar = (Toolbar) findViewById(R.id.manager_toolbar);
58 | listView = (ListView) findViewById(R.id.manager_listView);
59 | empty = (TextView) findViewById(R.id.emptyView);
60 | fab = (FloatingActionButton) findViewById(R.id.manager_fab);
61 | setSupportActionBar(toolbar);
62 | listView.setEmptyView(empty);
63 |
64 | actionBar = getSupportActionBar();
65 | if (actionBar != null) {
66 | actionBar.setHomeButtonEnabled(true);
67 | actionBar.setDisplayHomeAsUpEnabled(true);
68 | actionBar.setTitle(null);
69 | }
70 | }
71 |
72 | @Override
73 | public boolean onOptionsItemSelected(MenuItem item) {
74 | switch (item.getItemId()) {
75 | case android.R.id.home:
76 | if (!dismissFragment()) {
77 | finish();
78 | }
79 | return true;
80 | default:
81 | return super.onOptionsItemSelected(item);
82 | }
83 | }
84 |
85 | @Override
86 | public void onBackPressed() {
87 | if (fileListFragment != null ) {
88 | if (fileListFragment.onBackPressed()) {
89 | return;
90 | } else {
91 | dismissFragment();
92 | return;
93 | }
94 | }
95 | if (dismissFragment()) {
96 | return;
97 | }
98 | super.onBackPressed();
99 | }
100 |
101 | @Override
102 | protected void onStop() {
103 | super.onStop();
104 | isStop = true;
105 | }
106 |
107 | @Override
108 | protected void onStart() {
109 | super.onStart();
110 | isStop = false;
111 | if (notification != null) {
112 | setNotification(notification);
113 | }
114 | }
115 |
116 | protected void showFragment(Fragment fragment) {
117 | getFragmentManager().beginTransaction()
118 | .add(R.id.manager_frame, fragment, FRAGMENT_TAG)
119 | .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
120 | .commit();
121 | listView.setVisibility(View.INVISIBLE);
122 | empty.setVisibility(View.INVISIBLE);
123 | // if (actionBar != null) {
124 | // actionBar.setHomeButtonEnabled(true);
125 | // actionBar.setDisplayHomeAsUpEnabled(true);
126 | // }
127 | }
128 |
129 | protected boolean dismissFragment() {
130 | Fragment fragment = getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
131 | if (fragment == null) {
132 | return false;
133 | }
134 | getFragmentManager().beginTransaction()
135 | .remove(fragment)
136 | .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE)
137 | .commit();
138 | listView.setVisibility(View.VISIBLE);
139 | if (listView.getAdapter().isEmpty()) {
140 | empty.setVisibility(View.VISIBLE);
141 | }
142 | // if (actionBar != null) {
143 | // actionBar.setHomeButtonEnabled(false);
144 | // actionBar.setDisplayHomeAsUpEnabled(false);
145 | // }
146 | // toolbar.setTitle(title);
147 | fileListFragment = null;
148 | return true;
149 | }
150 |
151 | /**
152 | * after onStop() call this method (fragment's commit() method) will cause IllegalStateException.
153 | *
154 | * @param text
155 | */
156 | public void setNotification(String text) {
157 | if (isStop) {
158 | notification = text;
159 | return;
160 | } else {
161 | notification = null;
162 | }
163 | NotificationDialog dialog = NotificationDialog.newInstance(text);
164 | dialog.show(getFragmentManager(), null);
165 |
166 | if (fab.getVisibility() == View.VISIBLE) {
167 | final float y = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 72,
168 | getResources().getDisplayMetrics());
169 | fab.animate().translationYBy(-y);
170 | dialog.setFab(fab, y);
171 | }
172 | }
173 |
174 | public void setProgressDialog(int progress) {
175 | if (dialog != null && dialog.isAdded()) {
176 | dialog.setProgressBar(progress);
177 | }
178 | }
179 |
180 | public void dismissProgressDialog() {
181 | if (dialog != null) {
182 | dialog.dismissAllowingStateLoss();
183 | }
184 | }
185 |
186 | public void initProgressDialog(String msg, int max) {
187 | dialog = ProgressDialog.newInstance(msg, max);
188 | dialog.show(getFragmentManager(), null);
189 | }
190 | ProgressDialog dialog;
191 |
192 | }
193 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/DialogExPreference.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.content.Context;
4 | import android.preference.DialogPreference;
5 | import android.util.AttributeSet;
6 |
7 | import com.dict.hm.dictionary.R;
8 | import com.dict.hm.dictionary.dict.DictManager;
9 |
10 | /**
11 | * Created by hm on 15-6-5.
12 | */
13 | public class DialogExPreference extends DialogPreference{
14 | String key_paper;
15 | String key_dict;
16 | public DialogExPreference(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | setDialogTitle(null);
19 | key_paper = context.getString(R.string.action_clear_paper);
20 | key_dict = context.getString(R.string.action_clear_user_dict);
21 | }
22 |
23 | @Override
24 | protected void onDialogClosed(boolean positiveResult) {
25 | if (positiveResult) {
26 | DictManager manager = DictManager.getInstance(getContext());
27 | CharSequence key = getTitle();
28 | if (key.equals(key_dict)) {
29 | manager.clearUserDict();
30 | } else {
31 | manager.clearPaper();
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/DictManagerActivity.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.drawable.BitmapDrawable;
7 | import android.graphics.drawable.Drawable;
8 | import android.net.Uri;
9 | import android.os.Build;
10 | import android.os.Bundle;
11 | import android.os.Environment;
12 | import android.os.Handler;
13 | import android.os.Message;
14 | import android.util.Log;
15 | import android.view.MenuItem;
16 | import android.view.View;
17 | import android.widget.AdapterView;
18 | import android.widget.ArrayAdapter;
19 | import android.widget.Toast;
20 |
21 | import com.dict.hm.dictionary.R;
22 | import com.dict.hm.dictionary.dict.DictFormat;
23 | import com.dict.hm.dictionary.dict.DictManager;
24 | import com.dict.hm.dictionary.async.HttpDownload;
25 | import com.dict.hm.dictionary.lib.ZBarActivity;
26 | import com.dict.hm.dictionary.dict.parse.IfoFormat;
27 | import com.dict.hm.dictionary.ui.dialog.AlertDialogFragment;
28 | import com.dict.hm.dictionary.ui.dialog.EditDialog;
29 |
30 | import java.io.File;
31 | import java.util.ArrayList;
32 |
33 | /**
34 | * Created by hm on 15-3-18.
35 | */
36 | public class DictManagerActivity extends BaseManagerActivity {
37 |
38 | public static final int ERR = -1;
39 | public static final int OK = 0;
40 | public static final int PROCESSING = 1;
41 | public static final int DELETE = 2;
42 |
43 | public static final int DECOMPRESS = 10;
44 | public static final int DECOMPRESS_ERR = -10;
45 |
46 | private ArrayAdapter adapter;
47 | private int deleteItemPosition;
48 | private DictManager manager;
49 | private int wordCount;
50 |
51 | @Override
52 | protected void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 |
55 | //manage dictionary
56 | // title = getString(R.string.title_dict);
57 | empty.setText("No Dictionary");
58 | // setTitle(title);
59 | listView.setOnItemClickListener(dictClickListener);
60 | fab.setVisibility(View.VISIBLE);
61 | fab.setOnClickListener(fabClickListener);
62 |
63 | manager = DictManager.getInstance(this);
64 | adapter = new ArrayAdapter<>(this, R.layout.textview_item, manager.getDictFormats());
65 | listView.setAdapter(adapter);
66 | }
67 |
68 | // @Override
69 | // public boolean onCreateOptionsMenu(Menu menu) {
70 | // getMenuInflater().inflate(R.menu.menu_dict_manager, menu);
71 | // return true;
72 | // }
73 |
74 | @Override
75 | public boolean onOptionsItemSelected(MenuItem item) {
76 | if (item.getItemId() == R.id.action_add_url) {
77 | EditDialog editDialog = EditDialog.newInstance("Input Url", "http://");
78 | editDialog.show(getFragmentManager(), null);
79 | return true;
80 | } else if (item.getItemId() == R.id.action_scan_qrcode) {
81 | Intent intent = new Intent(this, ZBarActivity.class);
82 | startActivityForResult(intent, 0);
83 | return true;
84 | }
85 | return super.onOptionsItemSelected(item);
86 | }
87 |
88 | @Override
89 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
90 | super.onActivityResult(requestCode, resultCode, data);
91 | if (resultCode == RESULT_OK) {
92 | ArrayList list = data.getStringArrayListExtra(ZBarActivity.RESULT);
93 | if (list.size() == 1) {
94 | onEditDialogPositiveClick(list.get(0));
95 | Log.v("result", list.get(0));
96 | } else if (list.size() > 1) {
97 | //TODO: handle more than one scanning result.
98 | onEditDialogPositiveClick(list.get(0));
99 | }
100 | }
101 | }
102 |
103 | @Override
104 | public void onEditDialogPositiveClick(String url) {
105 | String filePath = Environment.getExternalStorageDirectory().getPath();
106 | Uri uri = Uri.parse(url);
107 | new HttpDownload(this).execute(url, filePath + "/" + uri.getLastPathSegment());
108 | }
109 |
110 | @Override
111 | public void onDialogPositiveClick() {
112 | switch (action) {
113 | case ADD:
114 | if (fileListFragment != null) {
115 | DictFormat format = manager.addDictionary(selectedFile, handler);
116 | if (format != null) {
117 | dismissFragment();
118 | initProgressDialog("Loading...", wordCount);
119 | }
120 | }
121 | break;
122 | case DEL:
123 | manager.removeDictionary(deleteItemPosition, handler);
124 | break;
125 | }
126 | action = -1;
127 | adapter.notifyDataSetChanged();
128 | }
129 |
130 | @Override
131 | public void onFileSelectedListener(File file) {
132 | String name = file.getName();
133 | if (name.endsWith(".ifo")) {
134 | IfoFormat format = new IfoFormat(file);
135 | String msg = "Book Name: " + format.getBookName() + '\n'
136 | + "Version: " + format.getVersion() + '\n'
137 | + "Word Count: " + format.getWordCount();
138 | AlertDialogFragment dialogFragment = AlertDialogFragment
139 | .newInstance("Add Dictionary", msg, "Add", "Cancel");
140 | dialogFragment.show(getFragmentManager(), null);
141 | action = ADD;
142 | selectedFile = file;
143 | wordCount = format.getWordCount();
144 | } else {
145 | Toast.makeText(this, "please select .ifo file", Toast.LENGTH_LONG).show();
146 | }
147 | }
148 |
149 | @Override
150 | protected boolean dismissFragment() {
151 | fab.setVisibility(View.VISIBLE);
152 | return super.dismissFragment();
153 | }
154 |
155 | private View.OnClickListener fabClickListener = new View.OnClickListener() {
156 | @Override
157 | public void onClick(View v) {
158 | fileListFragment = new FileListFragment();
159 | showFragment(fileListFragment);
160 | fab.setVisibility(View.INVISIBLE);
161 | }
162 | };
163 |
164 | private AdapterView.OnItemClickListener dictClickListener = new AdapterView.OnItemClickListener() {
165 | @Override
166 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
167 | DictFormat dictFormat = (DictFormat) parent.getItemAtPosition(position);
168 | String ifoPath = dictFormat.getData();
169 | IfoFormat format = new IfoFormat(new File(ifoPath));
170 | String msg = "Book Name: " + format.getBookName() + '\n'
171 | + "Version: " + format.getVersion() + '\n'
172 | + "Word Count: " + format.getWordCount();
173 |
174 | AlertDialogFragment dialogFragment = AlertDialogFragment
175 | .newInstance("Remove Dictionary?", msg, "Remove", "Cancel");
176 | dialogFragment.show(getFragmentManager(), null);
177 | deleteItemPosition = position;
178 | action = DEL;
179 | }
180 | };
181 |
182 | Handler handler = new Handler(new Handler.Callback() {
183 | @Override
184 | public boolean handleMessage(Message msg) {
185 | switch (msg.what) {
186 | case ERR: // something wrong happened
187 | return true;
188 | case PROCESSING: //in inserting words to SQLiteDatabase
189 | setProgressDialog(msg.arg1);
190 | return true;
191 | case OK: //have done loading new dictionary words index to SQLiteDatabase
192 | dismissProgressDialog();
193 | setNotification(msg.obj + " has been added");
194 | return true;
195 | case DELETE: //delete SQLiteDatabase table
196 | setNotification(msg.obj + " has been removed");
197 | return true;
198 | case DECOMPRESS: //have done decompressing
199 | return true;
200 | case DECOMPRESS_ERR:
201 | return true;
202 | default:
203 | return false;
204 | }
205 | }
206 | });
207 |
208 | }
209 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/FileListFragment.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.app.Activity;
4 | import android.app.Fragment;
5 | import android.content.Context;
6 | import android.os.Bundle;
7 | import android.os.Environment;
8 | import android.util.Log;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.AdapterView;
13 | import android.widget.ArrayAdapter;
14 | import android.widget.ListView;
15 | import android.widget.TextView;
16 |
17 | import com.dict.hm.dictionary.R;
18 |
19 | import java.io.File;
20 | import java.util.ArrayList;
21 | import java.util.Collections;
22 |
23 | /**
24 | * Created by hm on 15-1-7.
25 | *
26 | * Help to load file like *.ifo, *.txt and so on.
27 | * load Dictionary *.ifo
28 | * load text file, which contains your own words, like top 5000 words.
29 | */
30 | public class FileListFragment extends Fragment {
31 | public static final String FILEPATH = "FileListFragment";
32 | private File curDir = null;
33 | private Context context;
34 | private ListView listView;
35 | private TextView emptyText;
36 | private FileSelectedListener listener;
37 |
38 | public interface FileSelectedListener {
39 | void onFileSelectedListener(File file);
40 | }
41 | @Override
42 | public void onAttach(Activity activity) {
43 | super.onAttach(activity);
44 | context = activity;
45 | try {
46 | listener = (FileSelectedListener) activity;
47 | } catch (ClassCastException e) {
48 | throw new ClassCastException(activity.toString()
49 | + " must implement interface FileSelectedListener");
50 | }
51 | }
52 |
53 | @Override
54 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
55 | View view = inflater.inflate(R.layout.fragment_file, container, false);
56 | listView = (ListView) view.findViewById(R.id.file_listView);
57 | emptyText = (TextView) view.findViewById(R.id.file_emptyView);
58 |
59 | return view;
60 | }
61 |
62 | @Override
63 | public void onActivityCreated(Bundle savedInstanceState) {
64 | Log.d("FileListFragment", "onActivityCreated");
65 | super.onCreate(savedInstanceState);
66 | emptyText.setText("No File");
67 | listView.setOnItemClickListener(fileListViewListener);
68 | listView.setEmptyView(emptyText);
69 |
70 | Bundle bundle = getArguments();
71 | File rootDir;
72 | if (bundle != null) {
73 | String path = bundle.getString(FILEPATH);
74 | rootDir = new File(path);
75 | } else {
76 | rootDir = Environment.getExternalStorageDirectory();
77 | }
78 |
79 | if (rootDir.isDirectory()) {
80 | length = rootDir.getAbsolutePath().length();
81 | onDictionarySelected(rootDir);
82 | }
83 | // getActivity().setTitle("Select File");
84 | }
85 |
86 | int length;
87 | public boolean onBackPressed() {
88 | Log.d("FileListFragment", "onBackPressed");
89 | if(curDir != null) {
90 | if (curDir.getAbsolutePath().length() > length) {
91 | onDictionarySelected(curDir.getParentFile());
92 | return true;
93 | }
94 | }
95 | return false;
96 | }
97 |
98 | AdapterView.OnItemClickListener fileListViewListener = new AdapterView.OnItemClickListener(){
99 | @Override
100 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
101 | String fileName = (String) parent.getItemAtPosition(position);
102 | File file = new File(curDir, fileName);
103 | onDictionarySelected(file);
104 | }
105 | };
106 |
107 | private void onDictionarySelected(File file) {
108 | Log.d(FILEPATH, file.getPath());
109 | if (file.isFile()) {
110 | listener.onFileSelectedListener(file);
111 | return;
112 | }
113 | String[] names = file.list();
114 | if (names == null) {
115 | return;
116 | }
117 |
118 | ArrayList list = new ArrayList<>();
119 | for (String name : names) {
120 | list.add(name);
121 | }
122 | Collections.sort(list);
123 | curDir = file;
124 | ArrayAdapter adapter = new ArrayAdapter<>(context, R.layout.textview_item, list);
125 | listView.setAdapter(adapter);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/PaperArchiveFragment.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.app.ListFragment;
4 | import android.os.Bundle;
5 | import android.support.v7.app.ActionBar;
6 | import android.view.Menu;
7 | import android.view.MenuInflater;
8 | import android.view.MenuItem;
9 | import android.view.View;
10 | import android.widget.ListView;
11 |
12 | import java.io.File;
13 | import java.util.ArrayList;
14 |
15 | import com.dict.hm.dictionary.paper.JsonEntry;
16 | import com.dict.hm.dictionary.paper.PaperWorkerHandler;
17 | import com.dict.hm.dictionary.ui.PaperManagerActivity;
18 | import com.dict.hm.dictionary.R;
19 | import com.dict.hm.dictionary.ui.adapter.PaperJsonAdapter;
20 |
21 |
22 | /**
23 | * Created by hm on 15-1-22.
24 | */
25 | public class PaperArchiveFragment extends ListFragment {
26 | public static final String JSON_PATH = "path";
27 |
28 | File jsonFile;
29 | boolean isManual;
30 |
31 | PaperJsonAdapter adapter = null;
32 | PaperWorkerHandler paperWorkerHandler = null;
33 | PaperManagerActivity activity = null;
34 | Menu menu;
35 | ActionBar actionBar;
36 |
37 | @Override
38 | public void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setHasOptionsMenu(true);
41 | }
42 |
43 | @Override
44 | public void onActivityCreated(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | setListShown(true);
47 | setListAdapter(null);
48 | // getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
49 | // drawable = getListView().getSelector();
50 |
51 | isManual = false;
52 | activity = (PaperManagerActivity) getActivity();
53 | // activity.setTitle(getActivity().getResources().getString(R.string.title_paper_archive));
54 | actionBar = activity.getSupportActionBar();
55 |
56 | Bundle bundle = getArguments();
57 | String jsonPath = bundle.getString(JSON_PATH);
58 | if (jsonPath == null) {
59 | setEmptyText("missing paper");
60 | } else {
61 | jsonFile = new File(jsonPath);
62 | paperWorkerHandler = activity.getPaperWorkerHandler();
63 | paperWorkerHandler.startJsonRead(jsonFile);
64 | }
65 | }
66 |
67 | @Override
68 | public void onDestroy() {
69 | super.onDestroy();
70 | actionBar.setHomeAsUpIndicator(null);
71 | }
72 |
73 | @Override
74 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
75 | inflater.inflate(R.menu.menu_archive, menu);
76 | menu.findItem(R.id.action_save).setVisible(false);
77 | menu.findItem(R.id.action_attachment).setVisible(false);
78 | menu.findItem(R.id.action_add_url).setVisible(false);
79 | menu.findItem(R.id.action_scan_qrcode).setVisible(false);
80 | this.menu = menu;
81 | }
82 |
83 | @Override
84 | public boolean onOptionsItemSelected(MenuItem item) {
85 | if (adapter == null) {
86 | return false;
87 | }
88 | int id = item.getItemId();
89 | switch (id) {
90 | case R.id.action_filter:
91 | /**
92 | * this will filter the word, that had been existed in UserDict.
93 | * And left the new words.
94 | */
95 | archiveALL(true);
96 | return true;
97 | case R.id.action_archive:
98 | /**
99 | * this will archive all the words into MyDict.
100 | */
101 | archiveALL(false);
102 | return true;
103 | case R.id.action_manual:
104 | startManual();
105 | return true;
106 | case R.id.action_save:
107 | archiveManual();
108 | finishManual();
109 | return true;
110 | }
111 | return super.onOptionsItemSelected(item);
112 | }
113 |
114 | /**
115 | * record the click item's position
116 | */
117 | @Override
118 | public void onListItemClick(ListView l, View v, int position, long id) {
119 | if (isManual) {
120 | adapter.removeItem(position);
121 | }
122 | }
123 |
124 | /**
125 | * start to manually select words
126 | */
127 | private void startManual() {
128 | /**
129 | * show the archiving interface
130 | */
131 | menu.findItem(R.id.action_archive).setVisible(false);
132 | menu.findItem(R.id.action_filter).setVisible(false);
133 | menu.findItem(R.id.action_manual).setVisible(false);
134 | menu.findItem(R.id.action_save).setVisible(true);
135 | isManual = true;
136 | actionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_18dp);
137 | // getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
138 | // getListView().setSelector(android.R.color.transparent);
139 | adapter.clearRemovedList();
140 | }
141 |
142 | private void finishManual() {
143 | menu.findItem(R.id.action_archive).setVisible(true);
144 | menu.findItem(R.id.action_filter).setVisible(true);
145 | menu.findItem(R.id.action_manual).setVisible(true);
146 | menu.findItem(R.id.action_save).setVisible(false);
147 |
148 | isManual = false;
149 | actionBar.setHomeAsUpIndicator(null);
150 | // getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
151 | // getListView().setSelector(drawable);
152 | }
153 |
154 | private void archiveALL(boolean filter) {
155 | ArrayList words = adapter.getList();
156 | if (filter) {
157 | paperWorkerHandler.startArchive(words, jsonFile, PaperWorkerHandler.FILTER);
158 | activity.initProgressDialog("Filter words...", 0);
159 | } else {
160 | paperWorkerHandler.startArchive(words, jsonFile, PaperWorkerHandler.ALL);
161 | activity.initProgressDialog("Archive all words", 0);
162 | }
163 | }
164 |
165 | private void archiveManual() {
166 | ArrayList words = adapter.getRemovedList();
167 | paperWorkerHandler.startArchive(words, jsonFile, PaperWorkerHandler.MANUAL);
168 | paperWorkerHandler.startJsonWrite(jsonFile, adapter.getList());
169 | activity.initProgressDialog("Archive selected words", 0);
170 | }
171 |
172 | public void setAdapter(ArrayList arrayList) {
173 | if (arrayList != null) {
174 | adapter = new PaperJsonAdapter(getActivity(), arrayList);
175 | setListAdapter(adapter);
176 | }
177 | setEmptyText("No Word");
178 | }
179 |
180 | public void onFilterComplete(ArrayList left) {
181 | adapter.setList(left);
182 | }
183 |
184 | }
185 |
186 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/PaperViewerFragment.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.app.Activity;
4 | import android.app.ListFragment;
5 | import android.os.Bundle;
6 |
7 | import com.dict.hm.dictionary.paper.PaperJsonReader;
8 | import com.dict.hm.dictionary.ui.MainActivity;
9 | import com.dict.hm.dictionary.dict.DictManager;
10 | import com.dict.hm.dictionary.dict.parse.DictParser;
11 | import com.dict.hm.dictionary.ui.adapter.PaperViewerAdapter;
12 |
13 | import java.io.File;
14 |
15 | /**
16 | * Created by hm on 15-5-28.
17 | */
18 | public class PaperViewerFragment extends ListFragment{
19 | public static final String PAPER_NAME = "paper_name";
20 | DictParser dictParser;
21 | PaperJsonReader jsonReader;
22 |
23 | @Override
24 | public void onAttach(Activity activity) {
25 | super.onAttach(activity);
26 | dictParser = DictManager.getInstance(activity).getDictParser();
27 | }
28 |
29 | @Override
30 | public void onActivityCreated(Bundle savedInstanceState) {
31 | super.onActivityCreated(savedInstanceState);
32 | Bundle bundle = getArguments();
33 | String name = bundle.getString(PAPER_NAME);
34 | if (name != null) {
35 | File json = new File(DictManager.getInstance(getActivity()).getPaperDir(), name);
36 | jsonReader = new PaperJsonReader(json);
37 | jsonReader.openJson();
38 | PaperViewerAdapter adapter = new PaperViewerAdapter(getActivity(), jsonReader, dictParser);
39 | setListAdapter(adapter);
40 | } else {
41 | setEmptyText("Missing Paper");
42 | //setListShown to true will display empty text. Or it will display the ProgressBar.
43 | setListShown(true);
44 | }
45 | }
46 |
47 | @Override
48 | public void onDestroyView() {
49 | super.onDestroyView();
50 | if (jsonReader != null) {
51 | jsonReader.closeJson();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/SettingsFragment.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.os.Bundle;
4 | import android.preference.PreferenceFragment;
5 |
6 | import com.dict.hm.dictionary.R;
7 |
8 | /**
9 | * Created by hm on 15-6-1.
10 | */
11 | public class SettingsFragment extends PreferenceFragment {
12 |
13 | @Override
14 | public void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | addPreferencesFromResource(R.xml.preferences);
17 | getActivity().setTheme(R.style.SettingsPreferenceStyle);
18 | }
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/UserDictFragment.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui;
2 |
3 | import android.app.ListFragment;
4 | import android.content.ContentResolver;
5 | import android.database.Cursor;
6 | import android.net.Uri;
7 | import android.os.Bundle;
8 | import android.view.Menu;
9 | import android.view.MenuInflater;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.widget.ListView;
13 |
14 | import com.dict.hm.dictionary.R;
15 | import com.dict.hm.dictionary.async.UserAsyncWorkerHandler;
16 | import com.dict.hm.dictionary.dict.DictContentProvider;
17 | import com.dict.hm.dictionary.dict.DictManager;
18 | import com.dict.hm.dictionary.dict.DictSQLiteDefine;
19 | import com.dict.hm.dictionary.dict.UserDictSQLiteHelper;
20 | import com.dict.hm.dictionary.dict.parse.DictParser;
21 | import com.dict.hm.dictionary.ui.adapter.UserDictAdapter;
22 | import com.dict.hm.dictionary.ui.dialog.DefinitionDialog;
23 | import com.dict.hm.dictionary.ui.dialog.SelectDialog;
24 |
25 | import java.util.ArrayList;
26 |
27 | /**
28 | * Created by hm on 15-6-9.
29 | */
30 | public class UserDictFragment extends ListFragment
31 | implements UserAsyncWorkerHandler.UserDictQueryListener,
32 | SelectDialog.OrderSelectListener {
33 | public static final int ORDER_COUNT = 0;
34 | public static final int ORDER_TIME = 1;
35 | public static final int ORDER_OTHER = 2;
36 | public static final int size = 100;
37 | private UserDictAdapter userDictAdapter = null;
38 | private UserAsyncWorkerHandler userHandler;
39 | private Uri uri;
40 | private DictManager manager;
41 |
42 | @Override
43 | public void onCreate(Bundle savedInstanceState) {
44 | super.onCreate(savedInstanceState);
45 | setHasOptionsMenu(true);
46 | }
47 |
48 | @Override
49 | public void onActivityCreated(Bundle savedInstanceState) {
50 | super.onActivityCreated(savedInstanceState);
51 |
52 | userHandler = UserAsyncWorkerHandler.getInstance(getActivity(), null);
53 | userHandler.setUserDictQueryListener(this);
54 | userHandler.startQuery(ORDER_OTHER);
55 |
56 | userDictAdapter = new UserDictAdapter(getActivity());
57 | setEmptyText(getResources().getString(R.string.action_user_dict));
58 | setListAdapter(userDictAdapter);
59 | setListShown(true);
60 |
61 | manager = DictManager.getInstance(getActivity());
62 | uri = Uri.withAppendedPath(DictContentProvider.CONTENT_URI, "word");
63 | }
64 |
65 | @Override
66 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
67 | inflater.inflate(R.menu.menu_user_dict, menu);
68 | }
69 |
70 | @Override
71 | public boolean onOptionsItemSelected(MenuItem item) {
72 | if (item.getItemId() == R.id.order) {
73 | SelectDialog dialog = new SelectDialog();
74 | dialog.setTargetFragment(this, 0);
75 | dialog.show(getFragmentManager(), null);
76 | return true;
77 | } else {
78 | return super.onOptionsItemSelected(item);
79 | }
80 | }
81 |
82 | @Override
83 | public void onListItemClick(ListView l, View v, int position, long id) {
84 | DictParser dictParser = manager.getDictParser();
85 | if (dictParser == null) {
86 | return;
87 | }
88 | String word = (String) l.getItemAtPosition(position);
89 | ContentResolver contentResolver = getActivity().getContentResolver();
90 | Cursor cursor = contentResolver.query(uri, null, null, new String[]{word}, null);
91 | if (cursor != null) {
92 | if (cursor.moveToFirst()) {
93 | int offset = cursor.getInt(cursor.getColumnIndex(DictSQLiteDefine.COLUMN_OFFSET));
94 | int size = cursor.getInt(cursor.getColumnIndex(DictSQLiteDefine.COLUMN_SIZE));
95 | String definition = dictParser.getWordDefinition(offset, size);
96 | DefinitionDialog.getDefinitionDialog(word, definition).show(getFragmentManager(), null);
97 | }
98 | cursor.close();
99 | }
100 | }
101 |
102 | /** -----------------------------------------------------------------------------------------*/
103 | //TODO: remove the lastID, sort the words by count or time. get all the words in one time.
104 | @Override
105 | public void onUserDictQueryComplete(Cursor cursor) {
106 | ArrayList words = new ArrayList<>();
107 | ArrayList counts = new ArrayList<>();
108 | ArrayList times = new ArrayList<>();
109 |
110 | if (cursor != null) {
111 | if (cursor.moveToFirst()) {
112 | int wordIndex = cursor.getColumnIndex(UserDictSQLiteHelper.COLUMN_WORD);
113 | int countIndex = cursor.getColumnIndex(UserDictSQLiteHelper.COLUMN_COUNT);
114 | int timeIndex = cursor.getColumnIndex(UserDictSQLiteHelper.COLUMN_TIME);
115 | do {
116 | words.add(cursor.getString(wordIndex));
117 | counts.add(cursor.getLong(countIndex));
118 | times.add(cursor.getString(timeIndex));
119 | } while (cursor.moveToNext());
120 | cursor.moveToLast();
121 | }
122 | cursor.close();
123 | }
124 | userDictAdapter.updateAdapterData(words, counts, times);
125 | setListShown(true);
126 | }
127 |
128 | @Override
129 | public void onOrderSelectListener(int which) {
130 | userDictAdapter.clearAdapterData();
131 | userHandler.startQuery(which);
132 | setListShown(false);
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/adapter/NavigationDrawerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.adapter;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.graphics.drawable.ClipDrawable;
6 | import android.util.TypedValue;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.BaseAdapter;
11 | import android.widget.TextView;
12 |
13 | import com.dict.hm.dictionary.R;
14 |
15 | /**
16 | * Created by hm on 15-5-28.
17 | */
18 | public class NavigationDrawerAdapter extends BaseAdapter{
19 | public static final int PERSONAL_DICT = 1;
20 | public static final int SWITCH_DICT = 2;
21 | public static final int LIST_PAPER = 3;
22 | public static final int MANAGE_DICT = 4;
23 | public static final int MANAGE_PAPER = 5;
24 | public static final int SETTINGS = 6;
25 | public static final int ABOUT = 7;
26 |
27 | private Context context;
28 | private LayoutInflater inflater;
29 | private Resources resources;
30 | private final int count = 12;
31 |
32 | public NavigationDrawerAdapter(Context context) {
33 | this.context = context;
34 | inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
35 | resources = context.getResources();
36 | }
37 |
38 | @Override
39 | public View getView(int position, View convertView, ViewGroup parent) {
40 | View view;
41 | if (convertView == null) {
42 | view = inflater.inflate(R.layout.drawer_item, parent, false);
43 | } else {
44 | view = convertView;
45 | }
46 | String string;
47 | switch (position) {
48 | case 2: //personal dict
49 | string = context.getString(R.string.drawer_personal_dict);
50 | break;
51 | case 3: //switch dict
52 | string = context.getString(R.string.drawer_dict_switch);
53 | break;
54 | case 4: //list paper
55 | string = context.getString(R.string.drawer_paper_list);
56 | break;
57 | case 6: //manage dict
58 | string = context.getString(R.string.drawer_dict_manager);
59 | break;
60 | case 7: //manage paper
61 | string = context.getString(R.string.drawer_paper_manager);
62 | break;
63 | case 9: //settings
64 | string = context.getString(R.string.drawer_settings);
65 | break;
66 | case 10: //about
67 | string = context.getString(R.string.drawer_about);
68 | break;
69 | case 0: //image
70 | case 1: //space
71 | case 5: //divider
72 | case 8: //divider
73 | case 11: //space
74 | string = null;
75 | break;
76 | default:
77 | string = "";
78 | }
79 | TextView textView = (TextView) view.findViewById(R.id.drawer_text);
80 | textView.setText(string);
81 |
82 | view.setBackground(null);
83 | if (string == null) {
84 | if (position == 0) {
85 | view.getLayoutParams().height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
86 | 152, resources.getDisplayMetrics());
87 | view.setBackgroundResource(R.drawable.ic_wallpaper);
88 | } else if (position == 1 || position == 11){
89 | view.getLayoutParams().height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
90 | 16, resources.getDisplayMetrics());
91 | } else {
92 | view.getLayoutParams().height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
93 | 16, resources.getDisplayMetrics());
94 | ClipDrawable drawable = (ClipDrawable) resources.getDrawable(R.drawable.drawer_divider);
95 | if (drawable != null) {
96 | //set title divider height to 1dp, view's height is 16dp
97 | int level = 10000 / 16;
98 | drawable.setLevel(level);
99 | }
100 | view.setBackground(drawable);
101 | }
102 | }
103 | return view;
104 | }
105 |
106 | @Override
107 | public int getItemViewType(int position) {
108 | int type;
109 | switch (position) {
110 | case 2: //personal dict
111 | type = PERSONAL_DICT;
112 | break;
113 | case 3: //switch dict
114 | type = SWITCH_DICT;
115 | break;
116 | case 4: //list paper
117 | type = LIST_PAPER;
118 | break;
119 | case 6: //manage dict
120 | type = MANAGE_DICT;
121 | break;
122 | case 7: //manage paper
123 | type = MANAGE_PAPER;
124 | break;
125 | case 9: //settings
126 | type = SETTINGS;
127 | break;
128 | case 10: //about
129 | type = ABOUT;
130 | break;
131 | // case 0: //image
132 | // case 1: //space
133 | // case 5: //divider
134 | // case 8: //divider
135 | // case 11: //space
136 | default:
137 | type = 0;
138 | }
139 | return type;
140 | }
141 |
142 | @Override
143 | public boolean isEnabled(int position) {
144 | return getItemViewType(position) > 0;
145 | }
146 |
147 | @Override
148 | public int getCount() {
149 | return count;
150 | }
151 |
152 | @Override
153 | public Object getItem(int position) {
154 | return null;
155 | }
156 |
157 | @Override
158 | public long getItemId(int position) {
159 | return position;
160 | }
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/adapter/PaperJsonAdapter.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import com.dict.hm.dictionary.R;
11 | import com.dict.hm.dictionary.paper.JsonEntry;
12 |
13 | import java.util.ArrayList;
14 |
15 |
16 | /**
17 | * Created by hm on 15-3-20.
18 | */
19 | public class PaperJsonAdapter extends BaseAdapter{
20 | LayoutInflater inflater;
21 | ArrayList list;
22 | ArrayList removedList;
23 |
24 | public PaperJsonAdapter(Context context, ArrayList list) {
25 | inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
26 | this.list= list;
27 | removedList = new ArrayList<>();
28 | }
29 |
30 | @Override
31 | public int getCount() {
32 | return list.size();
33 | }
34 |
35 | @Override
36 | public Object getItem(int position) {
37 | if (list.size() > position) {
38 | return list.get(position).getWord();
39 | } else {
40 | return null;
41 | }
42 | }
43 |
44 | @Override
45 | public long getItemId(int position) {
46 | return position;
47 | }
48 |
49 | @Override
50 | public View getView(int position, View convertView, ViewGroup parent) {
51 | View view;
52 | if (convertView != null) {
53 | view = convertView;
54 | } else {
55 | view = inflater.inflate(R.layout.paper_json_item, parent, false);
56 | // view.setBackgroundResource(R.drawable.list_selector);
57 | }
58 | TextView wordView = (TextView) view.findViewById(R.id.paper_json_word);
59 | TextView countView = (TextView) view.findViewById(R.id.paper_json_count);
60 | JsonEntry entry = list.get(position);
61 | wordView.setText(entry.getWord());
62 | countView.setText(Long.toString(entry.getCount()));
63 | return view;
64 | }
65 |
66 | public void removeItem(int position) {
67 | removedList.add(list.get(position));
68 | list.remove(position);
69 | notifyDataSetChanged();
70 | }
71 |
72 | public void setList(ArrayList list) {
73 | if (list == null) {
74 | return;
75 | }
76 | this.list = list;
77 | notifyDataSetChanged();
78 | }
79 |
80 | public ArrayList getList() {
81 | return list;
82 | }
83 |
84 | public ArrayList getRemovedList() {
85 | return removedList;
86 | }
87 |
88 | public void clearRemovedList() {
89 | removedList.clear();
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/adapter/PaperViewerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.adapter;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.net.Uri;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.BaseAdapter;
10 | import android.widget.TextView;
11 |
12 | import com.dict.hm.dictionary.async.WordAsyncQueryHandler;
13 | import com.dict.hm.dictionary.dict.DictContentProvider;
14 | import com.dict.hm.dictionary.dict.DictSQLiteDefine;
15 | import com.dict.hm.dictionary.R;
16 | import com.dict.hm.dictionary.dict.parse.DictParser;
17 | import com.dict.hm.dictionary.paper.JsonEntry;
18 | import com.dict.hm.dictionary.paper.PaperJsonReader;
19 |
20 | import java.util.ArrayList;
21 |
22 | /**
23 | * Created by hm on 15-2-12.
24 | */
25 | public class PaperViewerAdapter extends BaseAdapter
26 | implements WordAsyncQueryHandler.AsyncQueryListener{
27 | private LayoutInflater inflater;
28 | private WordAsyncQueryHandler queryWord;
29 | private DictParser parser;
30 | private PaperJsonReader reader;
31 | private ArrayList definitions;
32 | private ArrayList entries;
33 | private Uri uri;
34 |
35 | private static final String error = "can't find word in the dictionary";
36 | private static final String error1 = "occur error while reading text from .dict file";
37 |
38 | private int count = 0;
39 | private int queryPosition = 0;
40 | private static final int preloadSize = 5;
41 | private boolean hasNext = true;
42 |
43 |
44 | public PaperViewerAdapter(Context context, PaperJsonReader reader, DictParser parser) {
45 | this.parser = parser;
46 | this.reader = reader;
47 | inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
48 | definitions = new ArrayList<>();
49 | entries = new ArrayList<>();
50 | queryWord = new WordAsyncQueryHandler(context.getContentResolver(), this);
51 | uri = Uri.parse(DictContentProvider.CONTENT_URI + "/" + "word");
52 | /**
53 | * This can't set to Integer.MAX_VALUE, because the ListView which will setAdapter() to
54 | * this Adapter has a HeadView. The HeadView will be counted as one view. And I think the
55 | * max views is up to MAX_VALUE. So while I set 'size = Integer.MAX_VALUE - 1', the ListView
56 | * would show nothing.
57 | */
58 | // size = Integer.MAX_VALUE - 1;
59 | preload();
60 | }
61 |
62 | @Override
63 | public View getView(int position, View convertView, ViewGroup parent) {
64 | // long start, end;
65 | // start = SystemClock.currentThreadTimeMillis();
66 |
67 | View view;
68 | if (convertView != null) {
69 | view = convertView;
70 | } else {
71 | view = inflater.inflate(R.layout.paper_viewer_item, parent, false);
72 | }
73 | String word_text = entries.get(position).getWord();
74 | String definition_text = definitions.get(position);
75 |
76 | TextView word_TextView = (TextView) view.findViewById(R.id.paper_word);
77 | TextView definition_TextView = (TextView) view.findViewById(R.id.paper_definition);
78 | word_TextView.setText(word_text);
79 | definition_TextView.setText(definition_text);
80 |
81 | if (hasNext && (queryPosition < position + preloadSize)) {
82 | preload();
83 | }
84 | // if (position == mark) {
85 | // Animation animation = AnimationUtils
86 | // .loadAnimation(context, R.anim.abc_slide_in_bottom);
87 | // view.startAnimation(animation);
88 | // }
89 |
90 | // end = SystemClock.currentThreadTimeMillis();
91 | // Log.d("preload", "time-" + (end - start));
92 |
93 | return view;
94 | }
95 |
96 | @Override
97 | public int getCount() {
98 | return count;
99 | }
100 |
101 | @Override
102 | public Object getItem(int position) {
103 | if (position < entries.size()) {
104 | return entries.get(position).getWord();
105 | }
106 | return null;
107 | }
108 |
109 | @Override
110 | public long getItemId(int position) {
111 | return position;
112 | }
113 |
114 | @Override
115 | public void onQueryComplete(int token, Object cookie, Cursor cursor) {
116 | updateWordDefinition(token, cookie, cursor);
117 | }
118 |
119 | private void preload() {
120 | int i = 0;
121 | while (i < preloadSize) {
122 | JsonEntry entry = reader.getNextJsonEntry();
123 | if (entry != null) {
124 | queryWord.startQuery(queryPosition, null, uri, null, null,
125 | new String[]{entry.getWord()}, null);
126 | entries.add(entry);
127 | } else {
128 | hasNext = false;
129 | break;
130 | }
131 | i++;
132 | queryPosition++;
133 | }
134 | }
135 |
136 | //TODO: need to be changed
137 | private void updateWordDefinition(int token, Object cookie, Cursor cursor) {
138 | int offset = -1;
139 | int size = -1;
140 | if (cursor != null) {
141 | try {
142 | cursor.moveToFirst();
143 | if (cursor.moveToFirst()) {
144 | int i0 = cursor.getColumnIndex(DictSQLiteDefine.COLUMN_OFFSET);
145 | int i1 = cursor.getColumnIndex(DictSQLiteDefine.COLUMN_SIZE);
146 | offset = cursor.getInt(i0);
147 | size = cursor.getInt(i1);
148 | }
149 | } finally {
150 | cursor.close();
151 | }
152 | }
153 | count++;
154 | definitions.add(getDefinition(offset, size));
155 | //done preload
156 | if (token + 1 == queryPosition) {
157 | notifyDataSetChanged();
158 | }
159 | if (token < preloadSize) {
160 | notifyDataSetChanged();
161 | }
162 | }
163 |
164 | private String getDefinition(int offset, int size) {
165 | if (offset < 0 || size < 0) {
166 | return error;
167 | }
168 | String definition = null;
169 | if (parser != null) {
170 | definition = parser.getWordDefinition(offset, size);
171 | }
172 | if (definition != null) {
173 | return definition;
174 | }
175 | return error1;
176 | }
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/adapter/UserDictAdapter.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.adapter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import com.dict.hm.dictionary.R;
11 |
12 | import java.util.ArrayList;
13 |
14 | /**
15 | * Created by hm on 15-5-6.
16 | */
17 | public class UserDictAdapter extends BaseAdapter {
18 | private LayoutInflater layoutInflater;
19 | private int count;
20 | ArrayList words;
21 | ArrayList counts;
22 | ArrayList times;
23 |
24 | public UserDictAdapter(Context context) {
25 | layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
26 | words = new ArrayList<>();
27 | counts = new ArrayList<>();
28 | times = new ArrayList<>();
29 | count = 0;
30 | }
31 |
32 | public void updateAdapterData(ArrayList words, ArrayList counts,
33 | ArrayList times) {
34 | this.words.addAll(words);
35 | this.counts.addAll(counts);
36 | this.times.addAll(times);
37 | count = this.words.size();
38 | notifyDataSetChanged();
39 | }
40 |
41 | public void clearAdapterData () {
42 | words.clear();
43 | counts.clear();
44 | times.clear();
45 | count = 0;
46 | }
47 |
48 | @Override
49 | public int getCount() {
50 | return count;
51 | }
52 |
53 | @Override
54 | public Object getItem(int position) {
55 | if (position < words.size()) {
56 | return words.get(position);
57 | }
58 | return null;
59 | }
60 |
61 | @Override
62 | public long getItemId(int position) {
63 | if (position < words.size()) {
64 | return position;
65 | }
66 | return 0;
67 | }
68 |
69 | @Override
70 | public View getView(int position, View convertView, ViewGroup parent) {
71 | View view;
72 | if (convertView != null) {
73 | view = convertView;
74 | } else {
75 | view = layoutInflater.inflate(R.layout.user_word_item, parent, false);
76 | }
77 | TextView word = (TextView) view.findViewById(R.id.user_word);
78 | TextView count = (TextView) view.findViewById(R.id.user_count);
79 | TextView time = (TextView) view.findViewById(R.id.user_time);
80 | word.setText(words.get(position));
81 | count.setText(counts.get(position).toString());
82 | time.setText(times.get(position));
83 |
84 | return view;
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/AboutDialog.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.Dialog;
4 | import android.app.DialogFragment;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AlertDialog;
7 |
8 | import com.dict.hm.dictionary.R;
9 |
10 | /**
11 | * Created by hm on 15-6-1.
12 | */
13 | public class AboutDialog extends DialogFragment {
14 |
15 | @Override
16 | public Dialog onCreateDialog(Bundle savedInstanceState) {
17 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
18 | builder.setTitle(getString(R.string.about_title));
19 | builder.setMessage(getString(R.string.about_message));
20 | builder.setPositiveButton("OK", null);
21 |
22 | return builder.create();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/AlertDialogFragment.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.Activity;
4 | import android.app.Dialog;
5 | import android.app.DialogFragment;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.support.v7.app.AlertDialog;
9 |
10 | /**
11 | * Created by hm on 15-1-20.
12 | */
13 | public class AlertDialogFragment extends DialogFragment {
14 | private static final String TITLE = "title";
15 | private static final String POSITIVE = "positive";
16 | private static final String NEGATIVE = "negative";
17 | private static final String MSG = "msg";
18 | ConfirmDialogListener listener;
19 |
20 | public static AlertDialogFragment newInstance(String title, String msg,
21 | String positive , String negative) {
22 | Bundle bundle = new Bundle();
23 | bundle.putString(TITLE, title);
24 | bundle.putString(MSG, msg);
25 | bundle.putString(POSITIVE, positive);
26 | bundle.putString(NEGATIVE, negative);
27 | AlertDialogFragment dialogFragment = new AlertDialogFragment();
28 | dialogFragment.setArguments(bundle);
29 | return dialogFragment;
30 | }
31 |
32 | public interface ConfirmDialogListener {
33 | void onDialogPositiveClick();
34 | }
35 |
36 | @Override
37 | public void onAttach(Activity activity) {
38 | super.onAttach(activity);
39 | try {
40 | listener = (ConfirmDialogListener) activity;
41 | } catch (ClassCastException e) {
42 | throw new ClassCastException(activity.toString()
43 | + " must implement ConfirmDialogListener");
44 | }
45 | }
46 |
47 | @Override
48 | public Dialog onCreateDialog(Bundle savedInstanceState) {
49 | Bundle bundle = getArguments();
50 | String title = bundle.getString(TITLE);
51 | String message= bundle.getString(MSG);
52 | String positive = bundle.getString(POSITIVE);
53 | String negative = bundle.getString(NEGATIVE);
54 |
55 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
56 | builder.setTitle(title);
57 | builder.setMessage(message);
58 | builder.setPositiveButton(positive, new DialogInterface.OnClickListener() {
59 | @Override
60 | public void onClick(DialogInterface dialog, int which) {
61 | listener.onDialogPositiveClick();
62 | }
63 | });
64 | builder.setNegativeButton(negative, new DialogInterface.OnClickListener() {
65 | @Override
66 | public void onClick(DialogInterface dialog, int which) {
67 | dismiss();
68 | }
69 | });
70 |
71 | return builder.create();
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/DefinitionDialog.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.Dialog;
4 | import android.app.DialogFragment;
5 | import android.graphics.drawable.Drawable;
6 | import android.os.Bundle;
7 | import android.support.v7.app.AlertDialog;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.widget.ImageView;
11 | import android.widget.TextView;
12 |
13 | import com.dict.hm.dictionary.R;
14 | import com.dict.hm.dictionary.dict.UserDictSQLiteHelper;
15 | import com.dict.hm.dictionary.paper.JsonEntry;
16 |
17 | import java.util.ArrayList;
18 |
19 | /**
20 | * Created by hm on 15-6-10.
21 | */
22 | public class DefinitionDialog extends DialogFragment{
23 | private static final String WORD = "word";
24 | private static final String DEF = "def";
25 |
26 | public static DefinitionDialog getDefinitionDialog(String word, String def) {
27 | Bundle bundle = new Bundle();
28 | bundle.putString(WORD, word);
29 | bundle.putString(DEF, def);
30 | DefinitionDialog dialog = new DefinitionDialog();
31 | dialog.setArguments(bundle);
32 | return dialog;
33 | }
34 |
35 | @Override
36 | public Dialog onCreateDialog(Bundle savedInstanceState) {
37 | Bundle bundle = getArguments();
38 | String definition = bundle.getString(DEF);
39 | String word = bundle.getString(WORD);
40 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
41 | // builder.setTitle(word);
42 | builder.setMessage(definition);
43 | builder.setCustomTitle(createCustomTitleView(word));
44 | return builder.create();
45 | }
46 |
47 | private View createCustomTitleView(final String word) {
48 | View view = LayoutInflater.from(getActivity()).inflate(R.layout.definition_item, null);
49 | TextView textView = (TextView) view.findViewById(R.id.word);
50 | textView.setText(word);
51 | final ImageView favorite= (ImageView) view.findViewById(R.id.favorite);
52 | favorite.setOnClickListener(new View.OnClickListener() {
53 | @Override
54 | public void onClick(View v) {
55 | Drawable drawable = getResources().getDrawable(R.drawable.ic_favorite_black_48dp);
56 | favorite.setImageDrawable(drawable);
57 | //TODO: store the word to my dictionary.
58 | UserDictSQLiteHelper helper = UserDictSQLiteHelper.getInstance(getActivity());
59 | ArrayList words = new ArrayList<>();
60 | JsonEntry entry = new JsonEntry(word, 1);
61 | words.add(entry);
62 | helper.insertWords(words);
63 | }
64 | });
65 | return view;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/EditDialog.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.Activity;
4 | import android.app.Dialog;
5 | import android.app.DialogFragment;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.support.v7.app.AlertDialog;
9 | import android.view.View;
10 | import android.widget.EditText;
11 |
12 | import com.dict.hm.dictionary.R;
13 |
14 | /**
15 | * Created by hm on 14-12-21.
16 | */
17 | public class EditDialog extends DialogFragment {
18 | private static final String TEXT = "text";
19 | private static final String HINT = "hint";
20 | private static final String TITLE = "title";
21 | private static final String POSITIVE = "positive";
22 | EditDialogListener listener;
23 |
24 | public static EditDialog newInstance(String title, String hint) {
25 | EditDialog dialogFragment = new EditDialog();
26 | Bundle bundle = new Bundle();
27 | bundle.putString(HINT, hint);
28 | bundle.putString(TITLE, title);
29 | dialogFragment.setArguments(bundle);
30 |
31 | return dialogFragment;
32 | }
33 |
34 | public static EditDialog newInstance(String title, String editText, String positive) {
35 | EditDialog dialogFragment = new EditDialog();
36 | Bundle bundle = new Bundle();
37 | bundle.putString(TEXT, editText);
38 | bundle.putString(TITLE, title);
39 | bundle.putString(POSITIVE, positive);
40 | dialogFragment.setArguments(bundle);
41 |
42 | return dialogFragment;
43 | }
44 |
45 | public interface EditDialogListener{
46 | void onEditDialogPositiveClick(String url);
47 | }
48 |
49 | @Override
50 | public void onAttach(Activity activity) {
51 | super.onAttach(activity);
52 | try {
53 | listener = (EditDialogListener) activity;
54 | } catch (ClassCastException e) {
55 | throw new ClassCastException(getTargetFragment().toString()
56 | + " must implement WarningDialogListener");
57 | }
58 | }
59 |
60 | @Override
61 | public Dialog onCreateDialog(Bundle savedInstanceState) {
62 | Bundle bundle = getArguments();
63 | String editText = bundle.getString(TEXT);
64 | String title = bundle.getString(TITLE);
65 | String hint = bundle.getString(HINT);
66 | String positive = bundle.getString(POSITIVE);
67 | if (positive == null) {
68 | positive = "Ok";
69 | }
70 |
71 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
72 | builder.setTitle(title);
73 | View view = getActivity().getLayoutInflater().inflate(R.layout.edit_text, null);
74 | builder.setView(view);
75 | EditText edit = (EditText)view.findViewById(R.id.editText);
76 | edit.setHint(hint);
77 | edit.setText(editText);
78 |
79 | builder.setPositiveButton(positive, new DialogInterface.OnClickListener() {
80 | @Override
81 | public void onClick(DialogInterface dialogInterface, int i) {
82 | EditText edit = (EditText)getDialog().findViewById(R.id.editText);
83 | listener.onEditDialogPositiveClick(edit.getText().toString());
84 | }
85 | });
86 | builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
87 | @Override
88 | public void onClick(DialogInterface dialogInterface, int i) {
89 | dismiss();
90 | }
91 | });
92 |
93 | return builder.create();
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/NotificationDialog.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.Dialog;
4 | import android.app.DialogFragment;
5 | import android.content.DialogInterface;
6 | import android.os.Bundle;
7 | import android.support.v7.app.AlertDialog;
8 | import android.view.Gravity;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.view.Window;
12 | import android.view.WindowManager;
13 | import android.widget.ImageView;
14 | import android.widget.TextView;
15 |
16 | import com.dict.hm.dictionary.R;
17 |
18 | /**
19 | * Created by hm on 15-4-7.
20 | */
21 | public class NotificationDialog extends DialogFragment{
22 | private static String TXT = "text";
23 |
24 | public static NotificationDialog newInstance(String text) {
25 | NotificationDialog dialogFragment = new NotificationDialog();
26 | Bundle bundle = new Bundle();
27 | bundle.putString(TXT, text);
28 | dialogFragment.setArguments(bundle);
29 |
30 | return dialogFragment;
31 | }
32 |
33 | @Override
34 | public Dialog onCreateDialog(Bundle savedInstanceState) {
35 | Bundle bundle = getArguments();
36 | String text = bundle.getString(TXT);
37 | if (text == null || text.equals("")) {
38 | text = "HAVE A GOOD DAY!";
39 | }
40 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
41 | // builder.setMessage(text);
42 | View view = getActivity().getLayoutInflater().inflate(R.layout.snackbar, null);
43 | TextView textView =(TextView) view.findViewById(R.id.snackbar_text);
44 | textView.setText(text);
45 | builder.setView(view);
46 |
47 | Dialog dialog = builder.create();
48 | //set dialog's style
49 | Window window = dialog.getWindow();
50 | window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
51 | WindowManager.LayoutParams layoutParams = window.getAttributes();
52 | layoutParams.gravity = Gravity.BOTTOM;
53 | layoutParams.dimAmount = 0.0f;
54 | layoutParams.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
55 | window.setAttributes(layoutParams);
56 | return dialog;
57 | }
58 |
59 | @Override
60 | public void onDismiss(DialogInterface dialog) {
61 | if (fab != null) {
62 | fab.animate().translationYBy(y);
63 | }
64 | super.onDismiss(dialog);
65 | }
66 |
67 | public void setFab(ImageView fab, float y) {
68 | this.fab = fab;
69 | this.y = y;
70 | }
71 | ImageView fab = null;
72 | float y = 0;
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/ProgressDialog.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.Dialog;
5 | import android.app.DialogFragment;
6 | import android.os.Bundle;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.Window;
10 | import android.view.WindowManager;
11 | import android.widget.ProgressBar;
12 |
13 | import com.dict.hm.dictionary.R;
14 |
15 |
16 | /**
17 | * Created by hm on 15-4-8.
18 | */
19 | public class ProgressDialog extends DialogFragment{
20 | private static final String MAX = "max";
21 | private static final String MSG = "msg";
22 | ProgressBar progressBar;
23 |
24 |
25 | public static ProgressDialog newInstance(String msg, int max) {
26 | ProgressDialog dialogFragment = new ProgressDialog();
27 | Bundle bundle = new Bundle();
28 | bundle.putString(MSG, msg);
29 | bundle.putInt(MAX, max);
30 | dialogFragment.setArguments(bundle);
31 |
32 | return dialogFragment;
33 | }
34 |
35 | @Override
36 | public Dialog onCreateDialog(Bundle savedInstanceState) {
37 | Bundle bundle = getArguments();
38 | int max = bundle.getInt(MAX);
39 | String msg = bundle.getString(MSG);
40 |
41 | LayoutInflater inflater = getActivity().getLayoutInflater();
42 | View view;
43 | if (max > 0) {
44 | view = inflater.inflate(R.layout.progress, null);
45 | progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
46 | progressBar.setMax(max);
47 | } else {
48 | view = inflater.inflate(R.layout.progress_circle, null);
49 | progressBar = (ProgressBar) view.findViewById(R.id.progressBar_circle);
50 | }
51 |
52 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
53 | builder.setView(view);
54 | builder.setMessage(msg);
55 | Dialog dialog = builder.create();
56 |
57 | dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
58 | dialog.setCanceledOnTouchOutside(false);
59 | // setCancelable(false);
60 |
61 | return dialog;
62 | }
63 |
64 | @Override
65 | public void onStart() {
66 | super.onStart();
67 | //set dialog's style
68 | Window window = getDialog().getWindow();
69 | WindowManager.LayoutParams layoutParams = window.getAttributes();
70 | layoutParams.dimAmount = 0.0f;
71 | layoutParams.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
72 | window.setAttributes(layoutParams);
73 | }
74 |
75 | public void setProgressBar(int value) {
76 | progressBar.setProgress(value);
77 | if (value >= progressBar.getMax()) {
78 | dismiss();
79 | }
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/SelectDialog.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.Activity;
4 | import android.app.Dialog;
5 | import android.app.DialogFragment;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.support.v7.app.AlertDialog;
9 |
10 | import com.dict.hm.dictionary.R;
11 |
12 | /**
13 | * Created by hm on 15-6-9.
14 | */
15 | public class SelectDialog extends DialogFragment {
16 | OrderSelectListener listener;
17 |
18 | @Override
19 | public void onAttach(Activity activity) {
20 | try {
21 | listener = (OrderSelectListener) getTargetFragment();
22 | } catch (ClassCastException e) {
23 | throw new ClassCastException(getTargetFragment().toString()
24 | + " must implement OrderSelectListener");
25 | }
26 | super.onAttach(activity);
27 | }
28 |
29 | @Override
30 | public Dialog onCreateDialog(Bundle savedInstanceState) {
31 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
32 | builder.setItems(R.array.order, new DialogInterface.OnClickListener() {
33 | @Override
34 | public void onClick(DialogInterface dialog, int which) {
35 | listener.onOrderSelectListener(which);
36 | }
37 | });
38 | return builder.create();
39 | }
40 |
41 | public interface OrderSelectListener {
42 | void onOrderSelectListener(int which);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dict/hm/dictionary/ui/dialog/SwitchDictDialog.java:
--------------------------------------------------------------------------------
1 | package com.dict.hm.dictionary.ui.dialog;
2 |
3 | import android.app.Activity;
4 | import android.app.Dialog;
5 | import android.app.DialogFragment;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.support.v7.app.AlertDialog;
9 |
10 | import com.dict.hm.dictionary.R;
11 |
12 | /**
13 | * Created by hm on 15-5-28.
14 | */
15 | public class SwitchDictDialog extends DialogFragment {
16 | private SwitchDictDialogListener listener;
17 |
18 | public static final String ARRAY_DATA = "data";
19 | public static final String CHECKED = "checked";
20 |
21 | public interface SwitchDictDialogListener {
22 | void onSwitchDictClick(int which);
23 | }
24 |
25 | @Override
26 | public void onAttach(Activity activity) {
27 | super.onAttach(activity);
28 | try {
29 | listener = (SwitchDictDialogListener) activity;
30 | } catch (ClassCastException e) {
31 | throw new ClassCastException(activity.toString()
32 | + " must implement SwitchDictDialogListener");
33 | }
34 | }
35 |
36 | @Override
37 | public Dialog onCreateDialog(Bundle savedInstanceState) {
38 | Bundle bundle = getArguments();
39 | CharSequence[] items = bundle.getCharSequenceArray(ARRAY_DATA);
40 | int position = bundle.getInt(CHECKED);
41 |
42 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
43 | builder.setTitle(R.string.drawer_dict_switch);
44 | builder.setSingleChoiceItems(items, position, new DialogInterface.OnClickListener() {
45 | @Override
46 | public void onClick(DialogInterface dialog, int which) {
47 | listener.onSwitchDictClick(which);
48 | dismiss();
49 | }
50 | });
51 | return builder.create();
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_archive_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_action_archive_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_edit_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_action_edit_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_new_attachment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_action_new_attachment.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_action_qrcode.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_action_search.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_add_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_add_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_close_white_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_close_white_18dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_favorite_black_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_favorite_black_48dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_favorite_outline_black_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_favorite_outline_black_48dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_sort_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_sort_white_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_wallpaper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/app/src/main/res/drawable-xxhdpi/ic_wallpaper.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/drawer_divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/favorite_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/floating_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | -
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
-
30 |
31 |
32 |
38 |
39 |
40 | -
41 |
42 |
43 |
49 |
50 |
51 | -
52 |
53 |
54 |
60 |
61 |
62 | -
63 |
64 |
65 |
71 |
72 |
73 | -
74 |
75 |
76 |
82 |
83 |
84 | -
85 |
86 |
87 |
93 |
94 |
95 | -
96 |
97 |
98 |
104 |
105 |
106 | -
107 |
108 |
109 |
115 |
116 |
117 |
118 |
119 |
120 | -
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/list_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_camera.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
13 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
18 |
19 |
25 |
26 |
31 |
36 |
37 |
38 |
39 |
40 |
49 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_manager.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
16 |
17 |
22 |
29 |
30 |
37 |
38 |
39 |
58 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/definition_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
19 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/drawer_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/edit_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_file.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
14 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/paper_json_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/paper_viewer_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/progress_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/snackbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/textview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/user_word_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
17 |
18 |
25 |
31 |
32 |
33 |
34 |
35 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_archive.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_paper_manager.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_user_dict.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 词典
4 | 清空用户词典
5 | 词典
6 | 文章
7 | 搜索
8 | 设置
9 | 个人词典
10 | 关闭
11 | 打开
12 | 查询不到 \"%s\"
13 | 设置
14 | 词典
15 | 文章
16 | 归档
17 | 输入
18 | 关于
19 | 词典管理
20 | 切换词典
21 | 文章列表
22 | 文章管理
23 | 个人词典
24 | 设置
25 | 关于
26 | 感谢开源项目 Jsoup 和 ZBar。\n邮件支持: kenhm808@gmail.com
27 | 清空用户文章
28 | 自动过滤
29 | 新增文章时,自动过滤认识的单词
30 | 清空
31 | 取消
32 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/custom_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4db6ac
4 | #26a69a
5 | #00897b
6 | #00796b
7 | #00695c
8 | #F44336
9 | #1E000000
10 | #1E000000
11 |
12 | #8BC34A
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dictionary
5 |
6 | Settings
7 | Search
8 | Dictionary
9 | Paper
10 | Personal dictionary
11 | Clear user dictionary
12 |
13 |
14 | - %1$d result for \"%2$s\":
15 | - %1$d results for \"%2$s\":
16 |
17 |
18 |
19 | No results found for \"%s\"
20 |
21 | Enter Word
22 | setting
23 |
24 | Dictionary
25 | Paper
26 | Archive
27 |
28 | Open
29 | Close
30 |
31 | Personal dictionary
32 | Switch dictionary
33 | Paper list
34 | Manage dictionary
35 | Manage paper
36 | Settings
37 | About
38 | About
39 | Thanks to open source project Jsoup and ZBar.\nEmail support: kenhm808@gmail.com
40 | Clear user papers
41 | Auto-filter
42 | when add new paper, auto filter known words
43 | Clear
44 | Cancel
45 | auto_filter
46 |
47 |
48 | - order by count
49 | - order by time
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
38 |
39 |
42 |
45 |
46 |
50 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
11 |
12 |
13 |
14 |
19 |
20 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/searchable.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
25 |
40 |
41 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.2.3'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Sat Nov 21 15:38:42 CST 2015
16 | systemProp.https.proxyPort=8123
17 | systemProp.http.proxyHost=127.0.0.1
18 | systemProp.https.proxyHost=127.0.0.1
19 | systemProp.http.proxyPort=8123
20 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/screenshot/dict.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hm279/Dictionary/7525340d5833892993721243b9270079824a45ee/screenshot/dict.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------