diff --git a/README.md b/README.md deleted file mode 100644 index be398ea..0000000 --- a/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# Code-Reading-MiNote - -## 说明 - -此项目为“开源软件阅读标注”小组作业,小组成员为程星桦、张晋菡、张鹏展、文渤乔 - -阅读项目为[MiCode便签-小米便签的社区开源版](https://github.com/MiCode/Notes) - -具体环境部署和测试在本地进行 - - -## 协作规范 - -### 协作流程 - -每个参与者将版本库克隆到本地 - -``` -git clone https://bdgit.educoder.net/pqfx375oj/Code-Reading-MiNote.git -``` - -切换到到develop分支 - -``` -git checkout develop -``` - -在本地创建自己的分支 - -``` -git checkout -b your_branch_name (e.g. git checkout -b zjh) -``` - -进行修改后,将修改提交到自己的分支 - -``` -git add . -git commit -m "your commit message" -``` - -提交修改前,拉取develop分支最新代码,解决可能存在的冲突 - -``` -git pull origin develop -``` - -将自己的分支推送到远程仓库 - -``` -git push origin your_branch_name -``` - -**提交pull request**,将个人分支合并到develop分支;由组长进行代码审查,合并代码,并将develop的稳定版本合并到master分支。 - -### 代码阅读规范 - -协作者可将代码阅读记录通过注释的方式添加到源代码中,并标注注释的添加者; - -各协作者在doc目录中创建一个命名“xxx_notes.md"的文件,进行自己的阅读记录。 - -具体分工待定。 - - -## 参考资料(小组成员可另行补充) - -[源码以及阅读报告](https://gitee.com/mi-note-development-team/minote/tree/master/) - -[知识荟-过往讨论](https://www.learnerhub.net/#/spaces/146/search?text=%E5%B0%8F%E7%B1%B3%E4%BE%BF%E7%AD%BE&t=1729487479088&type=docs):有许多往届关于小米便签的阅读讨论帖,有很强的参考价值 \ No newline at end of file diff --git a/Untitled-3.py b/Untitled-3.py deleted file mode 100644 index f6c83cd..0000000 --- a/Untitled-3.py +++ /dev/null @@ -1,43 +0,0 @@ -import numpy as np -import scipy.stats as stats - -# 假设数据 -# 老龄化程度较高的群体数据 -high_aging_data = { - '老龄化给社会带来的主要问题': np.array([75.47, 85.85, 84.91, 53.77, 83.96]), - '政府应该采取哪些措施': np.array([62.26, 16.04, 91.51, 88.68, 51.89,0.94]), - 'life_expectancy': np.array([75, 76, 74, 77, 75]), - # 其他可能的因素... -} - -# 老龄化程度较低的群体数据 -low_aging_data = { - '老龄化给社会带来的主要问题': np.array([84.62, 69.23, 69.23, 15.38, 84.62]), - '政府应该采取哪些措施': np.array([46.15, 7.69, 69.23, 76.92, 30.77,7.69]), - 'life_expectancy': np.array([70, 71, 69, 72, 70]), - # 其他可能的因素... -} - -# 进行t检验并分析结果 -factors = ['老龄化给社会带来的主要问题', '政府应该采取哪些措施', 'life_expectancy'] -system_evaluation = {} - -for factor in factors: - high_group = high_aging_data[factor] - low_group = low_aging_data[factor] - t_stat, p_value = stats.ttest_ind(high_group, low_group) - system_evaluation[factor] = { - 't_statistic': t_stat, - 'p_value': p_value, - 'effect_size': np.abs(t_stat) * np.sqrt((len(high_group) + len(low_group)) / (len(high_group) * len(low_group))) - } - print(f"{factor}的t统计量: {t_stat}, P值: {p_value}") - if p_value < 0.05: - print(f"{factor}在两个群体之间存在显著差异。\n") - else: - print(f"{factor}在两个群体之间没有显著差异。\n") - -# 打印系统评价 -print("系统评价:") -for factor, evaluation in system_evaluation.items(): - print(f"{factor}: t统计量={evaluation['t_statistic']}, P值={evaluation['p_value']}, 影响大小={evaluation['effect_size']}") diff --git a/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/application/ExampleInstrumentedTest.java similarity index 100% rename from ExampleInstrumentedTest.java rename to app/src/androidTest/java/com/example/application/ExampleInstrumentedTest.java diff --git a/src/Notes-master/src/net/micode/notes/data/Contact.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/Contact.java similarity index 72% rename from src/Notes-master/src/net/micode/notes/data/Contact.java rename to code-reading-minote/src/Notes-master/src/net/micode/notes/data/Contact.java index 639e7ec..d97ac5d 100644 --- a/src/Notes-master/src/net/micode/notes/data/Contact.java +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/Contact.java @@ -26,12 +26,9 @@ import android.util.Log; import java.util.HashMap; public class Contact { - // 保存联系人名与电话号码映射的缓存 private static HashMap sContactCache; - // 日志标记 private static final String TAG = "Contact"; - // 查询联系人所用的选择条件 private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + " AND " + Data.RAW_CONTACT_ID + " IN " @@ -39,54 +36,36 @@ public class Contact { + " FROM phone_lookup" + " WHERE min_match = '+')"; - /** - * 根据电话号码获取联系人的姓名 - * - * @param context 应用的上下文 - * @param phoneNumber 要查询的电话号码 - * @return 联系人的姓名,如果没有找到则返回null - */ public static String getContact(Context context, String phoneNumber) { - // 初始化联系人缓存 if(sContactCache == null) { sContactCache = new HashMap(); } - // 如果缓存中已经存在该电话号码的联系人名,直接返回 if(sContactCache.containsKey(phoneNumber)) { return sContactCache.get(phoneNumber); } - // 替换选择条件中的占位符 String selection = CALLER_ID_SELECTION.replace("+", PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); - - // 执行查询 Cursor cursor = context.getContentResolver().query( Data.CONTENT_URI, - new String [] { Phone.DISPLAY_NAME }, // 查询显示名称 + new String [] { Phone.DISPLAY_NAME }, selection, new String[] { phoneNumber }, null); - // 如果查询结果不为空且移动到结果集的第一行 if (cursor != null && cursor.moveToFirst()) { try { - // 获取联系人姓名 String name = cursor.getString(0); - // 将联系人姓名缓存起来 sContactCache.put(phoneNumber, name); return name; } catch (IndexOutOfBoundsException e) { - // 捕获索引越界异常,记录错误日志 Log.e(TAG, " Cursor get string error " + e.toString()); return null; } finally { - // 关闭cursor,释放资源 cursor.close(); } } else { - // 如果没有找到匹配的联系人,记录日志 Log.d(TAG, "No contact matched with number:" + phoneNumber); return null; } diff --git a/zhushi1.txt b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/Notes.java similarity index 62% rename from zhushi1.txt rename to code-reading-minote/src/Notes-master/src/net/micode/notes/data/Notes.java index e6b5b4a..f240604 100644 --- a/zhushi1.txt +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/Notes.java @@ -1,302 +1,279 @@ -package net.micode.notes.data; - -import android.net.Uri; -public class Notes { -// 用于表示笔记应用中的各种类型、标识符以及Intent的额外数据 - public static final String AUTHORITY = "micode_notes"; - public static final String TAG = "Notes"; - - //对NoteColumns.TYPE的值进行设置时使用: - //即不同种类:笔记、文件夹和系统文件夹 - public static final int TYPE_NOTE = 0; - public static final int TYPE_FOLDER = 1; - public static final int TYPE_SYSTEM = 2; - - /** - * Following IDs are system folders' identifiers - * {@link Notes#ID_ROOT_FOLDER } is default folder - * {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder - * {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records - */ - //以下id是系统文件夹的标识符(即系统文件夹的分类) - //ID_ROOT_FOLDER:默认文件夹 - //ID_TEMPARAY_FOLDER:不属于文件夹的笔记 - //ID_CALL_RECORD_FOLDER:用于存储通话记录,以便返回 - //ID_TRASH_FOLER:垃圾回收站 - public static final int ID_ROOT_FOLDER = 0; - public static final int ID_TEMPARAY_FOLDER = -1; - public static final int ID_CALL_RECORD_FOLDER = -2; - public static final int ID_TRASH_FOLER = -3; - - - // 额外的数据键,个人理解为就是定义一些布局的ID - // 这部分就是用于设置UI界面的一些布局或小组件的id,给它定义成常量了。 - // (这样的封装性可能比较好?因为如果有部分要修改,则直接来这边修改即可,不用在activity部分一个一个修改。) - public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date"; - public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id"; - public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id"; - public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type"; - public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id"; - public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date"; - - public static final int TYPE_WIDGET_INVALIDE = -1; - public static final int TYPE_WIDGET_2X = 0; - public static final int TYPE_WIDGET_4X = 1; - - // 数据常量:里面定义了两种类型:文本便签和通话记录 - public static class DataConstants { - public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; - public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; - } - - //下面这些有类似指针的效果? 其实就是定义一堆访问笔记和文件的uri - //GPT:Android开发中常见的用于定义内容提供者(Content Provider)URI - //内容提供者是一种Android组件,它允许应用程序共享和存储数据。这里定义了一个URI来查询数据 - /** - * Uri to query all notes and folders - */ - public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); - - /** - * Uri to query data - */ - public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); - - public interface NoteColumns { - // 雨:这个接口定义了一系列静态的、最终的字符串常量,这些常量代表数据库表中的列名。 - // 作用:用于后面创建数据库的表头 - // 总的属性有:ID、父级ID、创建日期、修改日期、提醒日期、文件(标签)名(摘要?)、小部件ID、小部件类型、背景颜色ID、附件、文件中的标签数量、 - // 文件(标签)类型、最后一个同步ID、本地修改标签、移动前的ID、谷歌任务ID、代码版本信息。 - // GPT提示:在Android开发中,当使用SQLite数据库时,通常会为表中的每一列定义一个常量,以便在代码中引用。 - // 这样做的好处是,如果以后需要更改列名,只需要在一个地方修改,而不需要在整个代码中搜索和替换。 - - /** - * The unique ID for a row - *

Type: INTEGER (long)

- */ - public static final String ID = "_id"; - - /** - * The parent's id for note or folder - *

Type: INTEGER (long)

- */ - public static final String PARENT_ID = "parent_id"; - - /** - * Created data for note or folder - *

Type: INTEGER (long)

- */ - public static final String CREATED_DATE = "created_date"; - - /** - * Latest modified date - *

Type: INTEGER (long)

- */ - public static final String MODIFIED_DATE = "modified_date"; - - - /** - * Alert date - *

Type: INTEGER (long)

- */ - public static final String ALERTED_DATE = "alert_date"; - - /** - * Folder's name or text content of note - *

Type: TEXT

- */ - // 摘要? - public static final String SNIPPET = "snippet"; - - /** - * Note's widget id - *

Type: INTEGER (long)

- */ - public static final String WIDGET_ID = "widget_id"; - - /** - * Note's widget type - *

Type: INTEGER (long)

- */ - public static final String WIDGET_TYPE = "widget_type"; - - /** - * Note's background color's id - *

Type: INTEGER (long)

- */ - public static final String BG_COLOR_ID = "bg_color_id"; - - /** - * For text note, it doesn't has attachment, for multi-media - * note, it has at least one attachment - *

Type: INTEGER

- */ - public static final String HAS_ATTACHMENT = "has_attachment"; - - /** - * Folder's count of notes - *

Type: INTEGER (long)

- */ - public static final String NOTES_COUNT = "notes_count"; - - /** - * The file type: folder or note - *

Type: INTEGER

- */ - public static final String TYPE = "type"; - - /** - * The last sync id - *

Type: INTEGER (long)

- */ - //雨:在数据同步过程中,这个ID可能用来跟踪和识别每次同步操作的唯一性,确保数据的一致性。 - public static final String SYNC_ID = "sync_id"; - - /** - * Sign to indicate local modified or not - *

Type: INTEGER

- */ - public static final String LOCAL_MODIFIED = "local_modified"; - - /** - * Original parent id before moving into temporary folder - *

Type : INTEGER

- */ - public static final String ORIGIN_PARENT_ID = "origin_parent_id"; - - /** - * The gtask id - *

Type : TEXT

- */ - public static final String GTASK_ID = "gtask_id"; - - /** - * The version code - *

Type : INTEGER (long)

- */ - public static final String VERSION = "version"; - } - - public interface DataColumns { - // DataColumns的接口,这个接口包含了一系列静态常量,这些常量代表了数据库表中用于存储数据的列名。 - // 每个常量都有相应的注释,说明该列的作用和数据类型。 - - /** - * The unique ID for a row - *

Type: INTEGER (long)

- */ - public static final String ID = "_id"; - - /** - * The MIME type of the item represented by this row. - *

Type: Text

- */ - //MIME类型是一种标准,用于标识文档、文件或字节流的性质和格式。在数据库中,这个字段可以用来识别不同类型的数据,例如文本、图片、音频或视频等。 - public static final String MIME_TYPE = "mime_type"; - - /** - * The reference id to note that this data belongs to - *

Type: INTEGER (long)

- */ - //归属的Note的ID - public static final String NOTE_ID = "note_id"; - - /** - * Created data for note or folder - *

Type: INTEGER (long)

- */ - //创建日期 - public static final String CREATED_DATE = "created_date"; - - /** - * Latest modified date - *

Type: INTEGER (long)

- */ - //最近修改日期 - public static final String MODIFIED_DATE = "modified_date"; - - /** - * Data's content - *

Type: TEXT

- */ - //数据内容 - public static final String CONTENT = "content"; - - - // 以下5个是通用数据列,它们的具体意义取决于MIME类型(由MIME_TYPE字段指定)。 - // 不同的MIME类型可能需要存储不同类型的数据,这五个字段提供了灵活性,允许根据MIME类型来存储相应的数据。 - // 读后面的代码感觉这部分是在表示内容的不同状态? - /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for - * integer data type - *

Type: INTEGER

- */ - public static final String DATA1 = "data1"; - - /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for - * integer data type - *

Type: INTEGER

- */ - public static final String DATA2 = "data2"; - - /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for - * TEXT data type - *

Type: TEXT

- */ - public static final String DATA3 = "data3"; - - /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for - * TEXT data type - *

Type: TEXT

- */ - public static final String DATA4 = "data4"; - - /** - * Generic data column, the meaning is {@link #MIMETYPE} specific, used for - * TEXT data type - *

Type: TEXT

- */ - public static final String DATA5 = "data5"; - } - - //以下是文本便签的定义 - public static final class TextNote implements DataColumns { - /** - * Mode to indicate the text in check list mode or not - *

Type: Integer 1:check list mode 0: normal mode

- */ - public static final String MODE = DATA1; //模式?这个被存在DATA1列中 - - public static final int MODE_CHECK_LIST = 1; //所处检查列表模式? - - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; // 定义了MIME类型,用于标识文本标签的目录 - - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";// 定义了MIME类型,用于标识文本标签的单个项 - - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");//文本标签内容提供者(Content Provider)的URI,用于访问文本标签数据 - } - - // 通话记录的定义? - public static final class CallNote implements DataColumns { - /** - * Call date for this record - *

Type: INTEGER (long)

- */ - public static final String CALL_DATE = DATA1; //一个字符串常量,表示通话记录的日期 - - /** - * Phone number for this record - *

Type: TEXT

- */ - public static final String PHONE_NUMBER = DATA3; //意味着在数据库表中,这个电话号码信息将被存储在DATA3列中 - - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";// 同样定义了MIME类型,是用于标识通话记录的目录。 - - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";// 同样定义了MIME类型,是用于标识通话记录的单个项。 - - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");//定义了通话记录内容提供者的URI,用于访问通话记录数据。 - } -} \ No newline at end of file +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.data; + +import android.net.Uri; +public class Notes { + public static final String AUTHORITY = "micode_notes"; + public static final String TAG = "Notes"; + public static final int TYPE_NOTE = 0; + public static final int TYPE_FOLDER = 1; + public static final int TYPE_SYSTEM = 2; + + /** + * Following IDs are system folders' identifiers + * {@link Notes#ID_ROOT_FOLDER } is default folder + * {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder + * {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records + */ + public static final int ID_ROOT_FOLDER = 0; + public static final int ID_TEMPARAY_FOLDER = -1; + public static final int ID_CALL_RECORD_FOLDER = -2; + public static final int ID_TRASH_FOLER = -3; + + public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date"; + public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id"; + public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id"; + public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type"; + public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id"; + public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date"; + + public static final int TYPE_WIDGET_INVALIDE = -1; + public static final int TYPE_WIDGET_2X = 0; + public static final int TYPE_WIDGET_4X = 1; + + public static class DataConstants { + public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; + public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; + } + + /** + * Uri to query all notes and folders + */ + public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); + + /** + * Uri to query data + */ + public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); + + public interface NoteColumns { + /** + * The unique ID for a row + *

Type: INTEGER (long)

+ */ + public static final String ID = "_id"; + + /** + * The parent's id for note or folder + *

Type: INTEGER (long)

+ */ + public static final String PARENT_ID = "parent_id"; + + /** + * Created data for note or folder + *

Type: INTEGER (long)

+ */ + public static final String CREATED_DATE = "created_date"; + + /** + * Latest modified date + *

Type: INTEGER (long)

+ */ + public static final String MODIFIED_DATE = "modified_date"; + + + /** + * Alert date + *

Type: INTEGER (long)

+ */ + public static final String ALERTED_DATE = "alert_date"; + + /** + * Folder's name or text content of note + *

Type: TEXT

+ */ + public static final String SNIPPET = "snippet"; + + /** + * Note's widget id + *

Type: INTEGER (long)

+ */ + public static final String WIDGET_ID = "widget_id"; + + /** + * Note's widget type + *

Type: INTEGER (long)

+ */ + public static final String WIDGET_TYPE = "widget_type"; + + /** + * Note's background color's id + *

Type: INTEGER (long)

+ */ + public static final String BG_COLOR_ID = "bg_color_id"; + + /** + * For text note, it doesn't has attachment, for multi-media + * note, it has at least one attachment + *

Type: INTEGER

+ */ + public static final String HAS_ATTACHMENT = "has_attachment"; + + /** + * Folder's count of notes + *

Type: INTEGER (long)

+ */ + public static final String NOTES_COUNT = "notes_count"; + + /** + * The file type: folder or note + *

Type: INTEGER

+ */ + public static final String TYPE = "type"; + + /** + * The last sync id + *

Type: INTEGER (long)

+ */ + public static final String SYNC_ID = "sync_id"; + + /** + * Sign to indicate local modified or not + *

Type: INTEGER

+ */ + public static final String LOCAL_MODIFIED = "local_modified"; + + /** + * Original parent id before moving into temporary folder + *

Type : INTEGER

+ */ + public static final String ORIGIN_PARENT_ID = "origin_parent_id"; + + /** + * The gtask id + *

Type : TEXT

+ */ + public static final String GTASK_ID = "gtask_id"; + + /** + * The version code + *

Type : INTEGER (long)

+ */ + public static final String VERSION = "version"; + } + + public interface DataColumns { + /** + * The unique ID for a row + *

Type: INTEGER (long)

+ */ + public static final String ID = "_id"; + + /** + * The MIME type of the item represented by this row. + *

Type: Text

+ */ + public static final String MIME_TYPE = "mime_type"; + + /** + * The reference id to note that this data belongs to + *

Type: INTEGER (long)

+ */ + public static final String NOTE_ID = "note_id"; + + /** + * Created data for note or folder + *

Type: INTEGER (long)

+ */ + public static final String CREATED_DATE = "created_date"; + + /** + * Latest modified date + *

Type: INTEGER (long)

+ */ + public static final String MODIFIED_DATE = "modified_date"; + + /** + * Data's content + *

Type: TEXT

+ */ + public static final String CONTENT = "content"; + + + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * integer data type + *

Type: INTEGER

+ */ + public static final String DATA1 = "data1"; + + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * integer data type + *

Type: INTEGER

+ */ + public static final String DATA2 = "data2"; + + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * TEXT data type + *

Type: TEXT

+ */ + public static final String DATA3 = "data3"; + + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * TEXT data type + *

Type: TEXT

+ */ + public static final String DATA4 = "data4"; + + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific, used for + * TEXT data type + *

Type: TEXT

+ */ + public static final String DATA5 = "data5"; + } + + public static final class TextNote implements DataColumns { + /** + * Mode to indicate the text in check list mode or not + *

Type: Integer 1:check list mode 0: normal mode

+ */ + public static final String MODE = DATA1; + + public static final int MODE_CHECK_LIST = 1; + + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; + + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; + + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); + } + + public static final class CallNote implements DataColumns { + /** + * Call date for this record + *

Type: INTEGER (long)

+ */ + public static final String CALL_DATE = DATA1; + + /** + * Phone number for this record + *

Type: TEXT

+ */ + public static final String PHONE_NUMBER = DATA3; + + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; + + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; + + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); + } +} diff --git a/src/Notes-master/src/net/micode/notes/data/NotesDatabaseHelper.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/NotesDatabaseHelper.java similarity index 58% rename from src/Notes-master/src/net/micode/notes/data/NotesDatabaseHelper.java rename to code-reading-minote/src/Notes-master/src/net/micode/notes/data/NotesDatabaseHelper.java index 6057f34..ffe5d57 100644 --- a/src/Notes-master/src/net/micode/notes/data/NotesDatabaseHelper.java +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/NotesDatabaseHelper.java @@ -1,99 +1,92 @@ /* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * - * 本文件采用Apache 2.0许可协议进行许可。 - * 未经许可,您不得使用本文件。您可以在以下地址获取许可证: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * 除非适用法律另有规定或书面协议另有约定,否则根据许可证分发的软件是按"原样"提供的, - * 不附带任何明示或暗示的担保或条件。有关许可证下的特定语言条款和限制,请参阅许可证。 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -// 指定包名 package net.micode.notes.data; -// 导入必要的类 -import android.content.ContentValues; // 用于数据库内容的存储 -import android.content.Context; // 上下文类 -import android.database.sqlite.SQLiteDatabase; // SQLite数据库类 -import android.database.sqlite.SQLiteOpenHelper; // SQLite数据库帮助类 -import android.util.Log; // 日志类 +import android.content.ContentValues; +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; -// 导入自定义数据列和常量 -import net.micode.notes.data.Notes.DataColumns; // 数据列模型 -import net.micode.notes.data.Notes.DataConstants; // 数据常量 -import net.micode.notes.data.Notes.NoteColumns; // 笔记列模型 -// 创建NotesDatabaseHelper类,继承自SQLiteOpenHelper public class NotesDatabaseHelper extends SQLiteOpenHelper { - // 数据库名称 private static final String DB_NAME = "note.db"; - // 数据库版本号 private static final int DB_VERSION = 4; - // 定义表名的接口 public interface TABLE { - // 笔记表的名称 public static final String NOTE = "note"; - // 数据表的名称 public static final String DATA = "data"; } - // 日志标签 private static final String TAG = "NotesDatabaseHelper"; - // 单例实例 private static NotesDatabaseHelper mInstance; - // 创建笔记表的SQL语句 private static final String CREATE_NOTE_TABLE_SQL = "CREATE TABLE " + TABLE.NOTE + "(" + - NoteColumns.ID + " INTEGER PRIMARY KEY," + // 笔记ID,主键 - NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 父级ID - NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + // 提醒日期 - NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + // 背景颜色ID - NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建日期 - NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + // 是否有附件 - NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改日期 - NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + // 笔记数量 - NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + // 笔记摘要 - NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + // 笔记类型 - NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + // 小部件ID - NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + // 小部件类型 - NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + // 同步ID - NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + // 本地修改标志 - NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 原始父级ID - NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + // GTASK ID - NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + // 版本号 + NoteColumns.ID + " INTEGER PRIMARY KEY," + + NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + + NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + + NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + + NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + + NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + ")"; - // 创建数据表的SQL语句 private static final String CREATE_DATA_TABLE_SQL = "CREATE TABLE " + TABLE.DATA + "(" + - DataColumns.ID + " INTEGER PRIMARY KEY," + // 数据ID,主键 - DataColumns.MIME_TYPE + " TEXT NOT NULL," + // MIME类型 - DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + // 关联的笔记ID - NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建日期 - NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改日期 - DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," + // 内容 - DataColumns.DATA1 + " INTEGER," + // 数据字段1 - DataColumns.DATA2 + " INTEGER," + // 数据字段2 - DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + // 数据字段3 - DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + // 数据字段4 - DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + // 数据字段5 + DataColumns.ID + " INTEGER PRIMARY KEY," + + DataColumns.MIME_TYPE + " TEXT NOT NULL," + + DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + + NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + + NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + + DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," + + DataColumns.DATA1 + " INTEGER," + + DataColumns.DATA2 + " INTEGER," + + DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + + DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + + DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + ")"; - // 创建数据表中NOTE_ID字段的索引 private static final String CREATE_DATA_NOTE_ID_INDEX_SQL = "CREATE INDEX IF NOT EXISTS note_id_index ON " + TABLE.DATA + "(" + DataColumns.NOTE_ID + ");"; - // 当更新笔记时增加文件夹的笔记计数的触发器 + /** + * Increase folder's note count when move note to the folder + */ private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = - "CREATE TRIGGER increase_folder_count_on_update "+ + "CREATE TRIGGER increase_folder_count_on_update "+ " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + " BEGIN " + " UPDATE " + TABLE.NOTE + @@ -101,7 +94,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " END"; - // 当从文件夹中移动笔记时减少文件夹的笔记计数的触发器 + /** + * Decrease folder's note count when move note from folder + */ private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = "CREATE TRIGGER decrease_folder_count_on_update " + " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + @@ -112,7 +107,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " AND " + NoteColumns.NOTES_COUNT + ">0" + ";" + " END"; - // 当在文件夹中插入新笔记时增加文件夹的笔记计数的触发器 + /** + * Increase folder's note count when insert new note to the folder + */ private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = "CREATE TRIGGER increase_folder_count_on_insert " + " AFTER INSERT ON " + TABLE.NOTE + @@ -122,7 +119,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " END"; - // 当从文件夹中删除笔记时减少文件夹的笔记计数的触发器 + /** + * Decrease folder's note count when delete note from the folder + */ private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = "CREATE TRIGGER decrease_folder_count_on_delete " + " AFTER DELETE ON " + TABLE.NOTE + @@ -133,7 +132,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " AND " + NoteColumns.NOTES_COUNT + ">0;" + " END"; - // 在插入类型为NOTE的数据时更新笔记内容的触发器 + /** + * Update note's content when insert data with type {@link DataConstants#NOTE} + */ private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER = "CREATE TRIGGER update_note_content_on_insert " + " AFTER INSERT ON " + TABLE.DATA + @@ -144,7 +145,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " END"; - // 当类型为NOTE的数据发生变化时更新笔记内容的触发器 + /** + * Update note's content when data with {@link DataConstants#NOTE} type has changed + */ private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER = "CREATE TRIGGER update_note_content_on_update " + " AFTER UPDATE ON " + TABLE.DATA + @@ -155,7 +158,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " END"; - // 当类型为NOTE的数据被删除时更新笔记内容的触发器 + /** + * Update note's content when data with {@link DataConstants#NOTE} type has deleted + */ private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER = "CREATE TRIGGER update_note_content_on_delete " + " AFTER delete ON " + TABLE.DATA + @@ -166,7 +171,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" + " END"; - // 删除已删除笔记的所有数据的触发器 + /** + * Delete datas belong to note which has been deleted + */ private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER = "CREATE TRIGGER delete_data_on_delete " + " AFTER DELETE ON " + TABLE.NOTE + @@ -175,7 +182,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" + " END"; - // 删除已删除文件夹中的笔记的触发器 + /** + * Delete notes belong to folder which has been deleted + */ private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER = "CREATE TRIGGER folder_delete_notes_on_delete " + " AFTER DELETE ON " + TABLE.NOTE + @@ -184,7 +193,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " END"; - // 当文件夹被移动到垃圾桶时移动文件夹中的笔记的触发器 + /** + * Move notes belong to folder which has been moved to trash folder + */ private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER = "CREATE TRIGGER folder_move_notes_on_trash " + " AFTER UPDATE ON " + TABLE.NOTE + @@ -195,30 +206,26 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " END"; - // 构造函数,接受上下文参数 public NotesDatabaseHelper(Context context) { - super(context, DB_NAME, null, DB_VERSION); // 调用父类构造函数 + super(context, DB_NAME, null, DB_VERSION); } - // 创建笔记表 public void createNoteTable(SQLiteDatabase db) { - db.execSQL(CREATE_NOTE_TABLE_SQL); // 执行创建表的SQL语句 - reCreateNoteTableTriggers(db); // 重新创建触发器 - createSystemFolder(db); // 创建系统文件夹 - Log.d(TAG, "note table has been created"); // 日志输出 + db.execSQL(CREATE_NOTE_TABLE_SQL); + reCreateNoteTableTriggers(db); + createSystemFolder(db); + Log.d(TAG, "note table has been created"); } - // 重新创建笔记表的所有触发器 private void reCreateNoteTableTriggers(SQLiteDatabase db) { - db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash"); // 删除触发器 - - // 创建新的触发器 + db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); + db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); + db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete"); + db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete"); + db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert"); + db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete"); + db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash"); + db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER); @@ -228,130 +235,128 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER); } - // 创建系统文件夹 private void createSystemFolder(SQLiteDatabase db) { - ContentValues values = new ContentValues(); // 创建内容值对象 + ContentValues values = new ContentValues(); - // 为通话记录文件夹插入记录 + /** + * call record foler for call notes + */ values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); - db.insert(TABLE.NOTE, null, values); // 插入记录 + db.insert(TABLE.NOTE, null, values); - // 创建根文件夹 - values.clear(); // 清空内容值 + /** + * root folder which is default folder + */ + values.clear(); values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); - db.insert(TABLE.NOTE, null, values); // 插入记录 + db.insert(TABLE.NOTE, null, values); - // 创建临时文件夹 - values.clear(); // 清空内容值 + /** + * temporary folder which is used for moving note + */ + values.clear(); values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); - db.insert(TABLE.NOTE, null, values); // 插入记录 + db.insert(TABLE.NOTE, null, values); - // 创建垃圾桶文件夹 - values.clear(); // 清空内容值 + /** + * create trash folder + */ + values.clear(); values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); - db.insert(TABLE.NOTE, null, values); // 插入记录 + db.insert(TABLE.NOTE, null, values); } - // 创建数据表 public void createDataTable(SQLiteDatabase db) { - db.execSQL(CREATE_DATA_TABLE_SQL); // 执行创建表的SQL语句 - reCreateDataTableTriggers(db); // 重新创建触发器 - db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); // 创建索引 - Log.d(TAG, "data table has been created"); // 日志输出 + db.execSQL(CREATE_DATA_TABLE_SQL); + reCreateDataTableTriggers(db); + db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); + Log.d(TAG, "data table has been created"); } - // 重新创建数据表的所有触发器 private void reCreateDataTableTriggers(SQLiteDatabase db) { - db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update"); // 删除触发器 - db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete"); // 删除触发器 + db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); + db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update"); + db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete"); - // 创建新的触发器 db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER); } - // 获取NotesDatabaseHelper的单例实例 static synchronized NotesDatabaseHelper getInstance(Context context) { - if (mInstance == null) { // 如果实例为空,则创建新的实例 + if (mInstance == null) { mInstance = new NotesDatabaseHelper(context); } - return mInstance; // 返回实例 + return mInstance; } - // 当创建数据库时被调用 @Override public void onCreate(SQLiteDatabase db) { - createNoteTable(db); // 创建笔记表 - createDataTable(db); // 创建数据表 + createNoteTable(db); + createDataTable(db); } - // 当升级数据库时被调用 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - boolean reCreateTriggers = false; // 重创建触发器的标志 - boolean skipV2 = false; // 跳过V2的标志 + boolean reCreateTriggers = false; + boolean skipV2 = false; - if (oldVersion == 1) { // 如果旧版本是1 - upgradeToV2(db); // 升级到V2 - skipV2 = true; // 跳过V2的标志设为true - oldVersion++; // 增加版本号 + if (oldVersion == 1) { + upgradeToV2(db); + skipV2 = true; // this upgrade including the upgrade from v2 to v3 + oldVersion++; } - if (oldVersion == 2 && !skipV2) { // 如果旧版本是2且没有跳过 - upgradeToV3(db); // 升级到V3 - reCreateTriggers = true; // 设置重创建触发器的标志为true - oldVersion++; // 增加版本号 + if (oldVersion == 2 && !skipV2) { + upgradeToV3(db); + reCreateTriggers = true; + oldVersion++; } - if (oldVersion == 3) { // 如果旧版本是3 - upgradeToV4(db); // 升级到V4 - oldVersion++; // 增加版本号 + if (oldVersion == 3) { + upgradeToV4(db); + oldVersion++; } - if (reCreateTriggers) { // 如果需要重创建触发器 - reCreateNoteTableTriggers(db); // 重新创建笔记表的触发器 - reCreateDataTableTriggers(db); // 重新创建数据表的触发器 + if (reCreateTriggers) { + reCreateNoteTableTriggers(db); + reCreateDataTableTriggers(db); } - if (oldVersion != newVersion) { // 如果版本不一致,则抛出异常 + if (oldVersion != newVersion) { throw new IllegalStateException("Upgrade notes database to version " + newVersion - + " fails"); + + "fails"); } } - // 升级到V2 private void upgradeToV2(SQLiteDatabase db) { - db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); // 删除笔记表 - db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); // 删除数据表 - createNoteTable(db); // 创建笔记表 - createDataTable(db); // 创建数据表 + db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); + db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); + createNoteTable(db); + createDataTable(db); } - // 升级到V3 private void upgradeToV3(SQLiteDatabase db) { - // 删除未使用的触发器 + // drop unused triggers db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete"); db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update"); - // 为笔记添加一个新的字符ID列 + // add a column for gtask id db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''"); - // 添加一个垃圾桶系统文件夹 + // add a trash system folder ContentValues values = new ContentValues(); values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); - db.insert(TABLE.NOTE, null, values); // 插入记录 + db.insert(TABLE.NOTE, null, values); } - // 升级到V4 private void upgradeToV4(SQLiteDatabase db) { db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION - + " INTEGER NOT NULL DEFAULT 0"); // 为笔记表添加版本列 + + " INTEGER NOT NULL DEFAULT 0"); } } diff --git a/src/Notes-master/src/net/micode/notes/data/NotesProvider.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/NotesProvider.java similarity index 57% rename from src/Notes-master/src/net/micode/notes/data/NotesProvider.java rename to code-reading-minote/src/Notes-master/src/net/micode/notes/data/NotesProvider.java index 23a981f..edb0a60 100644 --- a/src/Notes-master/src/net/micode/notes/data/NotesProvider.java +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/data/NotesProvider.java @@ -16,7 +16,7 @@ package net.micode.notes.data; -// 导入需要的Android和本地类 + import android.app.SearchManager; import android.content.ContentProvider; import android.content.ContentUris; @@ -34,317 +34,271 @@ import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.NotesDatabaseHelper.TABLE; -/** - * NotesProvider 类继承自 ContentProvider, - * 负责与外部交互以进行笔记数据的增删改查操作。 - */ + public class NotesProvider extends ContentProvider { - // UriMatcher,用于匹配不同的URI请求 private static final UriMatcher mMatcher; - // 数据库助手实例 private NotesDatabaseHelper mHelper; - // 日志标签 private static final String TAG = "NotesProvider"; - // 定义URI常量 - private static final int URI_NOTE = 1; // 笔记 URI - private static final int URI_NOTE_ITEM = 2; // 单个笔记 URI - private static final int URI_DATA = 3; // 数据 URI - private static final int URI_DATA_ITEM = 4; // 单个数据 URI + private static final int URI_NOTE = 1; + private static final int URI_NOTE_ITEM = 2; + private static final int URI_DATA = 3; + private static final int URI_DATA_ITEM = 4; - private static final int URI_SEARCH = 5; // 搜索 URI - private static final int URI_SEARCH_SUGGEST = 6; // 搜索建议 URI + private static final int URI_SEARCH = 5; + private static final int URI_SEARCH_SUGGEST = 6; - // 静态代码块,初始化 URI 匹配器并添加各种 URI 匹配规则 static { mMatcher = new UriMatcher(UriMatcher.NO_MATCH); - mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); // 笔记的 URI - mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); // 单个笔记的 URI - mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); // 数据的 URI - mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM); // 单个数据的 URI - mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH); // 搜索 URI - mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST); // 搜索建议 URI - mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST); // 带参数的搜索建议 URI + mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); + mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); + mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); + mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM); + mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH); + mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST); + mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST); } /** - * 在搜索结果中,x'0A' 代表换行符。为了更好地展示信息, - * 我们将搜索结果中的标题和内容进行修剪以去除换行符和空格。 + * x'0A' represents the '\n' character in sqlite. For title and content in the search result, + * we will trim '\n' and white space in order to show more information. */ - private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," // 笔记 ID - + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," // 笔记 ID 作为意图额外数据 - + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," // 修剪后的内容作为建议文本1 - + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," // 修剪后的内容作为建议文本2 - + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," // 搜索结果图标 - + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," // 意图行为 - + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; // 笔记内容类型 + private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," + + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," + + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," + + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; - // 搜索笔记的 SQL 查询语句 private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION - + " FROM " + TABLE.NOTE // 查询的表为笔记表 - + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" // 根据内容片段进行模糊匹配 - + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER // 排除回收站的内容 - + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; // 仅匹配笔记类型 + + " FROM " + TABLE.NOTE + + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" + + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; @Override public boolean onCreate() { - // 初始化数据库助手 mHelper = NotesDatabaseHelper.getInstance(getContext()); - return true; // 创建成功 + return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - // 查询方法,处理不同的URI请求并返回结果的Cursor Cursor c = null; - SQLiteDatabase db = mHelper.getReadableDatabase(); // 获取可读数据库 - String id = null; // 用于存储ID - - switch (mMatcher.match(uri)) { // 根据URI匹配不同的查询类型 + SQLiteDatabase db = mHelper.getReadableDatabase(); + String id = null; + switch (mMatcher.match(uri)) { case URI_NOTE: - // 查询所有笔记 - c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, sortOrder); + c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, + sortOrder); break; case URI_NOTE_ITEM: - // 查询单个笔记 - id = uri.getPathSegments().get(1); // 从URI中获取笔记ID + id = uri.getPathSegments().get(1); c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs, null, null, sortOrder); break; case URI_DATA: - // 查询所有数据 - c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null, sortOrder); + c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null, + sortOrder); break; case URI_DATA_ITEM: - // 查询单个数据 - id = uri.getPathSegments().get(1); // 从URI中获取数据ID + id = uri.getPathSegments().get(1); c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs, null, null, sortOrder); break; case URI_SEARCH: case URI_SEARCH_SUGGEST: if (sortOrder != null || projection != null) { - // 搜索请求不支持排序或选择 throw new IllegalArgumentException( "do not specify sortOrder, selection, selectionArgs, or projection" + "with this query"); } String searchString = null; if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) { - // 获取搜索建议的参数 if (uri.getPathSegments().size() > 1) { searchString = uri.getPathSegments().get(1); } } else { - // 从查询参数获取搜索字符串 searchString = uri.getQueryParameter("pattern"); } if (TextUtils.isEmpty(searchString)) { - return null; // 如果搜索字符串为空,则返回null + return null; } try { - // 使用通配符模糊匹配 searchString = String.format("%%%s%%", searchString); c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY, - new String[] { searchString }); // 执行搜索查询 + new String[] { searchString }); } catch (IllegalStateException ex) { - Log.e(TAG, "got exception: " + ex.toString()); // 记录异常 + Log.e(TAG, "got exception: " + ex.toString()); } break; default: - // 未知的URI,抛出异常 throw new IllegalArgumentException("Unknown URI " + uri); } - if (c != null) { - // 设置通知URI,数据变化时通知的URI c.setNotificationUri(getContext().getContentResolver(), uri); } - return c; // 返回查询结果 + return c; } @Override public Uri insert(Uri uri, ContentValues values) { - // 插入数据方法 - SQLiteDatabase db = mHelper.getWritableDatabase(); // 获取可写数据库 - long dataId = 0, noteId = 0, insertedId = 0; // 初始化ID - - switch (mMatcher.match(uri)) { // 根据URI匹配不同的插入类型 + SQLiteDatabase db = mHelper.getWritableDatabase(); + long dataId = 0, noteId = 0, insertedId = 0; + switch (mMatcher.match(uri)) { case URI_NOTE: - // 插入新的笔记 insertedId = noteId = db.insert(TABLE.NOTE, null, values); break; case URI_DATA: - // 插入新的数据 if (values.containsKey(DataColumns.NOTE_ID)) { - // 获取关联的笔记ID noteId = values.getAsLong(DataColumns.NOTE_ID); } else { - Log.d(TAG, "Wrong data format without note id:" + values.toString()); // 记录错误日志 + Log.d(TAG, "Wrong data format without note id:" + values.toString()); } insertedId = dataId = db.insert(TABLE.DATA, null, values); break; default: - // 未知的URI,抛出异常 throw new IllegalArgumentException("Unknown URI " + uri); } - - // 当笔记插入成功时,通知笔记URI + // Notify the note uri if (noteId > 0) { getContext().getContentResolver().notifyChange( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null); } - // 当数据插入成功时,通知数据URI + // Notify the data uri if (dataId > 0) { getContext().getContentResolver().notifyChange( ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null); } - return ContentUris.withAppendedId(uri, insertedId); // 返回新插入项的URI + return ContentUris.withAppendedId(uri, insertedId); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { - // 删除数据方法 - int count = 0; // 计数删除的行数 - String id = null; // 用于存储ID - SQLiteDatabase db = mHelper.getWritableDatabase(); // 获取可写数据库 - boolean deleteData = false; // 标记是否删除数据 - - switch (mMatcher.match(uri)) { // 根据URI匹配不同的删除类型 + int count = 0; + String id = null; + SQLiteDatabase db = mHelper.getWritableDatabase(); + boolean deleteData = false; + switch (mMatcher.match(uri)) { case URI_NOTE: - // 删除所有笔记 - selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 "; // 除去系统文件夹 + selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 "; count = db.delete(TABLE.NOTE, selection, selectionArgs); break; case URI_NOTE_ITEM: - // 删除单个笔记 - id = uri.getPathSegments().get(1); // 从URI中获取笔记ID + id = uri.getPathSegments().get(1); + /** + * ID that smaller than 0 is system folder which is not allowed to + * trash + */ long noteId = Long.valueOf(id); if (noteId <= 0) { - break; // 系统文件夹不允许删除 + break; } count = db.delete(TABLE.NOTE, NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs); break; case URI_DATA: - // 删除所有数据 count = db.delete(TABLE.DATA, selection, selectionArgs); - deleteData = true; // 标记为删除数据 + deleteData = true; break; case URI_DATA_ITEM: - // 删除单个数据 - id = uri.getPathSegments().get(1); // 从URI中获取数据ID + id = uri.getPathSegments().get(1); count = db.delete(TABLE.DATA, DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs); - deleteData = true; // 标记为删除数据 + deleteData = true; break; default: - // 未知的URI,抛出异常 throw new IllegalArgumentException("Unknown URI " + uri); } - if (count > 0) { if (deleteData) { - // 如果删除了数据,通知笔记URI getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); } - // 通知数据URI getContext().getContentResolver().notifyChange(uri, null); } - return count; // 返回删除的行数 + return count; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - // 更新数据方法 - int count = 0; // 计数更新的行数 - String id = null; // 用于存储ID - SQLiteDatabase db = mHelper.getWritableDatabase(); // 获取可写数据库 - boolean updateData = false; // 标记是否更新数据 - - switch (mMatcher.match(uri)) { // 根据URI匹配不同的更新类型 + int count = 0; + String id = null; + SQLiteDatabase db = mHelper.getWritableDatabase(); + boolean updateData = false; + switch (mMatcher.match(uri)) { case URI_NOTE: - // 更新所有笔记 - increaseNoteVersion(-1, selection, selectionArgs); // 更新版本 + increaseNoteVersion(-1, selection, selectionArgs); count = db.update(TABLE.NOTE, values, selection, selectionArgs); break; case URI_NOTE_ITEM: - // 更新单个笔记 - id = uri.getPathSegments().get(1); // 从URI中获取笔记ID - increaseNoteVersion(Long.valueOf(id), selection, selectionArgs); // 更新版本 + id = uri.getPathSegments().get(1); + increaseNoteVersion(Long.valueOf(id), selection, selectionArgs); count = db.update(TABLE.NOTE, values, NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs); break; case URI_DATA: - // 更新所有数据 count = db.update(TABLE.DATA, values, selection, selectionArgs); - updateData = true; // 标记为更新数据 + updateData = true; break; case URI_DATA_ITEM: - // 更新单个数据 - id = uri.getPathSegments().get(1); // 从URI中获取数据ID + id = uri.getPathSegments().get(1); count = db.update(TABLE.DATA, values, DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs); - updateData = true; // 标记为更新数据 + updateData = true; break; default: - // 未知的URI,抛出异常 throw new IllegalArgumentException("Unknown URI " + uri); } if (count > 0) { if (updateData) { - // 如果更新了数据,通知笔记URI getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); } - // 通知数据URI getContext().getContentResolver().notifyChange(uri, null); } - return count; // 返回更新的行数 + return count; } - // 辅助方法,用于解析选择条件 private String parseSelection(String selection) { - return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); // 如果选择条件不为空则添加 AND + return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); } - // 辅助方法,用于增加笔记版本 private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); sql.append(TABLE.NOTE); sql.append(" SET "); sql.append(NoteColumns.VERSION); - sql.append("=" + NoteColumns.VERSION + "+1 "); // 增加版本号 + sql.append("=" + NoteColumns.VERSION + "+1 "); if (id > 0 || !TextUtils.isEmpty(selection)) { - sql.append(" WHERE "); // 如果有ID或选择条件,添加WHERE + sql.append(" WHERE "); } if (id > 0) { - sql.append(NoteColumns.ID + "=" + String.valueOf(id)); // 添加ID条件 + sql.append(NoteColumns.ID + "=" + String.valueOf(id)); } if (!TextUtils.isEmpty(selection)) { - // 处理选择参数 String selectString = id > 0 ? parseSelection(selection) : selection; for (String args : selectionArgs) { - selectString = selectString.replaceFirst("\\?", args); // 替换占位符 + selectString = selectString.replaceFirst("\\?", args); } sql.append(selectString); } - mHelper.getWritableDatabase().execSQL(sql.toString()); // 执行SQL更新版本号 + mHelper.getWritableDatabase().execSQL(sql.toString()); } @Override public String getType(Uri uri) { - // 返回特定URI的MIME类型,这里暂时不实现 + // TODO Auto-generated method stub return null; } diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/MetaData.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/MetaData.java new file mode 100644 index 0000000..3a2050b --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/MetaData.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.data; + +import android.database.Cursor; +import android.util.Log; + +import net.micode.notes.tool.GTaskStringUtils; + +import org.json.JSONException; +import org.json.JSONObject; + + +public class MetaData extends Task { + private final static String TAG = MetaData.class.getSimpleName(); + + private String mRelatedGid = null; + + public void setMeta(String gid, JSONObject metaInfo) { + try { + metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); + } catch (JSONException e) { + Log.e(TAG, "failed to put related gid"); + } + setNotes(metaInfo.toString()); + setName(GTaskStringUtils.META_NOTE_NAME); + } + + public String getRelatedGid() { + return mRelatedGid; + } + + @Override + public boolean isWorthSaving() { + return getNotes() != null; + } + + @Override + public void setContentByRemoteJSON(JSONObject js) { + super.setContentByRemoteJSON(js); + if (getNotes() != null) { + try { + JSONObject metaInfo = new JSONObject(getNotes().trim()); + mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); + } catch (JSONException e) { + Log.w(TAG, "failed to get related gid"); + mRelatedGid = null; + } + } + } + + @Override + public void setContentByLocalJSON(JSONObject js) { + // this function should not be called + throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); + } + + @Override + public JSONObject getLocalJSONFromContent() { + throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); + } + + @Override + public int getSyncAction(Cursor c) { + throw new IllegalAccessError("MetaData:getSyncAction should not be called"); + } + +} diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/Node.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/Node.java new file mode 100644 index 0000000..63950e0 --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/Node.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.data; + +import android.database.Cursor; + +import org.json.JSONObject; + +public abstract class Node { + public static final int SYNC_ACTION_NONE = 0; + + public static final int SYNC_ACTION_ADD_REMOTE = 1; + + public static final int SYNC_ACTION_ADD_LOCAL = 2; + + public static final int SYNC_ACTION_DEL_REMOTE = 3; + + public static final int SYNC_ACTION_DEL_LOCAL = 4; + + public static final int SYNC_ACTION_UPDATE_REMOTE = 5; + + public static final int SYNC_ACTION_UPDATE_LOCAL = 6; + + public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; + + public static final int SYNC_ACTION_ERROR = 8; + + private String mGid; + + private String mName; + + private long mLastModified; + + private boolean mDeleted; + + public Node() { + mGid = null; + mName = ""; + mLastModified = 0; + mDeleted = false; + } + + public abstract JSONObject getCreateAction(int actionId); + + public abstract JSONObject getUpdateAction(int actionId); + + public abstract void setContentByRemoteJSON(JSONObject js); + + public abstract void setContentByLocalJSON(JSONObject js); + + public abstract JSONObject getLocalJSONFromContent(); + + public abstract int getSyncAction(Cursor c); + + public void setGid(String gid) { + this.mGid = gid; + } + + public void setName(String name) { + this.mName = name; + } + + public void setLastModified(long lastModified) { + this.mLastModified = lastModified; + } + + public void setDeleted(boolean deleted) { + this.mDeleted = deleted; + } + + public String getGid() { + return this.mGid; + } + + public String getName() { + return this.mName; + } + + public long getLastModified() { + return this.mLastModified; + } + + public boolean getDeleted() { + return this.mDeleted; + } + +} diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/SqlData.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/SqlData.java new file mode 100644 index 0000000..d3ec3be --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/SqlData.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.data; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.data.NotesDatabaseHelper.TABLE; +import net.micode.notes.gtask.exception.ActionFailureException; + +import org.json.JSONException; +import org.json.JSONObject; + + +public class SqlData { + private static final String TAG = SqlData.class.getSimpleName(); + + private static final int INVALID_ID = -99999; + + public static final String[] PROJECTION_DATA = new String[] { + DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1, + DataColumns.DATA3 + }; + + public static final int DATA_ID_COLUMN = 0; + + public static final int DATA_MIME_TYPE_COLUMN = 1; + + public static final int DATA_CONTENT_COLUMN = 2; + + public static final int DATA_CONTENT_DATA_1_COLUMN = 3; + + public static final int DATA_CONTENT_DATA_3_COLUMN = 4; + + private ContentResolver mContentResolver; + + private boolean mIsCreate; + + private long mDataId; + + private String mDataMimeType; + + private String mDataContent; + + private long mDataContentData1; + + private String mDataContentData3; + + private ContentValues mDiffDataValues; + + public SqlData(Context context) { + mContentResolver = context.getContentResolver(); + mIsCreate = true; + mDataId = INVALID_ID; + mDataMimeType = DataConstants.NOTE; + mDataContent = ""; + mDataContentData1 = 0; + mDataContentData3 = ""; + mDiffDataValues = new ContentValues(); + } + + public SqlData(Context context, Cursor c) { + mContentResolver = context.getContentResolver(); + mIsCreate = false; + loadFromCursor(c); + mDiffDataValues = new ContentValues(); + } + + private void loadFromCursor(Cursor c) { + mDataId = c.getLong(DATA_ID_COLUMN); + mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN); + mDataContent = c.getString(DATA_CONTENT_COLUMN); + mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN); + mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN); + } + + public void setContent(JSONObject js) throws JSONException { + long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID; + if (mIsCreate || mDataId != dataId) { + mDiffDataValues.put(DataColumns.ID, dataId); + } + mDataId = dataId; + + String dataMimeType = js.has(DataColumns.MIME_TYPE) ? js.getString(DataColumns.MIME_TYPE) + : DataConstants.NOTE; + if (mIsCreate || !mDataMimeType.equals(dataMimeType)) { + mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType); + } + mDataMimeType = dataMimeType; + + String dataContent = js.has(DataColumns.CONTENT) ? js.getString(DataColumns.CONTENT) : ""; + if (mIsCreate || !mDataContent.equals(dataContent)) { + mDiffDataValues.put(DataColumns.CONTENT, dataContent); + } + mDataContent = dataContent; + + long dataContentData1 = js.has(DataColumns.DATA1) ? js.getLong(DataColumns.DATA1) : 0; + if (mIsCreate || mDataContentData1 != dataContentData1) { + mDiffDataValues.put(DataColumns.DATA1, dataContentData1); + } + mDataContentData1 = dataContentData1; + + String dataContentData3 = js.has(DataColumns.DATA3) ? js.getString(DataColumns.DATA3) : ""; + if (mIsCreate || !mDataContentData3.equals(dataContentData3)) { + mDiffDataValues.put(DataColumns.DATA3, dataContentData3); + } + mDataContentData3 = dataContentData3; + } + + public JSONObject getContent() throws JSONException { + if (mIsCreate) { + Log.e(TAG, "it seems that we haven't created this in database yet"); + return null; + } + JSONObject js = new JSONObject(); + js.put(DataColumns.ID, mDataId); + js.put(DataColumns.MIME_TYPE, mDataMimeType); + js.put(DataColumns.CONTENT, mDataContent); + js.put(DataColumns.DATA1, mDataContentData1); + js.put(DataColumns.DATA3, mDataContentData3); + return js; + } + + public void commit(long noteId, boolean validateVersion, long version) { + + if (mIsCreate) { + if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) { + mDiffDataValues.remove(DataColumns.ID); + } + + mDiffDataValues.put(DataColumns.NOTE_ID, noteId); + Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues); + try { + mDataId = Long.valueOf(uri.getPathSegments().get(1)); + } catch (NumberFormatException e) { + Log.e(TAG, "Get note id error :" + e.toString()); + throw new ActionFailureException("create note failed"); + } + } else { + if (mDiffDataValues.size() > 0) { + int result = 0; + if (!validateVersion) { + result = mContentResolver.update(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null); + } else { + result = mContentResolver.update(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, + " ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE + + " WHERE " + NoteColumns.VERSION + "=?)", new String[] { + String.valueOf(noteId), String.valueOf(version) + }); + } + if (result == 0) { + Log.w(TAG, "there is no update. maybe user updates note when syncing"); + } + } + } + + mDiffDataValues.clear(); + mIsCreate = false; + } + + public long getId() { + return mDataId; + } +} diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/SqlNote.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/SqlNote.java new file mode 100644 index 0000000..79a4095 --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/SqlNote.java @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.data; + +import android.appwidget.AppWidgetManager; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.exception.ActionFailureException; +import net.micode.notes.tool.GTaskStringUtils; +import net.micode.notes.tool.ResourceParser; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + + +public class SqlNote { + private static final String TAG = SqlNote.class.getSimpleName(); + + private static final int INVALID_ID = -99999; + + public static final String[] PROJECTION_NOTE = new String[] { + NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID, + NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE, + NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE, + NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.SYNC_ID, + NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID, + NoteColumns.VERSION + }; + + public static final int ID_COLUMN = 0; + + public static final int ALERTED_DATE_COLUMN = 1; + + public static final int BG_COLOR_ID_COLUMN = 2; + + public static final int CREATED_DATE_COLUMN = 3; + + public static final int HAS_ATTACHMENT_COLUMN = 4; + + public static final int MODIFIED_DATE_COLUMN = 5; + + public static final int NOTES_COUNT_COLUMN = 6; + + public static final int PARENT_ID_COLUMN = 7; + + public static final int SNIPPET_COLUMN = 8; + + public static final int TYPE_COLUMN = 9; + + public static final int WIDGET_ID_COLUMN = 10; + + public static final int WIDGET_TYPE_COLUMN = 11; + + public static final int SYNC_ID_COLUMN = 12; + + public static final int LOCAL_MODIFIED_COLUMN = 13; + + public static final int ORIGIN_PARENT_ID_COLUMN = 14; + + public static final int GTASK_ID_COLUMN = 15; + + public static final int VERSION_COLUMN = 16; + + private Context mContext; + + private ContentResolver mContentResolver; + + private boolean mIsCreate; + + private long mId; + + private long mAlertDate; + + private int mBgColorId; + + private long mCreatedDate; + + private int mHasAttachment; + + private long mModifiedDate; + + private long mParentId; + + private String mSnippet; + + private int mType; + + private int mWidgetId; + + private int mWidgetType; + + private long mOriginParent; + + private long mVersion; + + private ContentValues mDiffNoteValues; + + private ArrayList mDataList; + + public SqlNote(Context context) { + mContext = context; + mContentResolver = context.getContentResolver(); + mIsCreate = true; + mId = INVALID_ID; + mAlertDate = 0; + mBgColorId = ResourceParser.getDefaultBgId(context); + mCreatedDate = System.currentTimeMillis(); + mHasAttachment = 0; + mModifiedDate = System.currentTimeMillis(); + mParentId = 0; + mSnippet = ""; + mType = Notes.TYPE_NOTE; + mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; + mOriginParent = 0; + mVersion = 0; + mDiffNoteValues = new ContentValues(); + mDataList = new ArrayList(); + } + + public SqlNote(Context context, Cursor c) { + mContext = context; + mContentResolver = context.getContentResolver(); + mIsCreate = false; + loadFromCursor(c); + mDataList = new ArrayList(); + if (mType == Notes.TYPE_NOTE) + loadDataContent(); + mDiffNoteValues = new ContentValues(); + } + + public SqlNote(Context context, long id) { + mContext = context; + mContentResolver = context.getContentResolver(); + mIsCreate = false; + loadFromCursor(id); + mDataList = new ArrayList(); + if (mType == Notes.TYPE_NOTE) + loadDataContent(); + mDiffNoteValues = new ContentValues(); + + } + + private void loadFromCursor(long id) { + Cursor c = null; + try { + c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)", + new String[] { + String.valueOf(id) + }, null); + if (c != null) { + c.moveToNext(); + loadFromCursor(c); + } else { + Log.w(TAG, "loadFromCursor: cursor = null"); + } + } finally { + if (c != null) + c.close(); + } + } + + private void loadFromCursor(Cursor c) { + mId = c.getLong(ID_COLUMN); + mAlertDate = c.getLong(ALERTED_DATE_COLUMN); + mBgColorId = c.getInt(BG_COLOR_ID_COLUMN); + mCreatedDate = c.getLong(CREATED_DATE_COLUMN); + mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN); + mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN); + mParentId = c.getLong(PARENT_ID_COLUMN); + mSnippet = c.getString(SNIPPET_COLUMN); + mType = c.getInt(TYPE_COLUMN); + mWidgetId = c.getInt(WIDGET_ID_COLUMN); + mWidgetType = c.getInt(WIDGET_TYPE_COLUMN); + mVersion = c.getLong(VERSION_COLUMN); + } + + private void loadDataContent() { + Cursor c = null; + mDataList.clear(); + try { + c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA, + "(note_id=?)", new String[] { + String.valueOf(mId) + }, null); + if (c != null) { + if (c.getCount() == 0) { + Log.w(TAG, "it seems that the note has not data"); + return; + } + while (c.moveToNext()) { + SqlData data = new SqlData(mContext, c); + mDataList.add(data); + } + } else { + Log.w(TAG, "loadDataContent: cursor = null"); + } + } finally { + if (c != null) + c.close(); + } + } + + public boolean setContent(JSONObject js) { + try { + JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); + if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { + Log.w(TAG, "cannot set system folder"); + } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { + // for folder we can only update the snnipet and type + String snippet = note.has(NoteColumns.SNIPPET) ? note + .getString(NoteColumns.SNIPPET) : ""; + if (mIsCreate || !mSnippet.equals(snippet)) { + mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); + } + mSnippet = snippet; + + int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) + : Notes.TYPE_NOTE; + if (mIsCreate || mType != type) { + mDiffNoteValues.put(NoteColumns.TYPE, type); + } + mType = type; + } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) { + JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); + long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID; + if (mIsCreate || mId != id) { + mDiffNoteValues.put(NoteColumns.ID, id); + } + mId = id; + + long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note + .getLong(NoteColumns.ALERTED_DATE) : 0; + if (mIsCreate || mAlertDate != alertDate) { + mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate); + } + mAlertDate = alertDate; + + int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note + .getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext); + if (mIsCreate || mBgColorId != bgColorId) { + mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId); + } + mBgColorId = bgColorId; + + long createDate = note.has(NoteColumns.CREATED_DATE) ? note + .getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis(); + if (mIsCreate || mCreatedDate != createDate) { + mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate); + } + mCreatedDate = createDate; + + int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note + .getInt(NoteColumns.HAS_ATTACHMENT) : 0; + if (mIsCreate || mHasAttachment != hasAttachment) { + mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment); + } + mHasAttachment = hasAttachment; + + long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note + .getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis(); + if (mIsCreate || mModifiedDate != modifiedDate) { + mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate); + } + mModifiedDate = modifiedDate; + + long parentId = note.has(NoteColumns.PARENT_ID) ? note + .getLong(NoteColumns.PARENT_ID) : 0; + if (mIsCreate || mParentId != parentId) { + mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId); + } + mParentId = parentId; + + String snippet = note.has(NoteColumns.SNIPPET) ? note + .getString(NoteColumns.SNIPPET) : ""; + if (mIsCreate || !mSnippet.equals(snippet)) { + mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); + } + mSnippet = snippet; + + int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) + : Notes.TYPE_NOTE; + if (mIsCreate || mType != type) { + mDiffNoteValues.put(NoteColumns.TYPE, type); + } + mType = type; + + int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID) + : AppWidgetManager.INVALID_APPWIDGET_ID; + if (mIsCreate || mWidgetId != widgetId) { + mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId); + } + mWidgetId = widgetId; + + int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note + .getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE; + if (mIsCreate || mWidgetType != widgetType) { + mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType); + } + mWidgetType = widgetType; + + long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note + .getLong(NoteColumns.ORIGIN_PARENT_ID) : 0; + if (mIsCreate || mOriginParent != originParent) { + mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent); + } + mOriginParent = originParent; + + for (int i = 0; i < dataArray.length(); i++) { + JSONObject data = dataArray.getJSONObject(i); + SqlData sqlData = null; + if (data.has(DataColumns.ID)) { + long dataId = data.getLong(DataColumns.ID); + for (SqlData temp : mDataList) { + if (dataId == temp.getId()) { + sqlData = temp; + } + } + } + + if (sqlData == null) { + sqlData = new SqlData(mContext); + mDataList.add(sqlData); + } + + sqlData.setContent(data); + } + } + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + return false; + } + return true; + } + + public JSONObject getContent() { + try { + JSONObject js = new JSONObject(); + + if (mIsCreate) { + Log.e(TAG, "it seems that we haven't created this in database yet"); + return null; + } + + JSONObject note = new JSONObject(); + if (mType == Notes.TYPE_NOTE) { + note.put(NoteColumns.ID, mId); + note.put(NoteColumns.ALERTED_DATE, mAlertDate); + note.put(NoteColumns.BG_COLOR_ID, mBgColorId); + note.put(NoteColumns.CREATED_DATE, mCreatedDate); + note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment); + note.put(NoteColumns.MODIFIED_DATE, mModifiedDate); + note.put(NoteColumns.PARENT_ID, mParentId); + note.put(NoteColumns.SNIPPET, mSnippet); + note.put(NoteColumns.TYPE, mType); + note.put(NoteColumns.WIDGET_ID, mWidgetId); + note.put(NoteColumns.WIDGET_TYPE, mWidgetType); + note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent); + js.put(GTaskStringUtils.META_HEAD_NOTE, note); + + JSONArray dataArray = new JSONArray(); + for (SqlData sqlData : mDataList) { + JSONObject data = sqlData.getContent(); + if (data != null) { + dataArray.put(data); + } + } + js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); + } else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) { + note.put(NoteColumns.ID, mId); + note.put(NoteColumns.TYPE, mType); + note.put(NoteColumns.SNIPPET, mSnippet); + js.put(GTaskStringUtils.META_HEAD_NOTE, note); + } + + return js; + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + } + return null; + } + + public void setParentId(long id) { + mParentId = id; + mDiffNoteValues.put(NoteColumns.PARENT_ID, id); + } + + public void setGtaskId(String gid) { + mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); + } + + public void setSyncId(long syncId) { + mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId); + } + + public void resetLocalModified() { + mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0); + } + + public long getId() { + return mId; + } + + public long getParentId() { + return mParentId; + } + + public String getSnippet() { + return mSnippet; + } + + public boolean isNoteType() { + return mType == Notes.TYPE_NOTE; + } + + public void commit(boolean validateVersion) { + if (mIsCreate) { + if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) { + mDiffNoteValues.remove(NoteColumns.ID); + } + + Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues); + try { + mId = Long.valueOf(uri.getPathSegments().get(1)); + } catch (NumberFormatException e) { + Log.e(TAG, "Get note id error :" + e.toString()); + throw new ActionFailureException("create note failed"); + } + if (mId == 0) { + throw new IllegalStateException("Create thread id failed"); + } + + if (mType == Notes.TYPE_NOTE) { + for (SqlData sqlData : mDataList) { + sqlData.commit(mId, false, -1); + } + } + } else { + if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) { + Log.e(TAG, "No such note"); + throw new IllegalStateException("Try to update note with invalid id"); + } + if (mDiffNoteValues.size() > 0) { + mVersion ++; + int result = 0; + if (!validateVersion) { + result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" + + NoteColumns.ID + "=?)", new String[] { + String.valueOf(mId) + }); + } else { + result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" + + NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)", + new String[] { + String.valueOf(mId), String.valueOf(mVersion) + }); + } + if (result == 0) { + Log.w(TAG, "there is no update. maybe user updates note when syncing"); + } + } + + if (mType == Notes.TYPE_NOTE) { + for (SqlData sqlData : mDataList) { + sqlData.commit(mId, validateVersion, mVersion); + } + } + } + + // refresh local info + loadFromCursor(mId); + if (mType == Notes.TYPE_NOTE) + loadDataContent(); + + mDiffNoteValues.clear(); + mIsCreate = false; + } +} diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/Task.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/Task.java new file mode 100644 index 0000000..6a19454 --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/Task.java @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.data; + +import android.database.Cursor; +import android.text.TextUtils; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.exception.ActionFailureException; +import net.micode.notes.tool.GTaskStringUtils; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + + +public class Task extends Node { + private static final String TAG = Task.class.getSimpleName(); + + private boolean mCompleted; + + private String mNotes; + + private JSONObject mMetaInfo; + + private Task mPriorSibling; + + private TaskList mParent; + + public Task() { + super(); + mCompleted = false; + mNotes = null; + mPriorSibling = null; + mParent = null; + mMetaInfo = null; + } + + public JSONObject getCreateAction(int actionId) { + JSONObject js = new JSONObject(); + + try { + // action_type + js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, + GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); + + // action_id + js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); + + // index + js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this)); + + // entity_delta + JSONObject entity = new JSONObject(); + entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); + entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); + entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, + GTaskStringUtils.GTASK_JSON_TYPE_TASK); + if (getNotes() != null) { + entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); + } + js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); + + // parent_id + js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid()); + + // dest_parent_type + js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE, + GTaskStringUtils.GTASK_JSON_TYPE_GROUP); + + // list_id + js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid()); + + // prior_sibling_id + if (mPriorSibling != null) { + js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid()); + } + + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("fail to generate task-create jsonobject"); + } + + return js; + } + + public JSONObject getUpdateAction(int actionId) { + JSONObject js = new JSONObject(); + + try { + // action_type + js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, + GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); + + // action_id + js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); + + // id + js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); + + // entity_delta + JSONObject entity = new JSONObject(); + entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); + if (getNotes() != null) { + entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); + } + entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); + js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); + + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("fail to generate task-update jsonobject"); + } + + return js; + } + + public void setContentByRemoteJSON(JSONObject js) { + if (js != null) { + try { + // id + if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { + setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); + } + + // last_modified + if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { + setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); + } + + // name + if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { + setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); + } + + // notes + if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) { + setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES)); + } + + // deleted + if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) { + setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED)); + } + + // completed + if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) { + setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED)); + } + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("fail to get task content from jsonobject"); + } + } + } + + public void setContentByLocalJSON(JSONObject js) { + if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE) + || !js.has(GTaskStringUtils.META_HEAD_DATA)) { + Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); + } + + try { + JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); + JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); + + if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) { + Log.e(TAG, "invalid type"); + return; + } + + for (int i = 0; i < dataArray.length(); i++) { + JSONObject data = dataArray.getJSONObject(i); + if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) { + setName(data.getString(DataColumns.CONTENT)); + break; + } + } + + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + } + } + + public JSONObject getLocalJSONFromContent() { + String name = getName(); + try { + if (mMetaInfo == null) { + // new task created from web + if (name == null) { + Log.w(TAG, "the note seems to be an empty one"); + return null; + } + + JSONObject js = new JSONObject(); + JSONObject note = new JSONObject(); + JSONArray dataArray = new JSONArray(); + JSONObject data = new JSONObject(); + data.put(DataColumns.CONTENT, name); + dataArray.put(data); + js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); + note.put(NoteColumns.TYPE, Notes.TYPE_NOTE); + js.put(GTaskStringUtils.META_HEAD_NOTE, note); + return js; + } else { + // synced task + JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); + JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA); + + for (int i = 0; i < dataArray.length(); i++) { + JSONObject data = dataArray.getJSONObject(i); + if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) { + data.put(DataColumns.CONTENT, getName()); + break; + } + } + + note.put(NoteColumns.TYPE, Notes.TYPE_NOTE); + return mMetaInfo; + } + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + return null; + } + } + + public void setMetaInfo(MetaData metaData) { + if (metaData != null && metaData.getNotes() != null) { + try { + mMetaInfo = new JSONObject(metaData.getNotes()); + } catch (JSONException e) { + Log.w(TAG, e.toString()); + mMetaInfo = null; + } + } + } + + public int getSyncAction(Cursor c) { + try { + JSONObject noteInfo = null; + if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) { + noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); + } + + if (noteInfo == null) { + Log.w(TAG, "it seems that note meta has been deleted"); + return SYNC_ACTION_UPDATE_REMOTE; + } + + if (!noteInfo.has(NoteColumns.ID)) { + Log.w(TAG, "remote note id seems to be deleted"); + return SYNC_ACTION_UPDATE_LOCAL; + } + + // validate the note id now + if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) { + Log.w(TAG, "note id doesn't match"); + return SYNC_ACTION_UPDATE_LOCAL; + } + + if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { + // there is no local update + if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { + // no update both side + return SYNC_ACTION_NONE; + } else { + // apply remote to local + return SYNC_ACTION_UPDATE_LOCAL; + } + } else { + // validate gtask id + if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { + Log.e(TAG, "gtask id doesn't match"); + return SYNC_ACTION_ERROR; + } + if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { + // local modification only + return SYNC_ACTION_UPDATE_REMOTE; + } else { + return SYNC_ACTION_UPDATE_CONFLICT; + } + } + } catch (Exception e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + } + + return SYNC_ACTION_ERROR; + } + + public boolean isWorthSaving() { + return mMetaInfo != null || (getName() != null && getName().trim().length() > 0) + || (getNotes() != null && getNotes().trim().length() > 0); + } + + public void setCompleted(boolean completed) { + this.mCompleted = completed; + } + + public void setNotes(String notes) { + this.mNotes = notes; + } + + public void setPriorSibling(Task priorSibling) { + this.mPriorSibling = priorSibling; + } + + public void setParent(TaskList parent) { + this.mParent = parent; + } + + public boolean getCompleted() { + return this.mCompleted; + } + + public String getNotes() { + return this.mNotes; + } + + public Task getPriorSibling() { + return this.mPriorSibling; + } + + public TaskList getParent() { + return this.mParent; + } + +} diff --git a/src/Notes-master/src/net/micode/notes/gtask/data/TaskList.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/TaskList.java similarity index 57% rename from src/Notes-master/src/net/micode/notes/gtask/data/TaskList.java rename to code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/TaskList.java index d76b4b7..4ea21c5 100644 --- a/src/Notes-master/src/net/micode/notes/gtask/data/TaskList.java +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/data/TaskList.java @@ -16,169 +16,156 @@ package net.micode.notes.gtask.data; -// 导入所需的类 import android.database.Cursor; import android.util.Log; + import net.micode.notes.data.Notes; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.gtask.exception.ActionFailureException; import net.micode.notes.tool.GTaskStringUtils; + import org.json.JSONException; import org.json.JSONObject; + import java.util.ArrayList; -// TaskList类继承自Node类,表示一个任务列表 + public class TaskList extends Node { - // 定义日志标签 private static final String TAG = TaskList.class.getSimpleName(); - // 任务列表的索引 private int mIndex; - // 存储子任务的列表 private ArrayList mChildren; - // TaskList的构造函数,初始化子任务列表和索引 public TaskList() { super(); mChildren = new ArrayList(); - mIndex = 1; // 默认索引为1 + mIndex = 1; } - // 获取创建任务列表的JSON对象 public JSONObject getCreateAction(int actionId) { - JSONObject js = new JSONObject(); // 创建一个新的JSON对象 + JSONObject js = new JSONObject(); try { - // 设置动作类型为创建 + // action_type js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); - // 设置动作ID + // action_id js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - // 设置索引 + // index js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); - // 创建实体的变化对象 + // entity_delta JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 设置名称 - entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); // 创建者ID + entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); + entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, - GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 实体类型 - js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); // 将实体变化对象放入主对象中 + GTaskStringUtils.GTASK_JSON_TYPE_GROUP); + js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); } catch (JSONException e) { - Log.e(TAG, e.toString()); // 打印错误日志 + Log.e(TAG, e.toString()); e.printStackTrace(); - throw new ActionFailureException("fail to generate tasklist-create jsonobject"); // 抛出异常 + throw new ActionFailureException("fail to generate tasklist-create jsonobject"); } - return js; // 返回生成的JSON对象 + return js; } - // 获取更新任务列表的JSON对象 public JSONObject getUpdateAction(int actionId) { - JSONObject js = new JSONObject(); // 创建一个新的JSON对象 + JSONObject js = new JSONObject(); try { - // 设置动作类型为更新 + // action_type js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); - // 设置动作ID + // action_id js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - // 设置任务列表ID + // id js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); - // 创建实体的变化对象 + // entity_delta JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 设置名称 - entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); // 设置删除状态 - js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); // 将实体变化对象放入主对象中 + entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); + entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); + js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); } catch (JSONException e) { - Log.e(TAG, e.toString()); // 打印错误日志 + Log.e(TAG, e.toString()); e.printStackTrace(); - throw new ActionFailureException("fail to generate tasklist-update jsonobject"); // 抛出异常 + throw new ActionFailureException("fail to generate tasklist-update jsonobject"); } - return js; // 返回生成的JSON对象 + return js; } - // 根据远程JSON设置任务列表的内容 public void setContentByRemoteJSON(JSONObject js) { if (js != null) { try { - // 设置任务列表ID + // id if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); } - // 设置最后修改时间 + // last_modified if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); } - // 设置名称 + // name if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); } } catch (JSONException e) { - Log.e(TAG, e.toString()); // 打印错误日志 + Log.e(TAG, e.toString()); e.printStackTrace(); - throw new ActionFailureException("fail to get tasklist content from jsonobject"); // 抛出异常 + throw new ActionFailureException("fail to get tasklist content from jsonobject"); } } } - // 根据本地JSON设置任务列表的内容 public void setContentByLocalJSON(JSONObject js) { - // 检查JSON对象是否有效 if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { - Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); // 发出警告日志 + Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); } try { - // 获取任务列表的文件夹对象 JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - // 根据文件夹类型设置名称 if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { String name = folder.getString(NoteColumns.SNIPPET); - setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); // 设置文件夹名称 + setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); } else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { - // 检查系统文件夹ID并设置相应名称 if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT); else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE); else - Log.e(TAG, "invalid system folder"); // 打印错误日志 + Log.e(TAG, "invalid system folder"); } else { - Log.e(TAG, "error type"); // 打印错误日志 + Log.e(TAG, "error type"); } } catch (JSONException e) { - Log.e(TAG, e.toString()); // 打印错误日志 + Log.e(TAG, e.toString()); e.printStackTrace(); } } - // 从内容生成本地JSON对象 public JSONObject getLocalJSONFromContent() { try { - JSONObject js = new JSONObject(); // 创建一个新的JSON对象 - JSONObject folder = new JSONObject(); // 创建文件夹的JSON对象 + JSONObject js = new JSONObject(); + JSONObject folder = new JSONObject(); - String folderName = getName(); // 获取任务列表名称 + String folderName = getName(); if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)) folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(), - folderName.length()); // 去掉前缀 - - // 设置文件夹名称和类型 + folderName.length()); folder.put(NoteColumns.SNIPPET, folderName); if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT) || folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE)) @@ -186,183 +173,171 @@ public class TaskList extends Node { else folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); - js.put(GTaskStringUtils.META_HEAD_NOTE, folder); // 将文件夹对象放入主对象中 + js.put(GTaskStringUtils.META_HEAD_NOTE, folder); - return js; // 返回生成的JSON对象 + return js; } catch (JSONException e) { - Log.e(TAG, e.toString()); // 打印错误日志 + Log.e(TAG, e.toString()); e.printStackTrace(); - return null; // 出现异常时返回null + return null; } } - // 获取同步操作 public int getSyncAction(Cursor c) { try { if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { - // 本地没有更新 + // there is no local update if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // 本地和远程都没有更新 - return SYNC_ACTION_NONE; // 返回无操作 + // no update both side + return SYNC_ACTION_NONE; } else { - // 将远程应用到本地 + // apply remote to local return SYNC_ACTION_UPDATE_LOCAL; } } else { - // 校验任务ID + // validate gtask id if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { - Log.e(TAG, "gtask id doesn't match"); // 打印错误日志 - return SYNC_ACTION_ERROR; // 返回错误状态 + Log.e(TAG, "gtask id doesn't match"); + return SYNC_ACTION_ERROR; } if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // 仅本地修改 + // local modification only return SYNC_ACTION_UPDATE_REMOTE; } else { - // 对于文件夹冲突,采用本地修改 + // for folder conflicts, just apply local modification return SYNC_ACTION_UPDATE_REMOTE; } } } catch (Exception e) { - Log.e(TAG, e.toString()); // 打印错误日志 + Log.e(TAG, e.toString()); e.printStackTrace(); } - return SYNC_ACTION_ERROR; // 出现异常时返回错误状态 + return SYNC_ACTION_ERROR; } - // 获取子任务数量 public int getChildTaskCount() { - return mChildren.size(); // 返回子任务列表大小 + return mChildren.size(); } - // 添加子任务 public boolean addChildTask(Task task) { boolean ret = false; if (task != null && !mChildren.contains(task)) { - ret = mChildren.add(task); // 尝试添加任务 + ret = mChildren.add(task); if (ret) { - // 需要设置前一个兄弟任务和父任务 + // need to set prior sibling and parent task.setPriorSibling(mChildren.isEmpty() ? null : mChildren .get(mChildren.size() - 1)); - task.setParent(this); // 设置父任务 + task.setParent(this); } } - return ret; // 返回添加结果 + return ret; } - // 根据索引添加子任务 public boolean addChildTask(Task task, int index) { if (index < 0 || index > mChildren.size()) { - Log.e(TAG, "add child task: invalid index"); // 打印错误日志 - return false; // 返回失败 + Log.e(TAG, "add child task: invalid index"); + return false; } - int pos = mChildren.indexOf(task); // 查找任务在列表中的位置 + int pos = mChildren.indexOf(task); if (task != null && pos == -1) { - mChildren.add(index, task); // 根据索引添加任务 + mChildren.add(index, task); - // 更新任务列表 + // update the task list Task preTask = null; Task afterTask = null; if (index != 0) - preTask = mChildren.get(index - 1); // 获取前一个任务 + preTask = mChildren.get(index - 1); if (index != mChildren.size() - 1) - afterTask = mChildren.get(index + 1); // 获取后一个任务 + afterTask = mChildren.get(index + 1); - task.setPriorSibling(preTask); // 设置前一个兄弟任务 + task.setPriorSibling(preTask); if (afterTask != null) - afterTask.setPriorSibling(task); // 设置后一个兄弟任务 + afterTask.setPriorSibling(task); } - return true; // 返回成功 + return true; } - // 移除子任务 public boolean removeChildTask(Task task) { boolean ret = false; - int index = mChildren.indexOf(task); // 查找任务在列表中的位置 + int index = mChildren.indexOf(task); if (index != -1) { - ret = mChildren.remove(task); // 尝试移除任务 + ret = mChildren.remove(task); if (ret) { - // 重置前一个兄弟任务和父任务 + // reset prior sibling and parent task.setPriorSibling(null); task.setParent(null); - // 更新任务列表 + // update the task list if (index != mChildren.size()) { mChildren.get(index).setPriorSibling( - index == 0 ? null : mChildren.get(index - 1)); // 更新前一个兄弟任务 + index == 0 ? null : mChildren.get(index - 1)); } } } - return ret; // 返回移除结果 + return ret; } - // 移动子任务 public boolean moveChildTask(Task task, int index) { + if (index < 0 || index >= mChildren.size()) { - Log.e(TAG, "move child task: invalid index"); // 打印错误日志 - return false; // 返回失败 + Log.e(TAG, "move child task: invalid index"); + return false; } - int pos = mChildren.indexOf(task); // 查找任务在列表中的位置 + int pos = mChildren.indexOf(task); if (pos == -1) { - Log.e(TAG, "move child task: the task should in the list"); // 打印错误日志 - return false; // 返回失败 + Log.e(TAG, "move child task: the task should in the list"); + return false; } if (pos == index) - return true; // 位置不变返回成功 - return (removeChildTask(task) && addChildTask(task, index)); // 移除并重新添加任务 + return true; + return (removeChildTask(task) && addChildTask(task, index)); } - // 根据GID查找子任务 public Task findChildTaskByGid(String gid) { for (int i = 0; i < mChildren.size(); i++) { Task t = mChildren.get(i); if (t.getGid().equals(gid)) { - return t; // 找到任务返回 + return t; } } - return null; // 未找到返回null + return null; } - // 获取子任务索引 public int getChildTaskIndex(Task task) { - return mChildren.indexOf(task); // 返回任务在列表中的位置 + return mChildren.indexOf(task); } - // 根据索引获取子任务 public Task getChildTaskByIndex(int index) { if (index < 0 || index >= mChildren.size()) { - Log.e(TAG, "getTaskByIndex: invalid index"); // 打印错误日志 - return null; // 返回null + Log.e(TAG, "getTaskByIndex: invalid index"); + return null; } - return mChildren.get(index); // 返回任务 + return mChildren.get(index); } - // 根据GID获取子任务 public Task getChilTaskByGid(String gid) { for (Task task : mChildren) { if (task.getGid().equals(gid)) - return task; // 找到任务返回 + return task; } - return null; // 未找到返回null + return null; } - // 获取子任务列表 public ArrayList getChildTaskList() { - return this.mChildren; // 返回子任务列表 + return this.mChildren; } - // 设置索引 public void setIndex(int index) { - this.mIndex = index; // 设置任务列表索引 + this.mIndex = index; } - // 获取索引 public int getIndex() { - return this.mIndex; // 返回任务列表索引 + return this.mIndex; } } diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/exception/ActionFailureException.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/exception/ActionFailureException.java new file mode 100644 index 0000000..15504be --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/exception/ActionFailureException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.exception; + +public class ActionFailureException extends RuntimeException { + private static final long serialVersionUID = 4425249765923293627L; + + public ActionFailureException() { + super(); + } + + public ActionFailureException(String paramString) { + super(paramString); + } + + public ActionFailureException(String paramString, Throwable paramThrowable) { + super(paramString, paramThrowable); + } +} diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/exception/NetworkFailureException.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/exception/NetworkFailureException.java new file mode 100644 index 0000000..b08cfb1 --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/exception/NetworkFailureException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.exception; + +public class NetworkFailureException extends Exception { + private static final long serialVersionUID = 2107610287180234136L; + + public NetworkFailureException() { + super(); + } + + public NetworkFailureException(String paramString) { + super(paramString); + } + + public NetworkFailureException(String paramString, Throwable paramThrowable) { + super(paramString, paramThrowable); + } +} diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskASyncTask.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskASyncTask.java new file mode 100644 index 0000000..b3b61e7 --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskASyncTask.java @@ -0,0 +1,123 @@ + +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.remote; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; + +import net.micode.notes.R; +import net.micode.notes.ui.NotesListActivity; +import net.micode.notes.ui.NotesPreferenceActivity; + + +public class GTaskASyncTask extends AsyncTask { + + private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; + + public interface OnCompleteListener { + void onComplete(); + } + + private Context mContext; + + private NotificationManager mNotifiManager; + + private GTaskManager mTaskManager; + + private OnCompleteListener mOnCompleteListener; + + public GTaskASyncTask(Context context, OnCompleteListener listener) { + mContext = context; + mOnCompleteListener = listener; + mNotifiManager = (NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE); + mTaskManager = GTaskManager.getInstance(); + } + + public void cancelSync() { + mTaskManager.cancelSync(); + } + + public void publishProgess(String message) { + publishProgress(new String[] { + message + }); + } + + private void showNotification(int tickerId, String content) { + Notification notification = new Notification(R.drawable.notification, mContext + .getString(tickerId), System.currentTimeMillis()); + notification.defaults = Notification.DEFAULT_LIGHTS; + notification.flags = Notification.FLAG_AUTO_CANCEL; + PendingIntent pendingIntent; + if (tickerId != R.string.ticker_success) { + pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, + NotesPreferenceActivity.class), 0); + + } else { + pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, + NotesListActivity.class), 0); + } + notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content, + pendingIntent); + mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); + } + + @Override + protected Integer doInBackground(Void... unused) { + publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity + .getSyncAccountName(mContext))); + return mTaskManager.sync(mContext, this); + } + + @Override + protected void onProgressUpdate(String... progress) { + showNotification(R.string.ticker_syncing, progress[0]); + if (mContext instanceof GTaskSyncService) { + ((GTaskSyncService) mContext).sendBroadcast(progress[0]); + } + } + + @Override + protected void onPostExecute(Integer result) { + if (result == GTaskManager.STATE_SUCCESS) { + showNotification(R.string.ticker_success, mContext.getString( + R.string.success_sync_account, mTaskManager.getSyncAccount())); + NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis()); + } else if (result == GTaskManager.STATE_NETWORK_ERROR) { + showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network)); + } else if (result == GTaskManager.STATE_INTERNAL_ERROR) { + showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal)); + } else if (result == GTaskManager.STATE_SYNC_CANCELLED) { + showNotification(R.string.ticker_cancel, mContext + .getString(R.string.error_sync_cancelled)); + } + if (mOnCompleteListener != null) { + new Thread(new Runnable() { + + public void run() { + mOnCompleteListener.onComplete(); + } + }).start(); + } + } +} diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskClient.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskClient.java new file mode 100644 index 0000000..c67dfdf --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskClient.java @@ -0,0 +1,585 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.remote; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerFuture; +import android.app.Activity; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; + +import net.micode.notes.gtask.data.Node; +import net.micode.notes.gtask.data.Task; +import net.micode.notes.gtask.data.TaskList; +import net.micode.notes.gtask.exception.ActionFailureException; +import net.micode.notes.gtask.exception.NetworkFailureException; +import net.micode.notes.tool.GTaskStringUtils; +import net.micode.notes.ui.NotesPreferenceActivity; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; +import org.apache.http.params.HttpProtocolParams; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.List; +import java.util.zip.GZIPInputStream; +import java.util.zip.Inflater; +import java.util.zip.InflaterInputStream; + + +public class GTaskClient { + private static final String TAG = GTaskClient.class.getSimpleName(); + + private static final String GTASK_URL = "https://mail.google.com/tasks/"; + + private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig"; + + private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig"; + + private static GTaskClient mInstance = null; + + private DefaultHttpClient mHttpClient; + + private String mGetUrl; + + private String mPostUrl; + + private long mClientVersion; + + private boolean mLoggedin; + + private long mLastLoginTime; + + private int mActionId; + + private Account mAccount; + + private JSONArray mUpdateArray; + + private GTaskClient() { + mHttpClient = null; + mGetUrl = GTASK_GET_URL; + mPostUrl = GTASK_POST_URL; + mClientVersion = -1; + mLoggedin = false; + mLastLoginTime = 0; + mActionId = 1; + mAccount = null; + mUpdateArray = null; + } + + public static synchronized GTaskClient getInstance() { + if (mInstance == null) { + mInstance = new GTaskClient(); + } + return mInstance; + } + + public boolean login(Activity activity) { + // we suppose that the cookie would expire after 5 minutes + // then we need to re-login + final long interval = 1000 * 60 * 5; + if (mLastLoginTime + interval < System.currentTimeMillis()) { + mLoggedin = false; + } + + // need to re-login after account switch + if (mLoggedin + && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity + .getSyncAccountName(activity))) { + mLoggedin = false; + } + + if (mLoggedin) { + Log.d(TAG, "already logged in"); + return true; + } + + mLastLoginTime = System.currentTimeMillis(); + String authToken = loginGoogleAccount(activity, false); + if (authToken == null) { + Log.e(TAG, "login google account failed"); + return false; + } + + // login with custom domain if necessary + if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase() + .endsWith("googlemail.com"))) { + StringBuilder url = new StringBuilder(GTASK_URL).append("a/"); + int index = mAccount.name.indexOf('@') + 1; + String suffix = mAccount.name.substring(index); + url.append(suffix + "/"); + mGetUrl = url.toString() + "ig"; + mPostUrl = url.toString() + "r/ig"; + + if (tryToLoginGtask(activity, authToken)) { + mLoggedin = true; + } + } + + // try to login with google official url + if (!mLoggedin) { + mGetUrl = GTASK_GET_URL; + mPostUrl = GTASK_POST_URL; + if (!tryToLoginGtask(activity, authToken)) { + return false; + } + } + + mLoggedin = true; + return true; + } + + private String loginGoogleAccount(Activity activity, boolean invalidateToken) { + String authToken; + AccountManager accountManager = AccountManager.get(activity); + Account[] accounts = accountManager.getAccountsByType("com.google"); + + if (accounts.length == 0) { + Log.e(TAG, "there is no available google account"); + return null; + } + + String accountName = NotesPreferenceActivity.getSyncAccountName(activity); + Account account = null; + for (Account a : accounts) { + if (a.name.equals(accountName)) { + account = a; + break; + } + } + if (account != null) { + mAccount = account; + } else { + Log.e(TAG, "unable to get an account with the same name in the settings"); + return null; + } + + // get the token now + AccountManagerFuture accountManagerFuture = accountManager.getAuthToken(account, + "goanna_mobile", null, activity, null, null); + try { + Bundle authTokenBundle = accountManagerFuture.getResult(); + authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN); + if (invalidateToken) { + accountManager.invalidateAuthToken("com.google", authToken); + loginGoogleAccount(activity, false); + } + } catch (Exception e) { + Log.e(TAG, "get auth token failed"); + authToken = null; + } + + return authToken; + } + + private boolean tryToLoginGtask(Activity activity, String authToken) { + if (!loginGtask(authToken)) { + // maybe the auth token is out of date, now let's invalidate the + // token and try again + authToken = loginGoogleAccount(activity, true); + if (authToken == null) { + Log.e(TAG, "login google account failed"); + return false; + } + + if (!loginGtask(authToken)) { + Log.e(TAG, "login gtask failed"); + return false; + } + } + return true; + } + + private boolean loginGtask(String authToken) { + int timeoutConnection = 10000; + int timeoutSocket = 15000; + HttpParams httpParameters = new BasicHttpParams(); + HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); + HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); + mHttpClient = new DefaultHttpClient(httpParameters); + BasicCookieStore localBasicCookieStore = new BasicCookieStore(); + mHttpClient.setCookieStore(localBasicCookieStore); + HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false); + + // login gtask + try { + String loginUrl = mGetUrl + "?auth=" + authToken; + HttpGet httpGet = new HttpGet(loginUrl); + HttpResponse response = null; + response = mHttpClient.execute(httpGet); + + // get the cookie now + List cookies = mHttpClient.getCookieStore().getCookies(); + boolean hasAuthCookie = false; + for (Cookie cookie : cookies) { + if (cookie.getName().contains("GTL")) { + hasAuthCookie = true; + } + } + if (!hasAuthCookie) { + Log.w(TAG, "it seems that there is no auth cookie"); + } + + // get the client version + String resString = getResponseContent(response.getEntity()); + String jsBegin = "_setup("; + String jsEnd = ")}"; + int begin = resString.indexOf(jsBegin); + int end = resString.lastIndexOf(jsEnd); + String jsString = null; + if (begin != -1 && end != -1 && begin < end) { + jsString = resString.substring(begin + jsBegin.length(), end); + } + JSONObject js = new JSONObject(jsString); + mClientVersion = js.getLong("v"); + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + return false; + } catch (Exception e) { + // simply catch all exceptions + Log.e(TAG, "httpget gtask_url failed"); + return false; + } + + return true; + } + + private int getActionId() { + return mActionId++; + } + + private HttpPost createHttpPost() { + HttpPost httpPost = new HttpPost(mPostUrl); + httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + httpPost.setHeader("AT", "1"); + return httpPost; + } + + private String getResponseContent(HttpEntity entity) throws IOException { + String contentEncoding = null; + if (entity.getContentEncoding() != null) { + contentEncoding = entity.getContentEncoding().getValue(); + Log.d(TAG, "encoding: " + contentEncoding); + } + + InputStream input = entity.getContent(); + if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) { + input = new GZIPInputStream(entity.getContent()); + } else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) { + Inflater inflater = new Inflater(true); + input = new InflaterInputStream(entity.getContent(), inflater); + } + + try { + InputStreamReader isr = new InputStreamReader(input); + BufferedReader br = new BufferedReader(isr); + StringBuilder sb = new StringBuilder(); + + while (true) { + String buff = br.readLine(); + if (buff == null) { + return sb.toString(); + } + sb = sb.append(buff); + } + } finally { + input.close(); + } + } + + private JSONObject postRequest(JSONObject js) throws NetworkFailureException { + if (!mLoggedin) { + Log.e(TAG, "please login first"); + throw new ActionFailureException("not logged in"); + } + + HttpPost httpPost = createHttpPost(); + try { + LinkedList list = new LinkedList(); + list.add(new BasicNameValuePair("r", js.toString())); + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); + httpPost.setEntity(entity); + + // execute the post + HttpResponse response = mHttpClient.execute(httpPost); + String jsString = getResponseContent(response.getEntity()); + return new JSONObject(jsString); + + } catch (ClientProtocolException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new NetworkFailureException("postRequest failed"); + } catch (IOException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new NetworkFailureException("postRequest failed"); + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("unable to convert response content to jsonobject"); + } catch (Exception e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("error occurs when posting request"); + } + } + + public void createTask(Task task) throws NetworkFailureException { + commitUpdate(); + try { + JSONObject jsPost = new JSONObject(); + JSONArray actionList = new JSONArray(); + + // action_list + actionList.put(task.getCreateAction(getActionId())); + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); + + // client_version + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + // post + JSONObject jsResponse = postRequest(jsPost); + JSONObject jsResult = (JSONObject) jsResponse.getJSONArray( + GTaskStringUtils.GTASK_JSON_RESULTS).get(0); + task.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID)); + + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("create task: handing jsonobject failed"); + } + } + + public void createTaskList(TaskList tasklist) throws NetworkFailureException { + commitUpdate(); + try { + JSONObject jsPost = new JSONObject(); + JSONArray actionList = new JSONArray(); + + // action_list + actionList.put(tasklist.getCreateAction(getActionId())); + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); + + // client version + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + // post + JSONObject jsResponse = postRequest(jsPost); + JSONObject jsResult = (JSONObject) jsResponse.getJSONArray( + GTaskStringUtils.GTASK_JSON_RESULTS).get(0); + tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID)); + + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("create tasklist: handing jsonobject failed"); + } + } + + public void commitUpdate() throws NetworkFailureException { + if (mUpdateArray != null) { + try { + JSONObject jsPost = new JSONObject(); + + // action_list + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray); + + // client_version + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + postRequest(jsPost); + mUpdateArray = null; + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("commit update: handing jsonobject failed"); + } + } + } + + public void addUpdateNode(Node node) throws NetworkFailureException { + if (node != null) { + // too many update items may result in an error + // set max to 10 items + if (mUpdateArray != null && mUpdateArray.length() > 10) { + commitUpdate(); + } + + if (mUpdateArray == null) + mUpdateArray = new JSONArray(); + mUpdateArray.put(node.getUpdateAction(getActionId())); + } + } + + public void moveTask(Task task, TaskList preParent, TaskList curParent) + throws NetworkFailureException { + commitUpdate(); + try { + JSONObject jsPost = new JSONObject(); + JSONArray actionList = new JSONArray(); + JSONObject action = new JSONObject(); + + // action_list + action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, + GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE); + action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); + action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid()); + if (preParent == curParent && task.getPriorSibling() != null) { + // put prioring_sibing_id only if moving within the tasklist and + // it is not the first one + action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling()); + } + action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid()); + action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); + if (preParent != curParent) { + // put the dest_list only if moving between tasklists + action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid()); + } + actionList.put(action); + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); + + // client_version + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + postRequest(jsPost); + + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("move task: handing jsonobject failed"); + } + } + + public void deleteNode(Node node) throws NetworkFailureException { + commitUpdate(); + try { + JSONObject jsPost = new JSONObject(); + JSONArray actionList = new JSONArray(); + + // action_list + node.setDeleted(true); + actionList.put(node.getUpdateAction(getActionId())); + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); + + // client_version + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + postRequest(jsPost); + mUpdateArray = null; + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("delete node: handing jsonobject failed"); + } + } + + public JSONArray getTaskLists() throws NetworkFailureException { + if (!mLoggedin) { + Log.e(TAG, "please login first"); + throw new ActionFailureException("not logged in"); + } + + try { + HttpGet httpGet = new HttpGet(mGetUrl); + HttpResponse response = null; + response = mHttpClient.execute(httpGet); + + // get the task list + String resString = getResponseContent(response.getEntity()); + String jsBegin = "_setup("; + String jsEnd = ")}"; + int begin = resString.indexOf(jsBegin); + int end = resString.lastIndexOf(jsEnd); + String jsString = null; + if (begin != -1 && end != -1 && begin < end) { + jsString = resString.substring(begin + jsBegin.length(), end); + } + JSONObject js = new JSONObject(jsString); + return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS); + } catch (ClientProtocolException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new NetworkFailureException("gettasklists: httpget failed"); + } catch (IOException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new NetworkFailureException("gettasklists: httpget failed"); + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("get task lists: handing jasonobject failed"); + } + } + + public JSONArray getTaskList(String listGid) throws NetworkFailureException { + commitUpdate(); + try { + JSONObject jsPost = new JSONObject(); + JSONArray actionList = new JSONArray(); + JSONObject action = new JSONObject(); + + // action_list + action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, + GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL); + action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); + action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid); + action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false); + actionList.put(action); + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); + + // client_version + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + JSONObject jsResponse = postRequest(jsPost); + return jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_TASKS); + } catch (JSONException e) { + Log.e(TAG, e.toString()); + e.printStackTrace(); + throw new ActionFailureException("get task list: handing jsonobject failed"); + } + } + + public Account getSyncAccount() { + return mAccount; + } + + public void resetUpdateArray() { + mUpdateArray = null; + } +} diff --git a/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskManager.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskManager.java similarity index 56% rename from src/Notes-master/src/net/micode/notes/gtask/remote/GTaskManager.java rename to code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskManager.java index 83b6a11..d2b4082 100644 --- a/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskManager.java +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskManager.java @@ -1,54 +1,31 @@ /* - * 版权所有 (c) 2010-2011, MiCode 开源社区 (www.micode.net) + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * - * 根据 Apache 许可证,第 2.0 版(“许可证”)许可; - * 除非遵循许可证,否则不得使用此文件。 - * 可以在以下网址获取许可证副本: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * 除非适用于相关法律或书面协议,否则根据许可证分发的软件 - * 是以“原样”基础提供,不提供任何形式的保证或条件,无论是明示的还是暗示的。 - * 请参阅许可证以了解特定语言管理权限和 - * 许可证下的限制。 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -// 定义包 package net.micode.notes.gtask.remote; -// 导入需要的类 -import android.app.Activity; // 用于活动管理的类 -import android.content.ContentResolver; // 用于内容提供者的类 -import android.content.ContentUris; // 处理内容 URI 的工具类 -import android.content.ContentValues; // 包含 ContentProvider 插入或更新所需值的类 -import android.content.Context; // 应用上下文类 -import android.database.Cursor; // 数据库查询结果的类 -import android.util.Log; // 记录日志的工具类 +import android.app.Activity; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.util.Log; -// 导入项目中的相关类 import net.micode.notes.R; import net.micode.notes.data.Notes; -<<<<<<< HEAD -import net.micode.notes.data.Notes.DataColumns; // 数据列常量 -import net.micode.notes.data.Notes.NoteColumns; // 笔记列常量 -import net.micode.notes.gtask.data.MetaData; // 任务元数据类 -import net.micode.notes.gtask.data.Node; // 节点类 -import net.micode.notes.gtask.data.SqlNote; // SQL 笔记类 -import net.micode.notes.gtask.data.Task; // 任务类 -import net.micode.notes.gtask.data.TaskList; // 任务列表类 -import net.micode.notes.gtask.exception.ActionFailureException; // 操作失败异常 -import net.micode.notes.gtask.exception.NetworkFailureException; // 网络失败异常 -import net.micode.notes.tool.DataUtils; // 数据工具类 -import net.micode.notes.tool.GTaskStringUtils; // GTask 字符串工具类 - -import org.json.JSONArray; // JSON 数组类 -import org.json.JSONException; // JSON 异常类 -import org.json.JSONObject; // JSON 对象类 - -import java.util.HashMap; // 哈希表实现 -import java.util.HashSet; // 哈希集合实现 -import java.util.Iterator; // 迭代器类 -======= import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.gtask.data.MetaData; @@ -70,49 +47,46 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; -// GTaskManager类用于管理与Google Tasks的同步操作,包括初始化任务列表、同步内容、处理各种同步类型的操作等功能 + public class GTaskManager { private static final String TAG = GTaskManager.class.getSimpleName(); - // 同步成功状态码 public static final int STATE_SUCCESS = 0; - // 网络错误状态码 + public static final int STATE_NETWORK_ERROR = 1; - // 内部错误状态码 + public static final int STATE_INTERNAL_ERROR = 2; - // 同步正在进行状态码 + public static final int STATE_SYNC_IN_PROGRESS = 3; - // 同步被取消状态码 + public static final int STATE_SYNC_CANCELLED = 4; private static GTaskManager mInstance = null; - // 关联的Activity,用于获取授权令牌等操作 private Activity mActivity; - // 应用上下文 + private Context mContext; - // 用于操作内容提供器,进行数据查询、更新等操作 + private ContentResolver mContentResolver; - // 标记是否正在同步 + private boolean mSyncing; - // 标记同步是否被取消 + private boolean mCancelled; - // 存储Google Tasks任务列表的哈希表,以任务列表的全局唯一ID(GID)为键,任务列表对象为值 + private HashMap mGTaskListHashMap; - // 存储Google Tasks节点(任务、任务列表等)的哈希表,以节点的全局唯一ID(GID)为键,节点对象为值 + private HashMap mGTaskHashMap; - // 存储元数据的哈希表,以相关的全局唯一ID为键,元数据对象为值 + private HashMap mMetaHashMap; - // 元数据对应的任务列表 + private TaskList mMetaList; - // 存储本地已删除记录的ID集合,用于后续清理本地数据 + private HashSet mLocalDeleteIdMap; - // 存储从Google Tasks的全局唯一ID(GID)到本地记录ID(NID)的映射关系 + private HashMap mGidToNid; - // 存储从本地记录ID(NID)到Google Tasks的全局唯一ID(GID)的映射关系 + private HashMap mNidToGid; - // 私有构造函数,初始化相关成员变量 private GTaskManager() { mSyncing = false; mCancelled = false; @@ -125,7 +99,6 @@ public class GTaskManager { mNidToGid = new HashMap(); } - // 获取GTaskManager的单例实例 public static synchronized GTaskManager getInstance() { if (mInstance == null) { mInstance = new GTaskManager(); @@ -133,13 +106,11 @@ public class GTaskManager { return mInstance; } - // 设置关联的Activity上下文,主要用于获取授权令牌等相关操作 public synchronized void setActivityContext(Activity activity) { // used for getting authtoken mActivity = activity; } - // 执行同步操作,与Google Tasks进行数据同步 public int sync(Context context, GTaskASyncTask asyncTask) { if (mSyncing) { Log.d(TAG, "Sync is in progress"); @@ -149,7 +120,6 @@ public class GTaskManager { mContentResolver = mContext.getContentResolver(); mSyncing = true; mCancelled = false; - // 清除之前同步相关的数据缓存,如任务列表、节点、元数据等的哈希表以及ID映射关系等 mGTaskListHashMap.clear(); mGTaskHashMap.clear(); mMetaHashMap.clear(); @@ -161,18 +131,18 @@ public class GTaskManager { GTaskClient client = GTaskClient.getInstance(); client.resetUpdateArray(); - // 登录Google Tasks,如果取消同步则不再进行登录操作,如果登录失败则抛出网络异常 + // login google task if (!mCancelled) { if (!client.login(mActivity)) { throw new NetworkFailureException("login google task failed"); } } - // 发布同步进度信息,初始化任务列表阶段 + // get the task list from google asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list)); initGTaskList(); - // 发布同步进度信息,进行内容同步阶段 + // do content sync work asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing)); syncContent(); } catch (NetworkFailureException e) { @@ -186,7 +156,6 @@ public class GTaskManager { e.printStackTrace(); return STATE_INTERNAL_ERROR; } finally { - // 无论同步是否成功,最终都清除同步相关的数据缓存 mGTaskListHashMap.clear(); mGTaskHashMap.clear(); mMetaHashMap.clear(); @@ -199,16 +168,14 @@ public class GTaskManager { return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; } - // 初始化Google Tasks任务列表相关信息,包括获取任务列表、元数据列表以及加载任务等操作 private void initGTaskList() throws NetworkFailureException { if (mCancelled) return; GTaskClient client = GTaskClient.getInstance(); try { - // 从Google Tasks获取任务列表信息,返回JSON数组形式的数据 JSONArray jsTaskLists = client.getTaskLists(); - // 先初始化元数据列表,查找名为特定前缀加上"meta"的任务列表作为元数据列表 + // init meta list first mMetaList = null; for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); @@ -220,7 +187,7 @@ public class GTaskManager { mMetaList = new TaskList(); mMetaList.setContentByRemoteJSON(object); - // 加载元数据,获取元数据列表对应的任务列表中的具体元数据信息 + // load meta data JSONArray jsMetas = client.getTaskList(gid); for (int j = 0; j < jsMetas.length(); j++) { object = (JSONObject) jsMetas.getJSONObject(j); @@ -236,7 +203,7 @@ public class GTaskManager { } } - // 如果元数据列表不存在,则创建一个新的元数据列表,并发送到Google Tasks服务器创建对应的任务列表 + // create meta list if not existed if (mMetaList == null) { mMetaList = new TaskList(); mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX @@ -244,7 +211,7 @@ public class GTaskManager { GTaskClient.getInstance().createTaskList(mMetaList); } - // 初始化普通任务列表,遍历获取到的任务列表信息,创建任务列表对象并加载对应的任务信息 + // init task list for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); @@ -258,7 +225,7 @@ public class GTaskManager { mGTaskListHashMap.put(gid, tasklist); mGTaskHashMap.put(gid, tasklist); - // 加载任务,获取当前任务列表对应的任务信息 + // load tasks JSONArray jsTasks = client.getTaskList(gid); for (int j = 0; j < jsTasks.length(); j++) { object = (JSONObject) jsTasks.getJSONObject(j); @@ -280,7 +247,6 @@ public class GTaskManager { } } - // 进行内容同步操作,处理本地与Google Tasks之间的数据同步,包括本地删除、文件夹同步、数据库中已有记录的同步等情况 private void syncContent() throws NetworkFailureException { int syncType; Cursor c = null; @@ -293,7 +259,7 @@ public class GTaskManager { return; } - // 处理本地已删除的笔记(记录),查询本地回收站文件夹中的记录,对比Google Tasks中的对应节点进行相应的同步操作 + // for local deleted note try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type<>? AND parent_id=?)", new String[] { @@ -320,10 +286,10 @@ public class GTaskManager { } } - // 同步文件夹相关信息 + // sync folder first syncFolder(); - // 处理数据库中已存在的笔记(记录),根据其在Google Tasks中的对应情况确定同步类型,然后进行相应的同步操作 + // for note existing in database try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type=? AND parent_id<>?)", new String[] { @@ -340,10 +306,10 @@ public class GTaskManager { syncType = node.getSyncAction(c); } else { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // 本地新增情况 + // local add syncType = Node.SYNC_ACTION_ADD_REMOTE; } else { - // 远程已删除情况 + // remote delete syncType = Node.SYNC_ACTION_DEL_LOCAL; } } @@ -360,7 +326,7 @@ public class GTaskManager { } } - // 处理剩余的在Google Tasks中存在但本地未处理的节点,进行相应的同步操作(一般是添加到本地) + // go through remaining items Iterator> iter = mGTaskHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -368,14 +334,16 @@ public class GTaskManager { doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); } - // mCancelled可能被其他线程设置,所以需要逐个检查,清除本地已删除记录的相关数据(如果同步未取消) + // mCancelled can be set by another thread, so we neet to check one by + // one + // clear local delete table if (!mCancelled) { if (!DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) { throw new ActionFailureException("failed to batch-delete local deleted notes"); } } - // 刷新本地同步ID(如果同步未取消),提交更新并进行相关操作来更新本地记录的同步ID + // refresh local sync id if (!mCancelled) { GTaskClient.getInstance().commitUpdate(); refreshLocalSyncId(); @@ -383,7 +351,6 @@ public class GTaskManager { } - // 同步文件夹相关信息,包括根文件夹、通话记录文件夹、本地已存在的文件夹以及远程新增的文件夹等情况的处理 private void syncFolder() throws NetworkFailureException { Cursor c = null; String gid; @@ -394,7 +361,7 @@ public class GTaskManager { return; } - // 处理根文件夹的同步情况,根据其在Google Tasks中的对应情况进行相应的同步操作(添加、更新等) + // for root folder try { c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null); @@ -406,7 +373,7 @@ public class GTaskManager { mGTaskHashMap.remove(gid); mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER); mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid); - // 对于系统文件夹,仅在必要时更新远程名称 + // for system folder, only update remote name if necessary if (!node.getName().equals( GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); @@ -423,101 +390,77 @@ public class GTaskManager { } } - // for call-note文件夹相关的同步操作处理 - // 查询通话记录文件夹在本地数据库中的信息,根据其在Google Tasks中的对应情况进行相应的同步操作(添加、更新等) - // 如果查询到该文件夹信息存在(即游标c不为空且能移动到下一条记录),则进一步处理 + // for call-note folder try { - // 通过ContentResolver查询本地数据库中通话记录文件夹的记录信息,指定查询条件为_id等于通话记录文件夹的特定ID c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)", new String[] { - String.valueOf(Notes.ID_CALL_RECORD_FOLDER) + String.valueOf(Notes.ID_CALL_RECORD_FOLDER) }, null); if (c != null) { if (c.moveToNext()) { - // 获取该文件夹在Google Tasks中对应的全局唯一ID(GID) gid = c.getString(SqlNote.GTASK_ID_COLUMN); - // 根据GID从存储Google Tasks节点的哈希表中获取对应的节点对象 node = mGTaskHashMap.get(gid); if (node != null) { - // 如果节点存在,从哈希表中移除该节点(表示已处理) mGTaskHashMap.remove(gid); - // 在本地ID到Google Tasks的GID映射表中记录该文件夹的映射关系,键为GID,值为通话记录文件夹的本地ID mGidToNid.put(gid, (long) Notes.ID_CALL_RECORD_FOLDER); - // 在Google Tasks的GID到本地ID映射表中记录映射关系,键为本地ID,值为GID mNidToGid.put((long) Notes.ID_CALL_RECORD_FOLDER, gid); - // 对于系统文件夹,仅在其名称与预期的通话记录文件夹名称不一致时(即可能有更新情况),进行远程更新操作 + // for system folder, only update remote name if + // necessary if (!node.getName().equals( GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); } else { - // 如果节点不存在,则执行添加远程节点的操作(意味着本地有该文件夹记录,但在Google Tasks中还未创建对应节点) doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); } } } else { - // 如果查询失败,打印警告日志 Log.w(TAG, "failed to query call note folder"); } } finally { - // 无论查询是否成功,最终都要关闭游标,释放资源,并将游标置空 if (c != null) { c.close(); c = null; } } - // 处理本地已存在的文件夹的同步情况 - // 查询本地除回收站外的文件夹记录信息,根据其在Google Tasks中的对应情况进行相应的同步操作 + // for local existing folders try { - // 通过ContentResolver查询本地数据库中符合条件的文件夹记录信息,条件为类型是文件夹且父ID不等于回收站文件夹的ID c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type=? AND parent_id<>?)", new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER) }, NoteColumns.TYPE + " DESC"); if (c != null) { while (c.moveToNext()) { - // 获取文件夹在Google Tasks中对应的全局唯一ID(GID) gid = c.getString(SqlNote.GTASK_ID_COLUMN); - // 根据GID从存储Google Tasks节点的哈希表中获取对应的节点对象 node = mGTaskHashMap.get(gid); if (node != null) { - // 如果节点存在,从哈希表中移除该节点(表示已处理) mGTaskHashMap.remove(gid); - // 在本地ID到Google Tasks的GID映射表中记录该文件夹的映射关系,键为GID,值为文件夹的本地ID mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); - // 在Google Tasks的GID到本地ID映射表中记录映射关系,键为本地ID,值为GID mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); - // 获取该节点对应的同步操作类型(根据节点和游标信息判断是添加、更新、删除等哪种类型) syncType = node.getSyncAction(c); } else { - // 如果节点不存在,根据其GID是否为空字符串判断是本地新增还是远程删除情况,进而确定同步类型 if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // 本地新增情况,同步类型设置为添加远程节点 + // local add syncType = Node.SYNC_ACTION_ADD_REMOTE; } else { - // 远程删除情况,同步类型设置为删除本地节点 + // remote delete syncType = Node.SYNC_ACTION_DEL_LOCAL; } } - // 根据确定的同步类型执行相应的内容同步操作 doContentSync(syncType, node, c); } } else { - // 如果查询失败,打印警告日志 Log.w(TAG, "failed to query existing folder"); } } finally { - // 无论查询是否成功,最终都要关闭游标,释放资源,并将游标置空 if (c != null) { c.close(); c = null; } } - // 处理远程新增文件夹的同步情况 - // 遍历存储Google Tasks任务列表的哈希表,对于在Google - // Tasks中存在但本地未处理(还在mGTaskHashMap中)的文件夹,进行添加本地节点的同步操作 + // for remote add folders Iterator> iter = mGTaskListHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -529,12 +472,10 @@ public class GTaskManager { } } - // 如果同步未被取消,提交Google Tasks客户端的更新操作(将之前暂存的更新操作发送到服务器执行) if (!mCancelled) GTaskClient.getInstance().commitUpdate(); } - // 根据给定的同步类型执行具体的内容同步操作 private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -542,16 +483,12 @@ public class GTaskManager { MetaData meta; switch (syncType) { - // 同步类型为添加本地节点,调用相应方法进行本地节点添加操作 case Node.SYNC_ACTION_ADD_LOCAL: addLocalNode(node); break; - // 同步类型为添加远程节点,调用相应方法进行远程节点添加操作,并传入节点和游标信息 case Node.SYNC_ACTION_ADD_REMOTE: addRemoteNode(node, c); break; - // 同步类型为删除本地节点,先从元数据哈希表中获取对应的元数据,若存在则调用Google Tasks客户端删除该元数据节点, - // 同时将本地记录的ID添加到本地已删除记录集合中 case Node.SYNC_ACTION_DEL_LOCAL: meta = mMetaHashMap.get(c.getString(SqlNote.GTASK_ID_COLUMN)); if (meta != null) { @@ -559,8 +496,6 @@ public class GTaskManager { } mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); break; - // 同步类型为删除远程节点,先从元数据哈希表中获取对应节点的元数据,若存在则调用Google Tasks客户端删除该元数据节点, - // 然后再删除该节点本身 case Node.SYNC_ACTION_DEL_REMOTE: meta = mMetaHashMap.get(node.getGid()); if (meta != null) { @@ -568,66 +503,51 @@ public class GTaskManager { } GTaskClient.getInstance().deleteNode(node); break; - // 同步类型为更新本地节点,调用相应方法进行本地节点更新操作,并传入节点和游标信息 case Node.SYNC_ACTION_UPDATE_LOCAL: updateLocalNode(node, c); break; - // 同步类型为更新远程节点,调用相应方法进行远程节点更新操作,并传入节点和游标信息 case Node.SYNC_ACTION_UPDATE_REMOTE: updateRemoteNode(node, c); break; - // 同步类型为更新冲突,目前简单采用本地更新的方式(可能后续可以考虑合并修改等更好的处理方式),调用远程节点更新方法 case Node.SYNC_ACTION_UPDATE_CONFLICT: // merging both modifications maybe a good idea // right now just use local update simply updateRemoteNode(node, c); break; - // 同步类型为无操作,直接跳过不做任何处理 case Node.SYNC_ACTION_NONE: break; - // 同步类型为错误或其他未知类型,抛出操作失败异常,表示遇到了未知的同步操作类型 case Node.SYNC_ACTION_ERROR: default: throw new ActionFailureException("unkown sync action type"); } } - // 添加本地节点的操作方法 private void addLocalNode(Node node) throws NetworkFailureException { if (mCancelled) { return; } SqlNote sqlNote; - // 如果节点是任务列表类型(TaskList) if (node instanceof TaskList) { - // 如果节点名称是默认根文件夹的名称,创建一个对应根文件夹的SqlNote对象,传入上下文和根文件夹的本地ID if (node.getName().equals( GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) { sqlNote = new SqlNote(mContext, Notes.ID_ROOT_FOLDER); } else if (node.getName().equals( GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) { - // 如果节点名称是通话记录文件夹的名称,创建一个对应通话记录文件夹的SqlNote对象,传入上下文和通话记录文件夹的本地ID sqlNote = new SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER); } else { - // 其他普通任务列表情况,创建一个新的SqlNote对象,传入上下文 sqlNote = new SqlNote(mContext); - // 设置SqlNote的内容为节点的本地JSON格式内容(从节点获取) sqlNote.setContent(node.getLocalJSONFromContent()); - // 设置父ID为根文件夹的本地ID sqlNote.setParentId(Notes.ID_ROOT_FOLDER); } } else { - // 如果节点是普通任务(Task)类型,创建一个新的SqlNote对象,传入上下文 sqlNote = new SqlNote(mContext); JSONObject js = node.getLocalJSONFromContent(); try { - // 如果节点的本地JSON数据中包含特定的笔记头部信息(META_HEAD_NOTE) if (js.has(GTaskStringUtils.META_HEAD_NOTE)) { JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); if (note.has(NoteColumns.ID)) { long id = note.getLong(NoteColumns.ID); - // 检查该笔记ID在本地笔记数据库中是否已存在,如果存在则移除该ID(可能需要重新生成新的ID) if (DataUtils.existInNoteDatabase(mContentResolver, id)) { // the id is not available, have to create a new one note.remove(NoteColumns.ID); @@ -635,14 +555,12 @@ public class GTaskManager { } } - // 如果节点的本地JSON数据中包含特定的数据头部信息(META_HEAD_DATA) if (js.has(GTaskStringUtils.META_HEAD_DATA)) { JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); for (int i = 0; i < dataArray.length(); i++) { JSONObject data = dataArray.getJSONObject(i); if (data.has(DataColumns.ID)) { long dataId = data.getLong(DataColumns.ID); - // 检查该数据ID在本地数据数据库中是否已存在,如果存在则移除该ID(可能需要重新生成新的ID) if (DataUtils.existInDataDatabase(mContentResolver, dataId)) { // the data id is not available, have to create // a new one @@ -656,43 +574,36 @@ public class GTaskManager { Log.w(TAG, e.toString()); e.printStackTrace(); } - // 设置SqlNote的内容为处理后的JSON数据 sqlNote.setContent(js); - // 获取任务节点的父节点在本地ID到Google Tasks的GID映射表中的对应父ID,如果不存在则抛出异常表示找不到本地父ID Long parentId = mGidToNid.get(((Task) node).getParent().getGid()); if (parentId == null) { Log.e(TAG, "cannot find task's parent id locally"); throw new ActionFailureException("cannot add local node"); } - // 设置SqlNote的父ID为获取到的父节点的本地ID sqlNote.setParentId(parentId.longValue()); } - // 设置SqlNote的Google Tasks全局唯一ID(GID)为节点的GID + // create the local node sqlNote.setGtaskId(node.getGid()); - // 将SqlNote对象提交保存到本地数据库(传入参数false可能表示不触发某些额外的相关操作) sqlNote.commit(false); - // 在本地ID到Google Tasks的GID映射表中记录该节点的映射关系,键为节点的GID,值为SqlNote的本地ID + // update gid-nid mapping mGidToNid.put(node.getGid(), sqlNote.getId()); - // 在Google Tasks的GID到本地ID映射表中记录映射关系,键为SqlNote的本地ID,值为节点的GID mNidToGid.put(sqlNote.getId(), node.getGid()); - // 更新远程元数据,传入节点的GID和对应的SqlNote对象 + // update meta updateRemoteMeta(node.getGid(), sqlNote); } - // 更新本地节点的操作方法 private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; } SqlNote sqlNote; - // 根据传入的上下文和游标信息创建一个新的SqlNote对象,用于更新本地节点信息 + // update the note locally sqlNote = new SqlNote(mContext, c); - // 设置SqlNote的内容为节点的本地JSON格式内容(从节点获取) sqlNote.setContent(node.getLocalJSONFromContent()); Long parentId = (node instanceof Task) ? mGidToNid.get(((Task) node).getParent().getGid()) @@ -701,16 +612,13 @@ public class GTaskManager { Log.e(TAG, "cannot find task's parent id locally"); throw new ActionFailureException("cannot update local node"); } - // 设置SqlNote的父ID为获取到的父节点的本地ID sqlNote.setParentId(parentId.longValue()); - // 将更新后的SqlNote对象提交保存到本地数据库(传入参数true可能表示触发某些额外的相关操作) sqlNote.commit(true); - // 更新远程元数据,传入节点的GID和对应的SqlNote对象 + // update meta info updateRemoteMeta(node.getGid(), sqlNote); } - // 添加远程节点的操作方法 private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -719,10 +627,9 @@ public class GTaskManager { SqlNote sqlNote = new SqlNote(mContext, c); Node n; - // 如果SqlNote对应的是笔记类型(即普通任务) + // update remotely if (sqlNote.isNoteType()) { Task task = new Task(); - // 设置任务的内容为从本地SqlNote获取的JSON格式内容 task.setContentByLocalJSON(sqlNote.getContent()); String parentGid = mNidToGid.get(sqlNote.getParentId()); @@ -730,20 +637,17 @@ public class GTaskManager { Log.e(TAG, "cannot find task's parent tasklist"); throw new ActionFailureException("cannot add remote task"); } - // 将任务添加到对应的父任务列表中(通过本地ID到Google Tasks的GID映射表找到父任务列表) mGTaskListHashMap.get(parentGid).addChildTask(task); - // 通过Google Tasks客户端创建该任务(发送到服务器创建对应的任务节点) GTaskClient.getInstance().createTask(task); n = (Node) task; - // 更新远程元数据,传入任务的GID和对应的SqlNote对象 + // add meta updateRemoteMeta(task.getGid(), sqlNote); } else { TaskList tasklist = null; - // 构建文件夹名称,先添加特定的前缀,然后根据SqlNote的本地ID判断是否是根文件夹或通话记录文件夹,添加相应的后缀名称, - // 否则添加SqlNote的摘要信息作为后缀 + // we need to skip folder if it has already existed String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX; if (sqlNote.getId() == Notes.ID_ROOT_FOLDER) folderName += GTaskStringUtils.FOLDER_DEFAULT; @@ -752,166 +656,121 @@ public class GTaskManager { else folderName += sqlNote.getSnippet(); - // 遍历存储Google Tasks任务列表的哈希表(mGTaskListHashMap)的迭代器 Iterator> iter = mGTaskListHashMap.entrySet().iterator(); while (iter.hasNext()) { - // 获取哈希表中的每一个键值对,键是任务列表的全局唯一ID(GID),值是对应的任务列表对象(TaskList) Map.Entry entry = iter.next(); String gid = entry.getKey(); TaskList list = entry.getValue(); - // 判断当前任务列表的名称是否与之前构建的文件夹名称(folderName)相等 if (list.getName().equals(folderName)) { - // 如果相等,说明找到了对应的任务列表,将其赋值给tasklist变量 tasklist = list; - // 如果在存储Google Tasks节点的哈希表(mGTaskHashMap)中包含该任务列表的GID,说明已经处理过,将其移除 if (mGTaskHashMap.containsKey(gid)) { mGTaskHashMap.remove(gid); } - // 找到匹配的任务列表后就可以结束循环了 break; } } - // 如果经过上述查找没有找到匹配的任务列表(tasklist仍为null),则创建一个新的任务列表对象 + // no match we can add now if (tasklist == null) { tasklist = new TaskList(); - // 设置新任务列表的内容为从本地SqlNote获取的JSON格式内容 tasklist.setContentByLocalJSON(sqlNote.getContent()); - // 通过Google Tasks客户端创建该任务列表(发送到服务器创建对应的任务列表节点) GTaskClient.getInstance().createTaskList(tasklist); - // 将新创建的任务列表添加到存储Google Tasks任务列表的哈希表中,键为任务列表的GID,值为任务列表对象 mGTaskListHashMap.put(tasklist.getGid(), tasklist); } - // 将创建或找到的任务列表对象转换为Node类型并赋值给n(因为Node是更通用的节点类型,TaskList是一种特殊的Node) n = (Node) tasklist; } - // 更新本地笔记相关信息 - // 设置本地SqlNote的Google Tasks全局唯一ID(GID)为n的GID,即与远程任务列表或任务对应的GID保持一致 + // update local note sqlNote.setGtaskId(n.getGid()); - // 将SqlNote对象提交保存到本地数据库(传入参数false可能表示不触发某些额外的相关操作,此处用于保存基本的关联信息等) sqlNote.commit(false); - // 重置本地修改标志(可能表示将本地记录标记为已与远程同步,不再是本地修改状态) sqlNote.resetLocalModified(); - // 再次提交保存SqlNote对象到本地数据库(传入参数true可能表示触发一些更新相关的额外操作,确保修改标志等信息更新成功) sqlNote.commit(true); - // gid-id映射更新 - // 在本地ID到Google Tasks的GID映射表(mGidToNid)中记录该节点(n)的映射关系,键为节点的GID,值为SqlNote的本地ID + // gid-id mapping mGidToNid.put(n.getGid(), sqlNote.getId()); - // 在Google Tasks的GID到本地ID映射表(mNidToGid)中记录映射关系,键为SqlNote的本地ID,值为节点的GID mNidToGid.put(sqlNote.getId(), n.getGid()); } - // 更新远程节点的操作方法 private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; } - // 根据传入的上下文和游标信息创建一个新的SqlNote对象,用于后续操作 SqlNote sqlNote = new SqlNote(mContext, c); - // 远程更新操作 - // 设置远程节点(node)的内容为从本地SqlNote获取的JSON格式内容,即将本地修改同步到远程节点 + // update remotely node.setContentByLocalJSON(sqlNote.getContent()); - // 通过Google Tasks客户端将更新后的节点添加到更新队列中(后续会批量提交更新到服务器) GTaskClient.getInstance().addUpdateNode(node); - // 更新远程元数据,传入节点的GID和对应的SqlNote对象 + // update meta updateRemoteMeta(node.getGid(), sqlNote); - // 如果SqlNote对应的是笔记类型(即普通任务),则可能需要处理任务移动相关操作 + // move task if necessary if (sqlNote.isNoteType()) { Task task = (Task) node; - // 获取任务当前的父任务列表 TaskList preParentList = task.getParent(); - // 通过本地ID到Google Tasks的GID映射表,根据本地记录的父ID获取当前任务在远程对应的父任务列表的GID String curParentGid = mNidToGid.get(sqlNote.getParentId()); if (curParentGid == null) { Log.e(TAG, "cannot find task's parent tasklist"); throw new ActionFailureException("cannot update remote task"); } - // 根据获取到的GID从存储Google Tasks任务列表的哈希表中获取当前任务在远程对应的父任务列表对象 TaskList curParentList = mGTaskListHashMap.get(curParentGid); - // 如果当前任务的前后父任务列表不一致,说明任务需要在远程进行移动操作 if (preParentList != curParentList) { - // 先从原父任务列表中移除该任务 preParentList.removeChildTask(task); - // 将任务添加到新的父任务列表中 curParentList.addChildTask(task); - // 通过Google Tasks客户端执行任务移动操作,告知服务器任务在远程的位置变更 GTaskClient.getInstance().moveTask(task, preParentList, curParentList); } } - // 清除本地修改标志,标记本地记录已同步到远程,不再处于本地修改状态 + // clear local modified flag sqlNote.resetLocalModified(); - // 将更新后的SqlNote对象提交保存到本地数据库(传入参数true可能表示触发一些更新相关的额外操作,确保修改标志等信息更新成功) sqlNote.commit(true); } - // 更新远程元数据的操作方法 private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { if (sqlNote != null && sqlNote.isNoteType()) { - // 从存储元数据的哈希表(mMetaHashMap)中根据GID获取对应的元数据对象(MetaData) MetaData metaData = mMetaHashMap.get(gid); if (metaData != null) { - // 如果元数据对象存在,设置其元数据内容,传入GID和从本地SqlNote获取的JSON格式内容 metaData.setMeta(gid, sqlNote.getContent()); - // 通过Google Tasks客户端将更新后的元数据添加到更新队列中(后续会批量提交更新到服务器) GTaskClient.getInstance().addUpdateNode(metaData); } else { - // 如果元数据对象不存在,则创建一个新的元数据对象 metaData = new MetaData(); - // 设置新元数据对象的元数据内容,传入GID和从本地SqlNote获取的JSON格式内容 metaData.setMeta(gid, sqlNote.getContent()); - // 将新创建的元数据对象添加到元数据列表(mMetaList)中作为子任务(从逻辑上关联起来) mMetaList.addChildTask(metaData); - // 将新创建的元数据对象添加到存储元数据的哈希表中,键为GID,值为元数据对象 mMetaHashMap.put(gid, metaData); - // 通过Google Tasks客户端创建该元数据任务(发送到服务器创建对应的元数据节点) GTaskClient.getInstance().createTask(metaData); } } } - // 刷新本地同步ID的操作方法 private void refreshLocalSyncId() throws NetworkFailureException { if (mCancelled) { return; } - // 为了获取最新的Google Tasks列表信息,先清空之前存储相关信息的哈希表 + // get the latest gtask list mGTaskHashMap.clear(); mGTaskListHashMap.clear(); mMetaHashMap.clear(); - // 重新初始化Google Tasks列表信息(重新获取任务列表、元数据等相关内容) initGTaskList(); Cursor c = null; try { - // 通过ContentResolver查询本地数据库中除系统类型且不在回收站的笔记记录信息,按照类型降序排列 c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type<>? AND parent_id<>?)", new String[] { String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER) }, NoteColumns.TYPE + " DESC"); if (c != null) { while (c.moveToNext()) { - // 获取笔记在Google Tasks中对应的全局唯一ID(GID) String gid = c.getString(SqlNote.GTASK_ID_COLUMN); - // 根据GID从存储Google Tasks节点的哈希表中获取对应的节点对象 Node node = mGTaskHashMap.get(gid); if (node != null) { - // 如果节点存在,从哈希表中移除该节点(表示已处理) mGTaskHashMap.remove(gid); - // 创建一个ContentValues对象用于存放要更新的数据,此处将同步ID设置为节点的最后修改时间 ContentValues values = new ContentValues(); values.put(NoteColumns.SYNC_ID, node.getLastModified()); - // 通过ContentResolver更新本地数据库中对应笔记的记录,设置同步ID字段的值 mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(SqlNote.ID_COLUMN)), values, null, null); } else { @@ -924,7 +783,6 @@ public class GTaskManager { Log.w(TAG, "failed to query local note to refresh sync id"); } } finally { - // 无论查询是否成功,最终都要关闭游标,释放资源,并将游标置空 if (c != null) { c.close(); c = null; @@ -932,14 +790,11 @@ public class GTaskManager { } } - // 获取同步账户名称的方法,通过Google Tasks客户端获取同步账户对象,并返回其名称 public String getSyncAccount() { return GTaskClient.getInstance().getSyncAccount().name; } - // 取消同步的方法,将表示同步是否取消的标志(mCancelled)设置为true,其他相关操作可以根据该标志来判断是否停止执行 public void cancelSync() { mCancelled = true; } } ->>>>>>> a495b394fa4686564cc2bfe7d054eb66276713ae diff --git a/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskSyncService.java b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskSyncService.java new file mode 100644 index 0000000..cca36f7 --- /dev/null +++ b/code-reading-minote/src/Notes-master/src/net/micode/notes/gtask/remote/GTaskSyncService.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.gtask.remote; + +import android.app.Activity; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; + +public class GTaskSyncService extends Service { + public final static String ACTION_STRING_NAME = "sync_action_type"; + + public final static int ACTION_START_SYNC = 0; + + public final static int ACTION_CANCEL_SYNC = 1; + + public final static int ACTION_INVALID = 2; + + public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service"; + + public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing"; + + public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg"; + + private static GTaskASyncTask mSyncTask = null; + + private static String mSyncProgress = ""; + + private void startSync() { + if (mSyncTask == null) { + mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() { + public void onComplete() { + mSyncTask = null; + sendBroadcast(""); + stopSelf(); + } + }); + sendBroadcast(""); + mSyncTask.execute(); + } + } + + private void cancelSync() { + if (mSyncTask != null) { + mSyncTask.cancelSync(); + } + } + + @Override + public void onCreate() { + mSyncTask = null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Bundle bundle = intent.getExtras(); + if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) { + switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) { + case ACTION_START_SYNC: + startSync(); + break; + case ACTION_CANCEL_SYNC: + cancelSync(); + break; + default: + break; + } + return START_STICKY; + } + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onLowMemory() { + if (mSyncTask != null) { + mSyncTask.cancelSync(); + } + } + + public IBinder onBind(Intent intent) { + return null; + } + + public void sendBroadcast(String msg) { + mSyncProgress = msg; + Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); + intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null); + intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg); + sendBroadcast(intent); + } + + public static void startSync(Activity activity) { + GTaskManager.getInstance().setActivityContext(activity); + Intent intent = new Intent(activity, GTaskSyncService.class); + intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC); + activity.startService(intent); + } + + public static void cancelSync(Context context) { + Intent intent = new Intent(context, GTaskSyncService.class); + intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC); + context.startService(intent); + } + + public static boolean isSyncing() { + return mSyncTask != null; + } + + public static String getProgressString() { + return mSyncProgress; + } +} diff --git a/doc/minode.docx b/doc/minode.docx deleted file mode 100644 index 6e006c9..0000000 Binary files a/doc/minode.docx and /dev/null differ diff --git a/doc/minode2.docx b/doc/minode2.docx deleted file mode 100644 index 681b31f..0000000 Binary files a/doc/minode2.docx and /dev/null differ diff --git a/doc/summary.md b/doc/summary.md deleted file mode 100644 index e69de29..0000000 diff --git a/doc/小米便签开源软件泛读报告文档(1).docx b/doc/小米便签开源软件泛读报告文档(1).docx deleted file mode 100644 index 473000d..0000000 Binary files a/doc/小米便签开源软件泛读报告文档(1).docx and /dev/null differ diff --git a/https:/github.com/MiCode/Notes b/https:/github.com/MiCode/Notes deleted file mode 100644 index e69de29..0000000 diff --git a/src/Notes-master/.gitignore b/src/Notes-master/.gitignore deleted file mode 100644 index 7df8dff..0000000 --- a/src/Notes-master/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# generated files -bin/ -gen/ - -# Local configuration file (sdk path, etc) -project.properties -.settings/ -.classpath -.project diff --git a/src/Notes-master/AndroidManifest.xml b/src/Notes-master/AndroidManifest.xml deleted file mode 100644 index e5c7d47..0000000 --- a/src/Notes-master/AndroidManifest.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Notes-master/NOTICE b/src/Notes-master/NOTICE deleted file mode 100644 index 9a54521..0000000 --- a/src/Notes-master/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/src/Notes-master/README b/src/Notes-master/README deleted file mode 100644 index fc0d824..0000000 --- a/src/Notes-master/README +++ /dev/null @@ -1,23 +0,0 @@ -[中文] - -1. MiCode便签是小米便签的社区开源版,由MIUI团队(www.miui.com) 发起并贡献第一批代码,遵循NOTICE文件所描述的开源协议, - 今后为MiCode社区(www.micode.net) 拥有,并由社区发布和维护。 - -2. Bug反馈和跟踪,请访问Github, - https://github.com/MiCode/Notes/issues?sort=created&direction=desc&state=open - -3. 功能建议和综合讨论,请访问MiCode, - http://micode.net/forum.php?mod=forumdisplay&fid=38 - - -[English] - -1. MiCode Notes is open source edition of XM notepad, it's first initiated and sponsored by MIUI team (www.miui.com). - It's opened under license described by NOTICE file. It's owned by the MiCode community (www.micode.net). In future, - the MiCode community will release and maintain this project. - -2. Regarding issue tracking, please visit Github, - https://github.com/MiCode/Notes/issues?sort=created&direction=desc&state=open - -3. Regarding feature request and general discussion, please visit Micode forum, - http://micode.net/forum.php?mod=forumdisplay&fid=38 diff --git a/src/Notes-master/res/color/primary_text_dark.xml b/src/Notes-master/res/color/primary_text_dark.xml deleted file mode 100644 index 7c85459..0000000 --- a/src/Notes-master/res/color/primary_text_dark.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Notes-master/res/color/secondary_text_dark.xml b/src/Notes-master/res/color/secondary_text_dark.xml deleted file mode 100644 index c1c2384..0000000 --- a/src/Notes-master/res/color/secondary_text_dark.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/Notes-master/res/drawable-hdpi/bg_btn_set_color.png b/src/Notes-master/res/drawable-hdpi/bg_btn_set_color.png deleted file mode 100644 index 5eb5d44..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/bg_btn_set_color.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/bg_color_btn_mask.png b/src/Notes-master/res/drawable-hdpi/bg_color_btn_mask.png deleted file mode 100644 index 100db77..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/bg_color_btn_mask.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/call_record.png b/src/Notes-master/res/drawable-hdpi/call_record.png deleted file mode 100644 index fb88ca4..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/call_record.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/clock.png b/src/Notes-master/res/drawable-hdpi/clock.png deleted file mode 100644 index 5f2ae9a..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/clock.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/delete.png b/src/Notes-master/res/drawable-hdpi/delete.png deleted file mode 100644 index 643de3e..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/delete.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/dropdown_icon.9.png b/src/Notes-master/res/drawable-hdpi/dropdown_icon.9.png deleted file mode 100644 index 5525025..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/dropdown_icon.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_blue.9.png b/src/Notes-master/res/drawable-hdpi/edit_blue.9.png deleted file mode 100644 index 55a1856..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_blue.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_green.9.png b/src/Notes-master/res/drawable-hdpi/edit_green.9.png deleted file mode 100644 index 2cb2d60..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_green.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_red.9.png b/src/Notes-master/res/drawable-hdpi/edit_red.9.png deleted file mode 100644 index bae944a..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_red.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_title_blue.9.png b/src/Notes-master/res/drawable-hdpi/edit_title_blue.9.png deleted file mode 100644 index 96e6092..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_title_blue.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_title_green.9.png b/src/Notes-master/res/drawable-hdpi/edit_title_green.9.png deleted file mode 100644 index 08d8644..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_title_green.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_title_red.9.png b/src/Notes-master/res/drawable-hdpi/edit_title_red.9.png deleted file mode 100644 index 9c430e5..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_title_red.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_title_white.9.png b/src/Notes-master/res/drawable-hdpi/edit_title_white.9.png deleted file mode 100644 index 19e8d95..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_title_white.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_title_yellow.9.png b/src/Notes-master/res/drawable-hdpi/edit_title_yellow.9.png deleted file mode 100644 index bf8f580..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_title_yellow.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_white.9.png b/src/Notes-master/res/drawable-hdpi/edit_white.9.png deleted file mode 100644 index 918f7a6..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_white.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/edit_yellow.9.png b/src/Notes-master/res/drawable-hdpi/edit_yellow.9.png deleted file mode 100644 index 10cb642..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/edit_yellow.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/font_large.png b/src/Notes-master/res/drawable-hdpi/font_large.png deleted file mode 100644 index 78cf2e6..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/font_large.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/font_normal.png b/src/Notes-master/res/drawable-hdpi/font_normal.png deleted file mode 100644 index 9de7ced..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/font_normal.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/font_size_selector_bg.9.png b/src/Notes-master/res/drawable-hdpi/font_size_selector_bg.9.png deleted file mode 100644 index be8e64c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/font_size_selector_bg.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/font_small.png b/src/Notes-master/res/drawable-hdpi/font_small.png deleted file mode 100644 index d3ff104..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/font_small.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/font_super.png b/src/Notes-master/res/drawable-hdpi/font_super.png deleted file mode 100644 index 85b13a1..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/font_super.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/icon_app.png b/src/Notes-master/res/drawable-hdpi/icon_app.png deleted file mode 100644 index 418aadc..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/icon_app.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_background.png b/src/Notes-master/res/drawable-hdpi/list_background.png deleted file mode 100644 index 087e1f9..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_background.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_blue_down.9.png b/src/Notes-master/res/drawable-hdpi/list_blue_down.9.png deleted file mode 100644 index b88eebf..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_blue_down.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_blue_middle.9.png b/src/Notes-master/res/drawable-hdpi/list_blue_middle.9.png deleted file mode 100644 index 96b1c8b..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_blue_middle.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_blue_single.9.png b/src/Notes-master/res/drawable-hdpi/list_blue_single.9.png deleted file mode 100644 index d7e7206..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_blue_single.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_blue_up.9.png b/src/Notes-master/res/drawable-hdpi/list_blue_up.9.png deleted file mode 100644 index 632e88c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_blue_up.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_folder.9.png b/src/Notes-master/res/drawable-hdpi/list_folder.9.png deleted file mode 100644 index 829f61b..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_folder.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_footer_bg.9.png b/src/Notes-master/res/drawable-hdpi/list_footer_bg.9.png deleted file mode 100644 index 5325c25..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_footer_bg.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_green_down.9.png b/src/Notes-master/res/drawable-hdpi/list_green_down.9.png deleted file mode 100644 index 64a39d9..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_green_down.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_green_middle.9.png b/src/Notes-master/res/drawable-hdpi/list_green_middle.9.png deleted file mode 100644 index 897325a..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_green_middle.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_green_single.9.png b/src/Notes-master/res/drawable-hdpi/list_green_single.9.png deleted file mode 100644 index c83405f..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_green_single.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_green_up.9.png b/src/Notes-master/res/drawable-hdpi/list_green_up.9.png deleted file mode 100644 index 141f9e1..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_green_up.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_red_down.9.png b/src/Notes-master/res/drawable-hdpi/list_red_down.9.png deleted file mode 100644 index 4224309..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_red_down.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_red_middle.9.png b/src/Notes-master/res/drawable-hdpi/list_red_middle.9.png deleted file mode 100644 index 9988f17..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_red_middle.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_red_single.9.png b/src/Notes-master/res/drawable-hdpi/list_red_single.9.png deleted file mode 100644 index 587c348..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_red_single.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_red_up.9.png b/src/Notes-master/res/drawable-hdpi/list_red_up.9.png deleted file mode 100644 index 46b4757..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_red_up.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_white_down.9.png b/src/Notes-master/res/drawable-hdpi/list_white_down.9.png deleted file mode 100644 index 29f9d8c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_white_down.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_white_middle.9.png b/src/Notes-master/res/drawable-hdpi/list_white_middle.9.png deleted file mode 100644 index 77a4ab4..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_white_middle.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_white_single.9.png b/src/Notes-master/res/drawable-hdpi/list_white_single.9.png deleted file mode 100644 index 3e79189..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_white_single.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_white_up.9.png b/src/Notes-master/res/drawable-hdpi/list_white_up.9.png deleted file mode 100644 index e23cd5c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_white_up.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_yellow_down.9.png b/src/Notes-master/res/drawable-hdpi/list_yellow_down.9.png deleted file mode 100644 index 31cfc1e..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_yellow_down.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_yellow_middle.9.png b/src/Notes-master/res/drawable-hdpi/list_yellow_middle.9.png deleted file mode 100644 index b6549b2..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_yellow_middle.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_yellow_single.9.png b/src/Notes-master/res/drawable-hdpi/list_yellow_single.9.png deleted file mode 100644 index 3faf507..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_yellow_single.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/list_yellow_up.9.png b/src/Notes-master/res/drawable-hdpi/list_yellow_up.9.png deleted file mode 100644 index 4ae791c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/list_yellow_up.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/menu_delete.png b/src/Notes-master/res/drawable-hdpi/menu_delete.png deleted file mode 100644 index ccdfc4b..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/menu_delete.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/menu_move.png b/src/Notes-master/res/drawable-hdpi/menu_move.png deleted file mode 100644 index 1140b71..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/menu_move.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/new_note_normal.png b/src/Notes-master/res/drawable-hdpi/new_note_normal.png deleted file mode 100644 index e24e0d1..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/new_note_normal.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/new_note_pressed.png b/src/Notes-master/res/drawable-hdpi/new_note_pressed.png deleted file mode 100644 index c748936..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/new_note_pressed.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/note_edit_color_selector_panel.png b/src/Notes-master/res/drawable-hdpi/note_edit_color_selector_panel.png deleted file mode 100644 index fc49552..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/note_edit_color_selector_panel.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/notification.png b/src/Notes-master/res/drawable-hdpi/notification.png deleted file mode 100644 index b13ab4a..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/notification.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/search_result.png b/src/Notes-master/res/drawable-hdpi/search_result.png deleted file mode 100644 index ff2befd..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/search_result.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/selected.png b/src/Notes-master/res/drawable-hdpi/selected.png deleted file mode 100644 index b889bef..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/selected.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/title_alert.png b/src/Notes-master/res/drawable-hdpi/title_alert.png deleted file mode 100644 index 544ee9c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/title_alert.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/title_bar_bg.9.png b/src/Notes-master/res/drawable-hdpi/title_bar_bg.9.png deleted file mode 100644 index eb6bff0..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/title_bar_bg.9.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_2x_blue.png b/src/Notes-master/res/drawable-hdpi/widget_2x_blue.png deleted file mode 100644 index a1707f4..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_2x_blue.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_2x_green.png b/src/Notes-master/res/drawable-hdpi/widget_2x_green.png deleted file mode 100644 index f86886c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_2x_green.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_2x_red.png b/src/Notes-master/res/drawable-hdpi/widget_2x_red.png deleted file mode 100644 index 0e66c29..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_2x_red.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_2x_white.png b/src/Notes-master/res/drawable-hdpi/widget_2x_white.png deleted file mode 100644 index 5f0619a..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_2x_white.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_2x_yellow.png b/src/Notes-master/res/drawable-hdpi/widget_2x_yellow.png deleted file mode 100644 index 12d1c2b..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_2x_yellow.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_4x_blue.png b/src/Notes-master/res/drawable-hdpi/widget_4x_blue.png deleted file mode 100644 index 9183738..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_4x_blue.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_4x_green.png b/src/Notes-master/res/drawable-hdpi/widget_4x_green.png deleted file mode 100644 index fa8b452..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_4x_green.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_4x_red.png b/src/Notes-master/res/drawable-hdpi/widget_4x_red.png deleted file mode 100644 index 62de074..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_4x_red.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_4x_white.png b/src/Notes-master/res/drawable-hdpi/widget_4x_white.png deleted file mode 100644 index a37d67c..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_4x_white.png and /dev/null differ diff --git a/src/Notes-master/res/drawable-hdpi/widget_4x_yellow.png b/src/Notes-master/res/drawable-hdpi/widget_4x_yellow.png deleted file mode 100644 index d7c5fa4..0000000 Binary files a/src/Notes-master/res/drawable-hdpi/widget_4x_yellow.png and /dev/null differ diff --git a/src/Notes-master/res/drawable/new_note.xml b/src/Notes-master/res/drawable/new_note.xml deleted file mode 100644 index 2154ebc..0000000 --- a/src/Notes-master/res/drawable/new_note.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - diff --git a/src/Notes-master/res/layout/account_dialog_title.xml b/src/Notes-master/res/layout/account_dialog_title.xml deleted file mode 100644 index 7717112..0000000 --- a/src/Notes-master/res/layout/account_dialog_title.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/Notes-master/res/layout/add_account_text.xml b/src/Notes-master/res/layout/add_account_text.xml deleted file mode 100644 index c799178..0000000 --- a/src/Notes-master/res/layout/add_account_text.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Notes-master/res/layout/datetime_picker.xml b/src/Notes-master/res/layout/datetime_picker.xml deleted file mode 100644 index f10d592..0000000 --- a/src/Notes-master/res/layout/datetime_picker.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Notes-master/res/layout/dialog_edit_text.xml b/src/Notes-master/res/layout/dialog_edit_text.xml deleted file mode 100644 index 361b39a..0000000 --- a/src/Notes-master/res/layout/dialog_edit_text.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/Notes-master/res/layout/folder_list_item.xml b/src/Notes-master/res/layout/folder_list_item.xml deleted file mode 100644 index 77e8148..0000000 --- a/src/Notes-master/res/layout/folder_list_item.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Notes-master/res/layout/note_edit.xml b/src/Notes-master/res/layout/note_edit.xml deleted file mode 100644 index 10b2aa7..0000000 --- a/src/Notes-master/res/layout/note_edit.xml +++ /dev/null @@ -1,400 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Notes-master/res/layout/note_edit_list_item.xml b/src/Notes-master/res/layout/note_edit_list_item.xml deleted file mode 100644 index a885f9c..0000000 --- a/src/Notes-master/res/layout/note_edit_list_item.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - diff --git a/src/Notes-master/res/layout/note_item.xml b/src/Notes-master/res/layout/note_item.xml deleted file mode 100644 index d541f6a..0000000 --- a/src/Notes-master/res/layout/note_item.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Notes-master/res/layout/note_list.xml b/src/Notes-master/res/layout/note_list.xml deleted file mode 100644 index 6b25d38..0000000 --- a/src/Notes-master/res/layout/note_list.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - -