diff --git a/src/Notes-master/src/net/micode/notes/data/Contact.java b/src/Notes-master/src/net/micode/notes/data/Contact.java index 479516d..7313e80 100644 --- a/src/Notes-master/src/net/micode/notes/data/Contact.java +++ b/src/Notes-master/src/net/micode/notes/data/Contact.java @@ -26,13 +26,14 @@ import android.util.Log; import java.util.HashMap; /** - * 联系人查询工具类。 - *

职责:根据电话号码在系统通讯录中查找联系人姓名,并通过内存缓存减少重复查询。

- *

使用场景:通话记录笔记等功能需要把电话号码转成可读的联系人姓名。

+ * 联系人查询工具类 + * 核心功能:在小米便签中用于智能识别电话号码并显示联系人名称 + * 实现方法:通过电话号码查询系统联系人的姓名,并通过哈希表缓存查询结果,避免重复查询,提升性能 */ public class Contact { - /** 联系人缓存,用于提高查询效率,key 为原始电话号码字符串,value 为联系人姓名 */ + // 功能:缓存查询结果,,暂时存储电话号码与联系人的映射关系,避免重复查询,节省开销 private static HashMap sContactCache; + // 日志标签 private static final String TAG = "Contact"; /** @@ -45,6 +46,20 @@ public class Contact { + "(SELECT raw_contact_id " + " FROM phone_lookup" + " WHERE min_match = '+')"; + /** + * SQL语句逻辑解读 + * AND 连接一个条件与下一个条件 + * 第一个条件:PHONE_NUMBERS_EQUAL(Phone.NUMBER,?) + * PHONE_NUMBERS_EQUAL 函数:Android系统提供的特殊函数,用于查找和Phone.NUMBER相同的电话号码 + * 第二个条件:Data.MIMETYPE = 'Phone.CONTENT_ITEM_TYPE' + * 确保数据类型必须是电话号码类型 + * 第三个条件:Data.RAW_CONTACT_ID IN A + * 联系人的ID必须存在于这个表格A中 + * 表格A:(SELECT raw_contact_id FROM phone_lookup WHERE min_match = '+') + * phone_lookup:Android系统中的一个与联系人数据有关的特殊表 + * min_match:最小匹配位数 + * 预先计算一个电话号码的最小匹配形式的表格 + */ /** * 根据电话号码获取联系人姓名。 @@ -54,41 +69,50 @@ public class Contact { * @return 联系人姓名;未找到或异常时返回 null */ public static String getContact(Context context, String phoneNumber) { - // 初始化缓存:首次调用时创建,后续复用 + // 初始化查询缓存 if(sContactCache == null) { sContactCache = new HashMap(); } - // 先从缓存中查找,命中则直接返回,避免再次访问数据库 + // 检查缓存中是否已存在该电话号码的查询结果 if(sContactCache.containsKey(phoneNumber)) { return sContactCache.get(phoneNumber); } - // 构建查询条件:将占位符中的“+”替换为待查询号码的最小匹配值 + // PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)用于计算电话号码的最小匹配位数 + // 将占位符"+"替换为最小匹配数,以构建完整的查询语句 String selection = CALLER_ID_SELECTION.replace("+", PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); - // 查询联系人数据库,仅投影联系人显示名 + + /** + * 查询联系人数据库 + * context.getContentResolver().query:查询当前应用程序的数据 + */ Cursor cursor = context.getContentResolver().query( - Data.CONTENT_URI, - new String [] { Phone.DISPLAY_NAME }, - selection, - new String[] { phoneNumber }, - null); + Data.CONTENT_URI, // 查询URI + 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中 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/src/Notes-master/src/net/micode/notes/data/Notes.java b/src/Notes-master/src/net/micode/notes/data/Notes.java index 0f6e011..dda813a 100644 --- a/src/Notes-master/src/net/micode/notes/data/Notes.java +++ b/src/Notes-master/src/net/micode/notes/data/Notes.java @@ -20,38 +20,40 @@ import android.net.Uri; /** * 笔记应用的数据常量定义类。 - *

职责:集中管理 ContentProvider 相关的 URI、表字段、类型常量和系统文件夹 ID,避免硬编码分散。

- *

主要被数据层(Provider、DatabaseHelper)和业务层(UI、同步)引用。

+ * 功能:集中管理 ContentProvider 相关的 URI、表字段、类型常量和系统文件夹 ID,避免硬编码分散。 + * 主要被数据层(Provider、DatabaseHelper)和业务层(UI、GTASK)引用。 */ public class Notes { - /** ContentProvider的授权标识 */ + // ContentProvider的授权标识 public static final String AUTHORITY = "micode_notes"; + // 日志标签 public static final String TAG = "Notes"; - /** 笔记类型:普通笔记 */ + // 0类型:普通笔记 public static final int TYPE_NOTE = 0; - /** 笔记类型:文件夹 */ + // 1类型:文件夹 public static final int TYPE_FOLDER = 1; - /** 笔记类型:系统文件夹 */ + // 2类型:系统文件夹 public static final int TYPE_SYSTEM = 2; - /** - * 系统文件夹的 ID 定义。 - * - */ - /** 根文件夹ID */ + // 系统文件夹的 ID 定义。 + // #ID_ROOT_FOLDER 默认根文件夹 + // #ID_TEMPARAY_FOLDER 临时文件夹,移动笔记时的中转 + // #ID_CALL_RECORD_FOLDER 通话记录专用文件夹 + // #ID_TRASH_FOLER 回收站 public static final int ID_ROOT_FOLDER = 0; - /** 临时文件夹ID,用于存放不属于任何文件夹的笔记 */ public static final int ID_TEMPARAY_FOLDER = -1; - /** 通话记录文件夹ID */ public static final int ID_CALL_RECORD_FOLDER = -2; - /** 回收站文件夹ID */ public static final int ID_TRASH_FOLER = -3; + /** + * Intent Extra 键常量,用于在 Android 组件间通过 Intent 传递数据,包括: + * 1. 提醒日期 + * 2. 背景颜色ID + * 3. 小部件ID + * 4. 小部件类型 + * 5. 文件夹ID + * 6. 通话日期 + */ 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"; @@ -59,220 +61,171 @@ public class Notes { 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"; - /** 无效的小部件类型 */ + // 无效的小部件类型 -1 public static final int TYPE_WIDGET_INVALIDE = -1; - /** 2x2小部件类型 */ + // 2x2小部件类型 0 public static final int TYPE_WIDGET_2X = 0; - /** 4x4小部件类型 */ + // 4x4小部件类型 1 public static final int TYPE_WIDGET_4X = 1; - /** 数据类型常量,指明不同数据行的 MIME 类型 */ + // 数据类型常量,指明不同数据行的 MIME(Multipurpose Internet Mail Extensions,用于标识 ContentProvider 返回的数据类型。) public static class DataConstants { - /** 普通笔记的MIME类型 */ + // 普通笔记的MIME类型 public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; - /** 通话记录笔记的MIME类型 */ + // 通话记录笔记的MIME类型 public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; } - /** 查询所有笔记和文件夹的URI */ + // URI 是 ContentProvider 的标准访问入口,用于统一访问应用的数据。 + // 查询所有笔记和文件夹的URI public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); - /** 查询数据表的URI */ + // 查询数据表的URI public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); - /** 笔记表的列名接口,声明 note 表包含的所有字段 */ + /** + * NoteColumns 接口 - 便签表(notes表)列定义 + * 定义了便签和文件夹数据库表的所有列名和类型 + */ public interface NoteColumns { - /** - * 行的唯一ID,类型: INTEGER (long) - */ + + // 行的唯一ID public static final String ID = "_id"; - /** - * 笔记或文件夹的父ID,类型: INTEGER (long) - */ + // 笔记或文件夹的父ID public static final String PARENT_ID = "parent_id"; - /** - * 笔记或文件夹的创建日期,类型: INTEGER (long) - */ + // 笔记或文件夹的创建日期 public static final String CREATED_DATE = "created_date"; - /** - * 最后修改日期,类型: INTEGER (long) - */ + // 最后修改日期 public static final String MODIFIED_DATE = "modified_date"; - - /** - * 提醒日期,类型: INTEGER (long) - */ + // 提醒日期 public static final String ALERTED_DATE = "alert_date"; - /** - * 文件夹名称或笔记的文本内容摘要,类型: TEXT - */ + // 文件夹名称或笔记的文本内容摘要 public static final String SNIPPET = "snippet"; - /** - * 笔记的小部件ID,类型: INTEGER (long) - */ + // 笔记的小部件ID public static final String WIDGET_ID = "widget_id"; - /** - * 笔记的小部件类型,类型: INTEGER (long) - */ + // 笔记的小部件类型 public static final String WIDGET_TYPE = "widget_type"; - /** - * 笔记的背景颜色ID,类型: INTEGER (long) - */ + // 笔记的背景颜色ID public static final String BG_COLOR_ID = "bg_color_id"; - /** - * 是否有附件,类型: INTEGER;对于文本笔记没有附件,多媒体笔记至少有一个附件 - */ + // 是否有附件;对于文本笔记没有附件,多媒体笔记至少有一个附件 public static final String HAS_ATTACHMENT = "has_attachment"; - /** - * 文件夹中的笔记数量,类型: INTEGER (long) - */ + // 文件夹中的笔记数量 public static final String NOTES_COUNT = "notes_count"; - /** - * 文件类型:文件夹或笔记,类型: INTEGER - */ + // 文件类型:文件夹或笔记 public static final String TYPE = "type"; - /** - * 最后一次同步的ID,类型: INTEGER (long) - */ + // 最后一次同步的ID public static final String SYNC_ID = "sync_id"; - /** - * 标记是否在本地被修改,类型: INTEGER - */ + // 标记是否在本地被修改 public static final String LOCAL_MODIFIED = "local_modified"; - /** - * 移动到临时文件夹之前的原始父ID,类型: INTEGER - */ + // 移动到临时文件夹之前的原始父ID public static final String ORIGIN_PARENT_ID = "origin_parent_id"; - /** - * Google Task的ID,类型: TEXT - */ + // Google Task的ID public static final String GTASK_ID = "gtask_id"; - /** - * 版本号,类型: INTEGER (long) - */ + // 版本号 public static final String VERSION = "version"; } - /** - * 数据表的列名接口 + /** + * DataColumns 接口 - 便签数据表(data表)列定义 + * 定义了便签详细内容的数据表列名和类型 + * 使用MIME_TYPE字段区分不同类型的便签数据(文本便签、通话记录等) */ public interface DataColumns { - /** - * 行的唯一ID,类型: INTEGER (long) - */ + // 行的唯一ID public static final String ID = "_id"; - /** - * 该行数据项的MIME类型,类型: TEXT - */ + // 该行数据项的MIME类型 public static final String MIME_TYPE = "mime_type"; - /** - * 该数据所属笔记的引用ID,类型: INTEGER (long) - */ + // 该数据所属笔记的引用ID public static final String NOTE_ID = "note_id"; - /** - * 笔记或文件夹的创建日期,类型: INTEGER (long) - */ + // 笔记或文件夹的创建日期 public static final String CREATED_DATE = "created_date"; - /** - * 最后修改日期,类型: INTEGER (long) - */ + // 最后修改日期 public static final String MODIFIED_DATE = "modified_date"; - /** - * 数据内容,类型: TEXT - */ + // 数据内容 public static final String CONTENT = "content"; - - /** - * 通用数据列1,含义由{@link #MIME_TYPE}决定,用于存储整数类型数据,类型: INTEGER - */ + // 通用数据列1 public static final String DATA1 = "data1"; - /** - * 通用数据列2,含义由{@link #MIME_TYPE}决定,用于存储整数类型数据,类型: INTEGER - */ + // 通用数据列2 public static final String DATA2 = "data2"; - /** - * 通用数据列3,含义由{@link #MIME_TYPE}决定,用于存储TEXT类型数据,类型: TEXT - */ + // 通用数据列3 public static final String DATA3 = "data3"; - /** - * 通用数据列4,含义由{@link #MIME_TYPE}决定,用于存储TEXT类型数据,类型: TEXT - */ + // 通用数据列4 public static final String DATA4 = "data4"; - /** - * 通用数据列5,含义由{@link #MIME_TYPE}决定,用于存储TEXT类型数据,类型: TEXT - */ + // 通用数据列5 public static final String DATA5 = "data5"; } /** - * 文本笔记的数据列定义 + * TextNote 类 - 文本便签数据定义 + * 定义了文本便签特有的数据列和URI */ public static final class TextNote implements DataColumns { - /** - * 模式标识:文本是否为清单模式,类型: Integer(1 清单模式,0 普通模式) - */ + // 模式标识:文本是否为清单模式 public static final String MODE = DATA1; - /** 清单模式常量 */ + // 清单模式常量 public static final int MODE_CHECK_LIST = 1; + + // 普通模式常量 + public static final int MODE_NORMAL = 0; - /** 文本笔记的目录MIME类型 */ + // 文本笔记的目录MIME类型 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; - /** 文本笔记的单项MIME类型 */ + // 文本笔记的单项MIME类型 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; - /** 文本笔记的URI */ + // 文本笔记的URI public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); } /** - * 通话记录笔记的数据列定义 + * CallNote 类 - 通话记录便签数据定义 + * 定义了通话记录便签特有的数据列和URI */ public static final class CallNote implements DataColumns { - /** - * 通话日期,类型: INTEGER (long) - */ + // 通话日期 public static final String CALL_DATE = DATA1; - /** - * 电话号码,类型: TEXT - */ + // 电话号码 public static final String PHONE_NUMBER = DATA3; - /** 通话记录笔记的目录MIME类型 */ + // 联系人姓名 + public static final String CONTACT_NAME = DATA4; + + // 通话记录笔记的目录MIME类型 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; - /** 通话记录笔记的单项MIME类型 */ + // 通话记录笔记的单项MIME类型 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; - /** 通话记录笔记的URI */ + // 通话记录笔记的URI public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); } } diff --git a/src/Notes-master/src/net/micode/notes/data/NotesProvider.java b/src/Notes-master/src/net/micode/notes/data/NotesProvider.java index 50b5876..57f6937 100644 --- a/src/Notes-master/src/net/micode/notes/data/NotesProvider.java +++ b/src/Notes-master/src/net/micode/notes/data/NotesProvider.java @@ -35,30 +35,32 @@ import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.NotesDatabaseHelper.TABLE; /** - * 笔记内容提供者。 - *

职责:对外暴露笔记与数据表的 CRUD、搜索、以及通知能力;封装 URI 匹配和权限检查。

- *

使用场景:UI、同步服务等通过 ContentResolver 访问笔记内容,统一走此 Provider。

+ * 笔记内容提供者,继承自 ContentProvider + * 功能:提供笔记数据的增删改查、搜索功能,以及数据变化通知;根据不同的访问地址(URI)找到对应的数据,并检查访问权限。 + * 使用场景:UI界面、同步服务等通过 ContentResolver 访问笔记内容,统一走此 Provider。 + * ContentResolver:客户端接口,用于访问 ContentProvider 的数据。 + * :客户端与 ContentProvider 之间的桥梁。 */ public class NotesProvider extends ContentProvider { private static final UriMatcher mMatcher; - /** 数据库帮助类实例,负责获取读写数据库 */ + // 数据库帮助类实例,负责获取读写数据库 private NotesDatabaseHelper mHelper; private static final String TAG = "NotesProvider"; - /** URI匹配码:笔记列表 */ + // URI匹配码:笔记列表 private static final int URI_NOTE = 1; - /** URI匹配码:单个笔记 */ + // URI匹配码:单个笔记 private static final int URI_NOTE_ITEM = 2; - /** URI匹配码:数据列表 */ + // URI匹配码:数据列表 private static final int URI_DATA = 3; - /** URI匹配码:单个数据项 */ + // URI匹配码:单个数据项 private static final int URI_DATA_ITEM = 4; - /** URI匹配码:搜索 */ + // URI匹配码:搜索 private static final int URI_SEARCH = 5; - /** URI匹配码:搜索建议 */ + // URI匹配码:搜索建议 private static final int URI_SEARCH_SUGGEST = 6; static { @@ -74,7 +76,7 @@ public class NotesProvider extends ContentProvider { /** * 笔记搜索投影字段。 - *

x'0A' 代表 SQLite 中的换行符;搜索时去掉换行与空格,便于列表展示更多内容。

+ * x'0A' 代表 SQLite 中的换行符;搜索时去掉换行与空格,便于列表展示更多内容。 */ private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," @@ -101,7 +103,7 @@ public class NotesProvider extends ContentProvider { /** * 查询数据。 - *

支持 note/data 全表与单行查询,以及搜索入口。

+ * 支持 note/data 全表与单行查询,以及搜索入口。 */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, @@ -255,7 +257,7 @@ public class NotesProvider extends ContentProvider { /** * 更新数据。 - *

更新 note 时会先自增 version 字段,便于同步冲突检测;data 更新同样通知 note 列表刷新。

+ * 更新 note 时会先自增 version 字段,便于同步冲突检测;data 更新同样通知 note 列表刷新。 */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {