diff --git a/src/model/WorkingNote.java b/src/model/WorkingNote.java index be081e4..2d108a6 100644 --- a/src/model/WorkingNote.java +++ b/src/model/WorkingNote.java @@ -32,105 +32,143 @@ import net.micode.notes.data.Notes.TextNote; import net.micode.notes.tool.ResourceParser.NoteBgResources; +/** + * 工作笔记类,用于管理笔记的详细信息和状态。 + */ public class WorkingNote { - // Note for the working note + // 笔记对象 private Note mNote; - // Note Id + // 笔记ID private long mNoteId; - // Note content + // 笔记内容 private String mContent; - // Note mode + // 笔记模式 private int mMode; + // 笔记提醒日期 private long mAlertDate; + // 笔记最后修改日期 private long mModifiedDate; + // 笔记背景颜色ID private int mBgColorId; + // 笔记小部件ID private int mWidgetId; + // 笔记小部件类型 private int mWidgetType; + // 笔记所属文件夹ID private long mFolderId; + // 上下文对象,用于访问应用的资源和类 private Context mContext; + // 日志标签,用于日志输出 private static final String TAG = "WorkingNote"; + // 标记笔记是否已删除 private boolean mIsDeleted; + // 笔记设置更改监听器 private NoteSettingChangedListener mNoteSettingStatusListener; + /** + * 数据查询时需要的列。 + */ public static final String[] DATA_PROJECTION = new String[] { - DataColumns.ID, - DataColumns.CONTENT, - DataColumns.MIME_TYPE, - DataColumns.DATA1, - DataColumns.DATA2, - DataColumns.DATA3, - DataColumns.DATA4, + DataColumns.ID, // 数据ID + DataColumns.CONTENT, // 数据内容 + DataColumns.MIME_TYPE, // 数据MIME类型 + DataColumns.DATA1, // 数据字段1 + DataColumns.DATA2, // 数据字段2 + DataColumns.DATA3, // 数据字段3 + DataColumns.DATA4 // 数据字段4 }; + /** + * 笔记查询时需要的列。 + */ public static final String[] NOTE_PROJECTION = new String[] { - NoteColumns.PARENT_ID, - NoteColumns.ALERTED_DATE, - NoteColumns.BG_COLOR_ID, - NoteColumns.WIDGET_ID, - NoteColumns.WIDGET_TYPE, - NoteColumns.MODIFIED_DATE + NoteColumns.PARENT_ID, // 笔记父ID(所属文件夹ID) + NoteColumns.ALERTED_DATE, // 笔记提醒日期 + NoteColumns.BG_COLOR_ID, // 笔记背景颜色ID + NoteColumns.WIDGET_ID, // 笔记小部件ID + NoteColumns.WIDGET_TYPE, // 笔记小部件类型 + NoteColumns.MODIFIED_DATE // 笔记最后修改日期 }; - private static final int DATA_ID_COLUMN = 0; - - private static final int DATA_CONTENT_COLUMN = 1; - - private static final int DATA_MIME_TYPE_COLUMN = 2; - - private static final int DATA_MODE_COLUMN = 3; - - private static final int NOTE_PARENT_ID_COLUMN = 0; - - private static final int NOTE_ALERTED_DATE_COLUMN = 1; - - private static final int NOTE_BG_COLOR_ID_COLUMN = 2; - - private static final int NOTE_WIDGET_ID_COLUMN = 3; - - private static final int NOTE_WIDGET_TYPE_COLUMN = 4; - - private static final int NOTE_MODIFIED_DATE_COLUMN = 5; + /** + * 数据查询结果列的索引。 + */ + private static final int DATA_ID_COLUMN = 0; // 数据ID列索引 + private static final int DATA_CONTENT_COLUMN = 1; // 数据内容列索引 + private static final int DATA_MIME_TYPE_COLUMN = 2; // 数据MIME类型列索引 + private static final int DATA_MODE_COLUMN = 3; // 数据模式列索引 + private static final int NOTE_PARENT_ID_COLUMN = 0; // 笔记父ID列索引 + private static final int NOTE_ALERTED_DATE_COLUMN = 1; // 笔记提醒日期列索引 + private static final int NOTE_BG_COLOR_ID_COLUMN = 2; // 笔记背景颜色ID列索引 + private static final int NOTE_WIDGET_ID_COLUMN = 3; // 笔记小部件ID列索引 + private static final int NOTE_WIDGET_TYPE_COLUMN = 4; // 笔记小部件类型列索引 + private static final int NOTE_MODIFIED_DATE_COLUMN = 5; // 笔记最后修改日期列索引 +} - // New note construct private WorkingNote(Context context, long folderId) { + // 初始化上下文对象,用于后续访问应用的资源和类 mContext = context; + // 初始化提醒日期为0,表示没有设置提醒 mAlertDate = 0; + // 初始化最后修改日期为当前时间戳 mModifiedDate = System.currentTimeMillis(); + // 设置笔记所属的文件夹ID mFolderId = folderId; + // 创建一个新的Note对象,用于存储笔记的详细信息 mNote = new Note(); + // 初始化笔记ID为0,表示这是一个新笔记,尚未保存到数据库 mNoteId = 0; + // 标记笔记为未删除状态 mIsDeleted = false; + // 初始化笔记模式为0,具体模式根据应用需求定义 mMode = 0; + // 设置小部件类型为无效类型,表示这个笔记还没有关联的小部件 mWidgetType = Notes.TYPE_WIDGET_INVALIDE; } // Existing note construct private WorkingNote(Context context, long noteId, long folderId) { + // 初始化上下文对象,用于后续访问应用的资源和类 mContext = context; + // 设置笔记ID mNoteId = noteId; + // 设置笔记所属的文件夹ID mFolderId = folderId; + // 标记笔记为未删除状态 mIsDeleted = false; + // 创建一个新的Note对象,用于存储笔记的详细信息 mNote = new Note(); + // 加载笔记的详细信息 loadNote(); } - + + /** + * 加载笔记的详细信息。 + */ private void loadNote() { + // 根据笔记ID查询笔记的详细信息 Cursor cursor = mContext.getContentResolver().query( - ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, - null, null); - + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), // 构建笔记的内容URI + NOTE_PROJECTION, // 查询需要的列 + null, // 查询条件 + null, // 查询参数 + null); // 排序参数 + + // 如果查询结果不为空 if (cursor != null) { + // 如果查询结果至少有一条数据 if (cursor.moveToFirst()) { + // 从查询结果中获取笔记的详细信息并设置到成员变量 mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); @@ -138,84 +176,104 @@ public class WorkingNote { mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); } - cursor.close(); + cursor.close(); // 关闭游标 } else { + // 如果查询结果为空,记录错误日志并抛出异常 Log.e(TAG, "No note with id:" + mNoteId); throw new IllegalArgumentException("Unable to find note with id " + mNoteId); } + // 加载笔记的数据内容 loadNoteData(); } private void loadNoteData() { + // 通过内容解析器查询笔记数据URI,获取与当前笔记ID关联的数据 Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { - String.valueOf(mNoteId) + String.valueOf(mNoteId) // 查询参数,当前笔记的ID }, null); - + + // 如果查询结果不为空 if (cursor != null) { + // 如果查询结果至少有一条数据 if (cursor.moveToFirst()) { + // 遍历查询结果 do { + // 获取数据项的MIME类型 String type = cursor.getString(DATA_MIME_TYPE_COLUMN); + // 根据MIME类型处理数据 if (DataConstants.NOTE.equals(type)) { + // 如果是普通笔记类型,设置笔记的内容和模式 mContent = cursor.getString(DATA_CONTENT_COLUMN); mMode = cursor.getInt(DATA_MODE_COLUMN); mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN)); } else if (DataConstants.CALL_NOTE.equals(type)) { + // 如果是通话笔记类型,设置通话数据ID mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); } else { + // 如果遇到未知的笔记类型,记录日志 Log.d(TAG, "Wrong note type with type:" + type); } - } while (cursor.moveToNext()); + } while (cursor.moveToNext()); // 移动到下一条数据 } - cursor.close(); + cursor.close(); // 关闭游标 } else { + // 如果查询结果为空,记录错误日志并抛出异常 Log.e(TAG, "No data with id:" + mNoteId); throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); } } - public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, - int widgetType, int defaultBgColorId) { - WorkingNote note = new WorkingNote(context, folderId); - note.setBgColorId(defaultBgColorId); - note.setWidgetId(widgetId); - note.setWidgetType(widgetType); - return note; + public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,int widgetType, int defaultBgColorId) { + WorkingNote note = new WorkingNote(context, folderId); // 创建一个新的WorkingNote实例 + note.setBgColorId(defaultBgColorId); // 设置笔记的背景颜色ID + note.setWidgetId(widgetId); // 设置笔记的小部件ID + note.setWidgetType(widgetType); // 设置笔记的小部件类型 + return note; // 返回新创建的笔记实例 } - public static WorkingNote load(Context context, long id) { - return new WorkingNote(context, id, 0); + return new WorkingNote(context, id, 0); // 创建并返回一个新的WorkingNote实例 } - public synchronized boolean saveNote() { + // 检查笔记是否值得保存 if (isWorthSaving()) { + // 如果笔记在数据库中不存在 if (!existInDatabase()) { + // 尝试获取一个新的笔记ID if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { - Log.e(TAG, "Create new note fail with id:" + mNoteId); - return false; + Log.e(TAG, "Create new note fail with id:" + mNoteId); // 如果创建失败,记录错误日志 + return false; // 返回false } } - + + // 同步笔记到数据库 mNote.syncNote(mContext, mNoteId); - + /** - * Update widget content if there exist any widget of this note + * 如果笔记有关联的小部件,并且设置了监听器,则通知小部件内容已更改。 */ if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID && mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) { - mNoteSettingStatusListener.onWidgetChanged(); + mNoteSettingStatusListener.onWidgetChanged(); // 通知小部件更改 } - return true; + return true; // 返回true,表示保存成功 } else { - return false; + return false; // 如果笔记不值得保存,返回false } } + /** + * 检查笔记ID是否大于0,即笔记是否存在于数据库中。 + */ public boolean existInDatabase() { return mNoteId > 0; } + /** + * 判断笔记是否值得保存。 + * @return 如果笔记被标记为删除,或者内容为空(对于新笔记),或者笔记未被修改(对于已存在的笔记),则返回false;否则返回true。 + */ private boolean isWorthSaving() { if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) || (existInDatabase() && !mNote.isLocalModified())) { @@ -225,10 +283,16 @@ public class WorkingNote { } } + /** + * 设置笔记设置状态改变的监听器。 + */ public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { mNoteSettingStatusListener = l; } + /** + * 设置提醒日期并根据需要更新小部件。 + */ public void setAlertDate(long date, boolean set) { if (date != mAlertDate) { mAlertDate = date; @@ -239,14 +303,20 @@ public class WorkingNote { } } + /** + * 标记笔记为删除或未删除状态,并更新小部件。 + */ public void markDeleted(boolean mark) { mIsDeleted = mark; if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID && mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) { - mNoteSettingStatusListener.onWidgetChanged(); + mNoteSettingStatusListener.onWidgetChanged(); } } + /** + * 设置笔记的背景颜色ID,并更新小部件。 + */ public void setBgColorId(int id) { if (id != mBgColorId) { mBgColorId = id; @@ -257,6 +327,9 @@ public class WorkingNote { } } + /** + * 设置笔记的检查列表模式,并更新小部件。 + */ public void setCheckListMode(int mode) { if (mMode != mode) { if (mNoteSettingStatusListener != null) { @@ -267,6 +340,9 @@ public class WorkingNote { } } + /** + * 设置笔记的小部件类型。 + */ public void setWidgetType(int type) { if (type != mWidgetType) { mWidgetType = type; @@ -274,6 +350,9 @@ public class WorkingNote { } } + /** + * 设置笔记的小部件ID。 + */ public void setWidgetId(int id) { if (id != mWidgetId) { mWidgetId = id; @@ -281,6 +360,9 @@ public class WorkingNote { } } + /** + * 设置笔记的工作文本,并更新数据库。 + */ public void setWorkingText(String text) { if (!TextUtils.equals(mContent, text)) { mContent = text; @@ -288,80 +370,120 @@ public class WorkingNote { } } + /** + * 将笔记转换为通话记录笔记。 + */ public void convertToCallNote(String phoneNumber, long callDate) { mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); } + /** + * 检查笔记是否有时钟提醒。 + */ public boolean hasClockAlert() { return (mAlertDate > 0 ? true : false); } + /** + * 获取笔记的内容。 + */ public String getContent() { return mContent; } + /** + * 获取笔记的提醒日期。 + */ public long getAlertDate() { return mAlertDate; } + /** + * 获取笔记的最后修改日期。 + */ public long getModifiedDate() { return mModifiedDate; } + /** + * 获取笔记背景颜色的资源ID。 + */ public int getBgColorResId() { return NoteBgResources.getNoteBgResource(mBgColorId); } + /** + * 获取笔记的背景颜色ID。 + */ public int getBgColorId() { return mBgColorId; } + /** + * 获取笔记标题背景的资源ID。 + */ public int getTitleBgResId() { return NoteBgResources.getNoteTitleBgResource(mBgColorId); } + /** + * 获取笔记的检查列表模式。 + */ public int getCheckListMode() { return mMode; } + /** + * 获取笔记的ID。 + */ public long getNoteId() { return mNoteId; } + /** + * 获取笔记所属文件夹的ID。 + */ public long getFolderId() { return mFolderId; } + /** + * 获取笔记的小部件ID。 + */ public int getWidgetId() { return mWidgetId; } + /** + * 获取笔记的小部件类型。 + */ public int getWidgetType() { return mWidgetType; } + /** + * 笔记设置更改监听器接口,用于监听笔记设置的变化。 + */ public interface NoteSettingChangedListener { /** - * Called when the background color of current note has just changed + * 当前笔记的背景颜色刚刚发生变化时调用。 */ void onBackgroundColorChanged(); /** - * Called when user set clock + * 用户设置时钟提醒时调用。 */ void onClockAlertChanged(long date, boolean set); /** - * Call when user create note from widget + * 用户从一个小部件创建笔记时调用。 */ void onWidgetChanged(); /** - * Call when switch between check list mode and normal mode - * @param oldMode is previous mode before change - * @param newMode is new mode + * 在检查列表模式和普通模式之间切换时调用。 */ void onCheckListModeChanged(int oldMode, int newMode); } diff --git a/src/tool/BackupUtils.java b/src/tool/BackupUtils.java index 39f6ec4..95f8df0 100644 --- a/src/tool/BackupUtils.java +++ b/src/tool/BackupUtils.java @@ -37,123 +37,190 @@ import java.io.PrintStream; public class BackupUtils { + /** + * 这是一个工具类,用于备份和恢复数据。 + */ private static final String TAG = "BackupUtils"; + // Singleton stuff + /** + * 单例模式,用于确保BackupUtils类只有一个实例。 + */ private static BackupUtils sInstance; + /** + * 获取BackupUtils类的单例对象。 + * @param context 上下文对象,用于访问应用的资源和类。 + * @return BackupUtils类的单例对象。 + */ public static synchronized BackupUtils getInstance(Context context) { if (sInstance == null) { - sInstance = new BackupUtils(context); + sInstance = new BackupUtils(context); // 如果实例不存在,则创建一个新的实例。 } - return sInstance; + return sInstance; // 返回单例对象。 } /** - * Following states are signs to represents backup or restore - * status + * 定义备份或恢复状态的常量。 */ // Currently, the sdcard is not mounted - public static final int STATE_SD_CARD_UNMOUONTED = 0; + public static final int STATE_SD_CARD_UNMOUONTED = 0; // SD卡未挂载。 // The backup file not exist - public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; + public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; // 备份文件不存在。 // The data is not well formated, may be changed by other programs - public static final int STATE_DATA_DESTROIED = 2; + public static final int STATE_DATA_DESTROIED = 2; // 数据格式不正确,可能被其他程序修改。 // Some run-time exception which causes restore or backup fails - public static final int STATE_SYSTEM_ERROR = 3; + public static final int STATE_SYSTEM_ERROR = 3; // 运行时异常导致备份或恢复失败。 // Backup or restore success - public static final int STATE_SUCCESS = 4; + public static final int STATE_SUCCESS = 4; // 备份或恢复成功。 + /** + * TextExport类的实例,用于将数据导出为文本。 + */ private TextExport mTextExport; + /** + * BackupUtils类的构造函数。 + * @param context 上下文对象,用于访问应用的资源和类。 + */ private BackupUtils(Context context) { - mTextExport = new TextExport(context); + mTextExport = new TextExport(context); // 初始化TextExport对象。 } + /** + * 检查外部存储是否可用。 + * @return 如果外部存储可用,返回true;否则返回false。 + */ private static boolean externalStorageAvailable() { - return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); // 检查外部存储状态是否为已挂载。 } + /** + * 导出数据为文本。 + * @return 返回导出操作的状态码。 + */ public int exportToText() { - return mTextExport.exportToText(); + return mTextExport.exportToText(); // 调用TextExport对象的exportToText方法。 } + /** + * 获取导出文本文件的文件名。 + * @return 返回导出文本文件的文件名。 + */ public String getExportedTextFileName() { - return mTextExport.mFileName; + return mTextExport.mFileName; // 返回TextExport对象的文件名。 } + /** + * 获取导出文本文件的目录。 + * @return 返回导出文本文件的目录。 + */ public String getExportedTextFileDir() { - return mTextExport.mFileDirectory; + return mTextExport.mFileDirectory; // 返回TextExport对象的文件目录。 } + /** + * 私有静态内部类,用于将数据导出为文本格式。 + */ private static class TextExport { - private static final String[] NOTE_PROJECTION = { - NoteColumns.ID, - NoteColumns.MODIFIED_DATE, - NoteColumns.SNIPPET, - NoteColumns.TYPE - }; - - private static final int NOTE_COLUMN_ID = 0; - - private static final int NOTE_COLUMN_MODIFIED_DATE = 1; - - private static final int NOTE_COLUMN_SNIPPET = 2; - - private static final String[] DATA_PROJECTION = { - DataColumns.CONTENT, - DataColumns.MIME_TYPE, - DataColumns.DATA1, - DataColumns.DATA2, - DataColumns.DATA3, - DataColumns.DATA4, - }; - - private static final int DATA_COLUMN_CONTENT = 0; + /** + * 定义查询笔记时需要的列。 + */ + private static final String[] NOTE_PROJECTION = { + NoteColumns.ID, // 笔记ID + NoteColumns.MODIFIED_DATE, // 最后修改日期 + NoteColumns.SNIPPET, // 笔记摘要 + NoteColumns.TYPE // 笔记类型 + }; - private static final int DATA_COLUMN_MIME_TYPE = 1; + /** + * 定义NOTE_PROJECTION数组中各列的索引。 + */ + private static final int NOTE_COLUMN_ID = 0; // 笔记ID列索引 + private static final int NOTE_COLUMN_MODIFIED_DATE = 1; // 最后修改日期列索引 + private static final int NOTE_COLUMN_SNIPPET = 2; // 笔记摘要列索引 + private static final int NOTE_COLUMN_TYPE = 3; // 笔记类型列索引 - private static final int DATA_COLUMN_CALL_DATE = 2; + /** + * 定义查询数据时需要的列。 + */ + private static final String[] DATA_PROJECTION = { + DataColumns.CONTENT, // 数据内容 + DataColumns.MIME_TYPE, // 数据MIME类型 + DataColumns.DATA1, // 数据字段1 + DataColumns.DATA2, // 数据字段2 + DataColumns.DATA3, // 数据字段3 + DataColumns.DATA4 // 数据字段4 + }; - private static final int DATA_COLUMN_PHONE_NUMBER = 4; + /** + * 定义DATA_PROJECTION数组中各列的索引。 + */ + private static final int DATA_COLUMN_CONTENT = 0; // 数据内容列索引 + private static final int DATA_COLUMN_MIME_TYPE = 1; // 数据MIME类型列索引 + private static final int DATA_COLUMN_CALL_DATE = 2; // 通话日期列索引(注意:这里应该是DATA3,因为DATA2和DATA3的索引被占用了) + private static final int DATA_COLUMN_PHONE_NUMBER = 4; // 电话号码列索引(注意:这里应该是DATA4,因为DATA4的索引被占用了) - private final String [] TEXT_FORMAT; - private static final int FORMAT_FOLDER_NAME = 0; - private static final int FORMAT_NOTE_DATE = 1; - private static final int FORMAT_NOTE_CONTENT = 2; + /** + * 定义导出文本的格式。 + */ + private final String[] TEXT_FORMAT; // 导出文本的格式数组 + private static final int FORMAT_FOLDER_NAME = 0; // 文件夹名称格式索引 + private static final int FORMAT_NOTE_DATE = 1; // 笔记日期格式索引 + private static final int FORMAT_NOTE_CONTENT = 2; // 笔记内容格式索引 - private Context mContext; - private String mFileName; - private String mFileDirectory; + /** + * 上下文对象,用于访问应用的资源和类。 + */ + private Context mContext; + /** + * 导出文本文件的文件名。 + */ + private String mFileName; + /** + * 导出文本文件的目录。 + */ + private String mFileDirectory; - public TextExport(Context context) { - TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); - mContext = context; - mFileName = ""; - mFileDirectory = ""; - } + /** + * TextExport类的构造函数。 + * @param context 上下文对象,用于访问应用的资源和类。 + */ + public TextExport(Context context) { + TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); // 从资源文件中获取导出文本的格式 + mContext = context; // 初始化上下文对象 + mFileName = ""; // 初始化文件名为空 + mFileDirectory = ""; // 初始化文件目录为空 + } - private String getFormat(int id) { - return TEXT_FORMAT[id]; - } + /** + * 根据ID获取对应的格式字符串。 + * @param id 格式ID。 + * @return 返回对应的格式字符串。 + */ + private String getFormat(int id) { + return TEXT_FORMAT[id]; // 返回TEXT_FORMAT数组中对应ID的格式字符串 + } + } /** * Export the folder identified by folder id to text */ private void exportFolderToText(String folderId, PrintStream ps) { - // Query notes belong to this folder + // 查询属于该文件夹的笔记 Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { folderId }, null); - + if (notesCursor != null) { if (notesCursor.moveToFirst()) { do { - // Print note's last modified date + // 打印笔记的最后修改日期 ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( mContext.getString(R.string.format_datetime_mdhm), notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); - // Query data belong to this note + // 查询属于该笔记的数据 String noteId = notesCursor.getString(NOTE_COLUMN_ID); exportNoteToText(noteId, ps); } while (notesCursor.moveToNext()); @@ -161,35 +228,37 @@ public class BackupUtils { notesCursor.close(); } } - + /** - * Export note identified by id to a print stream + * 将指定ID的笔记导出到PrintStream。 + * @param noteId 笔记ID。 + * @param ps PrintStream对象,用于输出文本数据。 */ private void exportNoteToText(String noteId, PrintStream ps) { Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { noteId }, null); - + if (dataCursor != null) { if (dataCursor.moveToFirst()) { do { String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); if (DataConstants.CALL_NOTE.equals(mimeType)) { - // Print phone number + // 打印电话号码 String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); String location = dataCursor.getString(DATA_COLUMN_CONTENT); - + if (!TextUtils.isEmpty(phoneNumber)) { ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), phoneNumber)); } - // Print call date + // 打印通话日期 ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat .format(mContext.getString(R.string.format_datetime_mdhm), callDate))); - // Print call attachment location + // 打印通话附件位置 if (!TextUtils.isEmpty(location)) { ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), location)); @@ -205,7 +274,7 @@ public class BackupUtils { } dataCursor.close(); } - // print a line separator between note + // 在笔记之间打印一个分隔符 try { ps.write(new byte[] { Character.LINE_SEPARATOR, Character.LETTER_NUMBER @@ -219,126 +288,129 @@ public class BackupUtils { * Note will be exported as text which is user readable */ public int exportToText() { + // 检查外部存储是否可用 if (!externalStorageAvailable()) { - Log.d(TAG, "Media was not mounted"); - return STATE_SD_CARD_UNMOUONTED; + Log.d(TAG, "Media was not mounted"); // 如果外部存储不可用,则记录日志 + return STATE_SD_CARD_UNMOUONTED; // 返回SD卡未挂载的状态码 } - + + // 获取用于导出文本的PrintStream对象 PrintStream ps = getExportToTextPrintStream(); if (ps == null) { - Log.e(TAG, "get print stream error"); - return STATE_SYSTEM_ERROR; + Log.e(TAG, "get print stream error"); // 如果获取PrintStream失败,则记录错误日志 + return STATE_SYSTEM_ERROR; // 返回系统错误的状态码 } - // First export folder and its notes + // 首先导出文件夹及其笔记 Cursor folderCursor = mContext.getContentResolver().query( - Notes.CONTENT_NOTE_URI, - NOTE_PROJECTION, - "(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " - + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " - + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, null, null); - + Notes.CONTENT_NOTE_URI, // 笔记内容URI + NOTE_PROJECTION, // 查询需要的列 + "(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, // 查询条件 + null, // 查询参数 + null); // 排序参数 + if (folderCursor != null) { if (folderCursor.moveToFirst()) { do { - // Print folder's name + // 打印文件夹名称 String folderName = ""; if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { - folderName = mContext.getString(R.string.call_record_folder_name); + folderName = mContext.getString(R.string.call_record_folder_name); // 获取通话记录文件夹名称 } else { - folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET); + folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET); // 获取普通文件夹名称 } if (!TextUtils.isEmpty(folderName)) { - ps.println(String.format(getFormat(FORMAT_FOLDER_NAME), folderName)); + ps.println(String.format(getFormat(FORMAT_FOLDER_NAME), folderName)); // 按照格式打印文件夹名称 } String folderId = folderCursor.getString(NOTE_COLUMN_ID); - exportFolderToText(folderId, ps); + exportFolderToText(folderId, ps); // 导出文件夹内容 } while (folderCursor.moveToNext()); } folderCursor.close(); } - - // Export notes in root's folder + + // 导出根文件夹中的笔记 Cursor noteCursor = mContext.getContentResolver().query( - Notes.CONTENT_NOTE_URI, - NOTE_PROJECTION, - NoteColumns.TYPE + "=" + +Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID - + "=0", null, null); - + Notes.CONTENT_NOTE_URI, // 笔记内容URI + NOTE_PROJECTION, // 查询需要的列 + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + "=0", // 查询条件,选择根文件夹中的笔记 + null, // 查询参数 + null); // 排序参数 + if (noteCursor != null) { if (noteCursor.moveToFirst()) { do { ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( - mContext.getString(R.string.format_datetime_mdhm), + mContext.getString(R.string.format_datetime_mdhm), // 格式化笔记最后修改日期 noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); - // Query data belong to this note + // 查询属于该笔记的数据 String noteId = noteCursor.getString(NOTE_COLUMN_ID); - exportNoteToText(noteId, ps); + exportNoteToText(noteId, ps); // 导出笔记内容 } while (noteCursor.moveToNext()); } noteCursor.close(); } - ps.close(); - - return STATE_SUCCESS; + ps.close(); // 关闭PrintStream对象 + + return STATE_SUCCESS; // 返回成功的状态码 } /** * Get a print stream pointed to the file {@generateExportedTextFile} */ private PrintStream getExportToTextPrintStream() { + // 在SD卡上生成用于导出的文件 File file = generateFileMountedOnSDcard(mContext, R.string.file_path, R.string.file_name_txt_format); if (file == null) { - Log.e(TAG, "create file to exported failed"); - return null; + Log.e(TAG, "create file to exported failed"); // 如果文件创建失败,则记录错误日志 + return null; // 返回null } - mFileName = file.getName(); - mFileDirectory = mContext.getString(R.string.file_path); - PrintStream ps = null; + mFileName = file.getName(); // 设置导出文件的文件名 + mFileDirectory = mContext.getString(R.string.file_path); // 设置导出文件的目录 + PrintStream ps = null; // 初始化PrintStream对象 try { - FileOutputStream fos = new FileOutputStream(file); - ps = new PrintStream(fos); + FileOutputStream fos = new FileOutputStream(file); // 创建文件输出流 + ps = new PrintStream(fos); // 创建PrintStream对象 } catch (FileNotFoundException e) { - e.printStackTrace(); - return null; + e.printStackTrace(); // 如果发生文件未找到异常,则打印堆栈跟踪 + return null; // 返回null } catch (NullPointerException e) { - e.printStackTrace(); - return null; + e.printStackTrace(); // 如果发生空指针异常,则打印堆栈跟踪 + return null; // 返回null } - return ps; + return ps; // 返回PrintStream对象 } - } - - /** - * Generate the text file to store imported data - */ - private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { - StringBuilder sb = new StringBuilder(); - sb.append(Environment.getExternalStorageDirectory()); - sb.append(context.getString(filePathResId)); - File filedir = new File(sb.toString()); - sb.append(context.getString( - fileNameFormatResId, - DateFormat.format(context.getString(R.string.format_date_ymd), - System.currentTimeMillis()))); - File file = new File(sb.toString()); - - try { - if (!filedir.exists()) { - filedir.mkdir(); - } - if (!file.exists()) { - file.createNewFile(); + + /** + * 在SD卡上生成用于存储导入数据的文本文件。 + */ + private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { + StringBuilder sb = new StringBuilder(); // 初始化StringBuilder对象 + sb.append(Environment.getExternalStorageDirectory()); // 追加外部存储目录 + sb.append(context.getString(filePathResId)); // 追加文件路径 + File filedir = new File(sb.toString()); // 创建文件目录对象 + sb.append(context.getString( // 追加文件名 + fileNameFormatResId, + DateFormat.format(context.getString(R.string.format_date_ymd), // 使用日期格式化文件名 + System.currentTimeMillis()))); // 使用当前时间戳 + File file = new File(sb.toString()); // 创建文件对象 + + try { + if (!filedir.exists()) { // 如果文件目录不存在,则创建目录 + filedir.mkdir(); + } + if (!file.exists()) { // 如果文件不存在,则创建文件 + file.createNewFile(); + } + return file; // 返回文件对象 + } catch (SecurityException e) { + e.printStackTrace(); // 如果发生安全异常,则打印堆栈跟踪 + } catch (IOException e) { + e.printStackTrace(); // 如果发生IO异常,则打印堆栈跟踪 } - return file; - } catch (SecurityException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; + + return null; // 如果发生异常,则返回null } } - diff --git a/src/tool/DataUtils.java b/src/tool/DataUtils.java index 2a14982..9665465 100644 --- a/src/tool/DataUtils.java +++ b/src/tool/DataUtils.java @@ -35,95 +35,158 @@ import java.util.ArrayList; import java.util.HashSet; +/** + * 数据工具类,提供对数据进行操作的静态方法。 + */ public class DataUtils { + /** + * 日志标签,用于日志输出时标识来源。 + */ public static final String TAG = "DataUtils"; + + /** + * 批量删除笔记。 + * 此方法接受一组笔记ID,并执行批量删除操作。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param ids 待删除笔记的ID集合。 + * @return 如果删除操作成功,返回true;如果失败或ID集合为空/为null,返回false。 + */ public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { + // 如果传入的ID集合为null,记录日志并返回true(视为无操作) if (ids == null) { Log.d(TAG, "the ids is null"); return true; } + // 如果ID集合大小为0,即没有ID需要删除,记录日志并返回true if (ids.size() == 0) { Log.d(TAG, "no id is in the hashset"); return true; } + // 创建操作列表,用于批量操作 ArrayList operationList = new ArrayList(); + // 遍历ID集合,为每个ID创建一个删除操作 for (long id : ids) { + // 检查是否为根文件夹ID,如果是则跳过删除 if(id == Notes.ID_ROOT_FOLDER) { Log.e(TAG, "Don't delete system folder root"); continue; } + // 创建删除操作的构建器,并添加到操作列表 ContentProviderOperation.Builder builder = ContentProviderOperation .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); operationList.add(builder.build()); } try { + // 执行批量操作 ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + // 如果结果为空或结果数组长度为0或结果数组第一个元素为null,记录日志并返回false if (results == null || results.length == 0 || results[0] == null) { Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; } + // 如果批量操作成功,返回true return true; } catch (RemoteException e) { + // 捕获并记录远程异常 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } catch (OperationApplicationException e) { + // 捕获并记录操作应用异常 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } + // 如果发生异常,返回false return false; } + /** + * 将单个笔记移动到指定文件夹。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param id 待移动笔记的ID。 + * @param srcFolderId 笔记当前所在的文件夹ID。 + * @param desFolderId 目标文件夹ID。 + */ public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { + // 创建一个ContentValues对象,用于存储需要更新的值 ContentValues values = new ContentValues(); + // 更新笔记的父文件夹ID为新的目标文件夹ID values.put(NoteColumns.PARENT_ID, desFolderId); + // 记录笔记原始的父文件夹ID values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); + // 标记笔记为本地修改,值为1 values.put(NoteColumns.LOCAL_MODIFIED, 1); + // 更新指定笔记的记录 resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); } + /** + * 批量将笔记移动到指定文件夹。 + * 此方法接受一组笔记ID,并执行批量移动操作。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param ids 待移动笔记的ID集合。 + * @param folderId 目标文件夹ID。 + * @return 如果移动操作成功,返回true;如果失败或ID集合为空/为null,返回false。 + */ public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, long folderId) { + // 如果传入的ID集合为null,记录日志并返回true(视为无操作) if (ids == null) { Log.d(TAG, "the ids is null"); return true; } + // 创建操作列表,用于批量操作 ArrayList operationList = new ArrayList(); + // 遍历ID集合,为每个ID创建一个更新操作 for (long id : ids) { + // 创建更新操作的构建器,并设置新的父文件夹ID和本地修改标记 ContentProviderOperation.Builder builder = ContentProviderOperation .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); builder.withValue(NoteColumns.PARENT_ID, folderId); builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); + // 将构建好的操作添加到操作列表 operationList.add(builder.build()); } try { + // 执行批量操作 ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); + // 如果结果为空或结果数组长度为0或结果数组第一个元素为null,记录日志并返回false if (results == null || results.length == 0 || results[0] == null) { Log.d(TAG, "delete notes failed, ids:" + ids.toString()); return false; } + // 如果批量操作成功,返回true return true; } catch (RemoteException e) { + // 捕获并记录远程异常 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } catch (OperationApplicationException e) { + // 捕获并记录操作应用异常 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); } + // 如果发生异常,返回false return false; } +} /** * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} */ public static int getUserFolderCount(ContentResolver resolver) { - Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, + // 查询数据库,获取非回收站文件夹的总数 + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, new String[] { "COUNT(*)" }, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, null); int count = 0; - if(cursor != null) { - if(cursor.moveToFirst()) { + // 如果游标不为空,移动到第一行并获取计数 + if (cursor != null) { + if (cursor.moveToFirst()) { try { count = cursor.getInt(0); } catch (IndexOutOfBoundsException e) { @@ -136,11 +199,20 @@ public class DataUtils { return count; } + /** + * 检查笔记在数据库中是否可见。 + * 根据笔记类型和笔记ID查询数据库,判断笔记是否存在。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param noteId 笔记ID。 + * @param type 笔记类型。 + * @return 如果笔记存在且可见,返回true;否则返回false。 + */ public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, - new String [] {String.valueOf(type)}, + new String[] {String.valueOf(type)}, null); boolean exist = false; @@ -153,6 +225,13 @@ public class DataUtils { return exist; } + /** + * 检查笔记ID在数据库中是否存在。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param noteId 笔记ID。 + * @return 如果笔记ID存在,返回true;否则返回false。 + */ public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null, null, null, null); @@ -167,37 +246,72 @@ public class DataUtils { return exist; } + /** + * 检查数据ID在数据库中是否存在。 + * 此方法通过查询数据库来确定特定数据ID是否存在。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param dataId 要检查的数据ID。 + * @return 如果数据ID存在,返回true;否则返回false。 + */ public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { + // 构建查询,获取特定数据ID的记录 Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null, null, null, null); boolean exist = false; + // 如果查询结果的游标不为空,处理查询结果 if (cursor != null) { + // 如果游标计数大于0,表示记录存在 if (cursor.getCount() > 0) { exist = true; } + // 关闭游标,释放资源 cursor.close(); } + // 返回是否存在的结果 return exist; } + /** + * 检查给定名称的文件夹是否在数据库中已存在。 + * 此方法查询数据库中非回收站类型的文件夹,检查是否有重名。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param name 要检查的文件夹名称。 + * @return 如果文件夹已存在,返回true;否则返回false。 + */ public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { + // 构建查询,获取特定名称的文件夹记录 Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND " + NoteColumns.SNIPPET + "=?", new String[] { name }, null); boolean exist = false; - if(cursor != null) { - if(cursor.getCount() > 0) { + // 如果查询结果的游标不为空,处理查询结果 + if (cursor != null) { + // 如果游标计数大于0,表示文件夹已存在 + if (cursor.getCount() > 0) { exist = true; } + // 关闭游标,释放资源 cursor.close(); } + // 返回文件夹是否存在的结果 return exist; } + /** + * 获取文件夹中笔记的小部件属性集合。 + * 此方法查询数据库中属于特定文件夹的所有笔记的小部件属性。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param folderId 要查询的文件夹ID。 + * @return 包含小部件属性的HashSet集合,如果文件夹ID不存在则返回null。 + */ public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) { + // 构建查询,获取特定文件夹ID下所有笔记的小部件属性 Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, NoteColumns.PARENT_ID + "=?", @@ -205,7 +319,9 @@ public class DataUtils { null); HashSet set = null; + // 如果查询结果的游标不为空,处理查询结果 if (c != null) { + // 如果游标有数据,创建HashSet集合并填充数据 if (c.moveToFirst()) { set = new HashSet(); do { @@ -219,77 +335,140 @@ public class DataUtils { } } while (c.moveToNext()); } + // 关闭游标,释放资源 c.close(); } + // 返回小部件属性集合 return set; } + /** + * 根据笔记ID获取对应的通话记录号码。 + * 此方法查询数据库中对应笔记ID的通话记录号码。 + * 如果未找到对应ID的通话记录或者查询过程中出现错误,则返回空字符串。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param noteId 要查询的笔记ID。 + * @return 对应笔记ID的通话记录号码,如果未找到或查询出错则返回空字符串。 + */ public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { + // 构建查询,获取特定笔记ID的通话记录号码 Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, - new String [] { CallNote.PHONE_NUMBER }, + new String[] { CallNote.PHONE_NUMBER }, CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", - new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, + new String[] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, null); + // 如果查询结果的游标不为空且有数据,处理查询结果 if (cursor != null && cursor.moveToFirst()) { try { + // 返回获取到的通话记录号码 return cursor.getString(0); } catch (IndexOutOfBoundsException e) { + // 如果发生索引越界异常,记录错误日志 Log.e(TAG, "Get call number fails " + e.toString()); } finally { + // 无论是否成功获取数据,都关闭游标释放资源 cursor.close(); } } + // 如果查询结果为空、查询失败或发生异常,返回空字符串 return ""; } + + /** + * 根据电话号码和通话日期获取对应的笔记ID。 + * 此方法查询数据库中符合特定电话号码和通话日期的笔记,并返回其ID。 + * 如果未找到符合条件的笔记,则返回0。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param phoneNumber 要查询的电话号码。 + * @param callDate 要查询的通话日期。 + * @return 对应电话号码和通话日期的笔记ID,如果未找到则返回0。 + */ public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { + // 构建查询,获取特定电话号码和通话日期的笔记ID Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, - new String [] { CallNote.NOTE_ID }, + new String[] { CallNote.NOTE_ID }, CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" + CallNote.PHONE_NUMBER + ",?)", - new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, + new String[] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, null); + // 如果查询结果的游标不为空,处理查询结果 if (cursor != null) { + // 如果游标有数据,移动到第一行并获取笔记ID if (cursor.moveToFirst()) { try { + // 返回获取到的笔记ID return cursor.getLong(0); } catch (IndexOutOfBoundsException e) { + // 如果发生索引越界异常,记录错误日志 Log.e(TAG, "Get call note id fails " + e.toString()); } } + // 关闭游标,释放资源 cursor.close(); } + // 如果未找到符合条件的笔记或查询过程中发生错误,返回0 return 0; } - + /** + * 根据笔记ID获取笔记的摘要。 + * 此方法查询数据库中对应ID的笔记,并获取其摘要字段。 + * 如果未找到对应ID的笔记,则抛出IllegalArgumentException异常。 + * + * @param resolver ContentResolver实例,用于访问数据库。 + * @param noteId 要查询的笔记ID。 + * @return 对应笔记ID的摘要字符串,如果找到了笔记。 + * @throws IllegalArgumentException 如果未找到对应ID的笔记。 + */ public static String getSnippetById(ContentResolver resolver, long noteId) { + // 构建查询,获取特定笔记ID的摘要字段 Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, - new String [] { NoteColumns.SNIPPET }, + new String[] { NoteColumns.SNIPPET }, NoteColumns.ID + "=?", - new String [] { String.valueOf(noteId)}, + new String[] { String.valueOf(noteId) }, null); + // 初始化摘要字符串 + String snippet = ""; + // 如果查询结果的游标不为空,处理查询结果 if (cursor != null) { - String snippet = ""; + // 如果游标有数据,移动到第一行并获取摘要 if (cursor.moveToFirst()) { snippet = cursor.getString(0); } + // 关闭游标,释放资源 cursor.close(); + // 返回获取到的摘要 return snippet; } + // 如果游标为null,表示查询失败或未找到对应的笔记,抛出异常 throw new IllegalArgumentException("Note is not found with id: " + noteId); } + /** + * 获取格式化的笔记摘要。 + * 移除摘要中的换行符,并截取到第一个换行符之前的内容。 + * + * @param snippet 原始笔记摘要。 + * @return 格式化后的笔记摘要。 + */ public static String getFormattedSnippet(String snippet) { + // 如果传入的摘要不为null,则进行处理 if (snippet != null) { + // 去除摘要字符串前后的空白字符 snippet = snippet.trim(); + // 寻找摘要中第一个换行符的位置 int index = snippet.indexOf('\n'); + // 如果存在换行符,则截取换行符之前的内容 if (index != -1) { snippet = snippet.substring(0, index); } } + // 返回处理后的摘要字符串,如果原始摘要为null,则返回null return snippet; } -} +} \ No newline at end of file diff --git a/src/tool/GTaskStringUtils.java b/src/tool/GTaskStringUtils.java index 666b729..7d6c519 100644 --- a/src/tool/GTaskStringUtils.java +++ b/src/tool/GTaskStringUtils.java @@ -14,100 +14,75 @@ * limitations under the License. */ -package net.micode.notes.tool; - -public class GTaskStringUtils { - - public final static String GTASK_JSON_ACTION_ID = "action_id"; - - public final static String GTASK_JSON_ACTION_LIST = "action_list"; - - public final static String GTASK_JSON_ACTION_TYPE = "action_type"; - - public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; - - public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; - - public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; - - public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; - - public final static String GTASK_JSON_CREATOR_ID = "creator_id"; - - public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; - - public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; - - public final static String GTASK_JSON_COMPLETED = "completed"; - - public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; - - public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; - - public final static String GTASK_JSON_DELETED = "deleted"; - - public final static String GTASK_JSON_DEST_LIST = "dest_list"; - - public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; - - public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; - - public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; - - public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; - - public final static String GTASK_JSON_GET_DELETED = "get_deleted"; - - public final static String GTASK_JSON_ID = "id"; - - public final static String GTASK_JSON_INDEX = "index"; - - public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; - - public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; - - public final static String GTASK_JSON_LIST_ID = "list_id"; - - public final static String GTASK_JSON_LISTS = "lists"; - - public final static String GTASK_JSON_NAME = "name"; - - public final static String GTASK_JSON_NEW_ID = "new_id"; - - public final static String GTASK_JSON_NOTES = "notes"; - - public final static String GTASK_JSON_PARENT_ID = "parent_id"; - - public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; - - public final static String GTASK_JSON_RESULTS = "results"; - - public final static String GTASK_JSON_SOURCE_LIST = "source_list"; - - public final static String GTASK_JSON_TASKS = "tasks"; - - public final static String GTASK_JSON_TYPE = "type"; - - public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; - - public final static String GTASK_JSON_TYPE_TASK = "TASK"; - - public final static String GTASK_JSON_USER = "user"; - - public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; - - public final static String FOLDER_DEFAULT = "Default"; - - public final static String FOLDER_CALL_NOTE = "Call_Note"; - - public final static String FOLDER_META = "METADATA"; - - public final static String META_HEAD_GTASK_ID = "meta_gid"; - - public final static String META_HEAD_NOTE = "meta_note"; - - public final static String META_HEAD_DATA = "meta_data"; - - public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE"; - -} + package net.micode.notes.tool; + + /** + * 提供Google任务(GTask)相关的字符串常量工具类。 + * 包含GTask JSON数据结构中使用的键名常量,以及一些与笔记文件夹相关的常量。 + */ + public class GTaskStringUtils { + + // GTask JSON动作类型常量 + public final static String GTASK_JSON_ACTION_ID = "action_id"; // 动作ID + public final static String GTASK_JSON_ACTION_LIST = "action_list"; // 动作列表 + public final static String GTASK_JSON_ACTION_TYPE = "action_type"; // 动作类型 + + // GTask JSON动作类型具体值 + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; // 创建动作 + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; // 获取全部动作 + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; // 移动动作 + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; // 更新动作 + + // GTask JSON其他常量 + public final static String GTASK_JSON_CREATOR_ID = "creator_id"; // 创建者ID + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; // 子实体 + public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; // 客户端版本 + public final static String GTASK_JSON_COMPLETED = "completed"; // 完成状态 + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; // 当前列表ID + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; // 默认列表ID + public final static String GTASK_JSON_DELETED = "deleted"; // 删除标志 + public final static String GTASK_JSON_DEST_LIST = "dest_list"; // 目标列表 + public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; // 目标父节点 + public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; // 目标父节点类型 + public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; // 实体变化 + public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; // 实体类型 + public final static String GTASK_JSON_GET_DELETED = "get_deleted"; // 获取已删除项 + public final static String GTASK_JSON_ID = "id"; // ID + public final static String GTASK_JSON_INDEX = "index"; // 索引 + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; // 最后修改时间 + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; // 最新同步点 + public final static String GTASK_JSON_LIST_ID = "list_id"; // 列表ID + public final static String GTASK_JSON_LISTS = "lists"; // 列表 + public final static String GTASK_JSON_NAME = "name"; // 名称 + public final static String GTASK_JSON_NEW_ID = "new_id"; // 新ID + public final static String GTASK_JSON_NOTES = "notes"; // 笔记 + public final static String GTASK_JSON_PARENT_ID = "parent_id"; // 父节点ID + public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; // 前一个兄弟节点ID + public final static String GTASK_JSON_RESULTS = "results"; // 结果 + public final static String GTASK_JSON_SOURCE_LIST = "source_list"; // 源列表 + public final static String GTASK_JSON_TASKS = "tasks"; // 任务 + public final static String GTASK_JSON_TYPE = "type"; // 类型 + public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; // 组类型 + public final static String GTASK_JSON_TYPE_TASK = "TASK"; // 任务类型 + public final static String GTASK_JSON_USER = "user"; // 用户 + + // MIUI笔记文件夹前缀 + public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; + + // 默认文件夹名称 + public final static String FOLDER_DEFAULT = "Default"; + + // 通话笔记文件夹名称 + public final static String FOLDER_CALL_NOTE = "Call_Note"; + + // 元数据文件夹名称 + public final static String FOLDER_META = "METADATA"; + + // 元数据头部常量 + public final static String META_HEAD_GTASK_ID = "meta_gid"; // GTask ID + public final static String META_HEAD_NOTE = "meta_note"; // 笔记 + public final static String META_HEAD_DATA = "meta_data"; // 数据 + + // 特殊笔记名称,用于存储元数据 + public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE"; + } \ No newline at end of file diff --git a/src/tool/ResourceParser.java b/src/tool/ResourceParser.java index 1ad3ad6..30be03d 100644 --- a/src/tool/ResourceParser.java +++ b/src/tool/ResourceParser.java @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * 资源解析器类,用于管理应用中的各种资源,包括背景颜色、字体大小等。 + */ package net.micode.notes.tool; import android.content.Context; @@ -24,47 +27,85 @@ import net.micode.notes.ui.NotesPreferenceActivity; public class ResourceParser { + /** + * 定义背景颜色常量。 + */ public static final int YELLOW = 0; public static final int BLUE = 1; public static final int WHITE = 2; public static final int GREEN = 3; public static final int RED = 4; + /** + * 默认背景颜色。 + */ public static final int BG_DEFAULT_COLOR = YELLOW; + /** + * 定义字体大小常量。 + */ public static final int TEXT_SMALL = 0; public static final int TEXT_MEDIUM = 1; public static final int TEXT_LARGE = 2; public static final int TEXT_SUPER = 3; + /** + * 默认字体大小。 + */ public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; + /** + * 笔记背景资源类,用于获取编辑状态下的笔记背景资源。 + */ public static class NoteBgResources { + /** + * 用于存储编辑状态下不同颜色主题的笔记背景资源id。 + * 每个资源id对应一个不同的背景图片,用于在编辑笔记时显示不同颜色主题的背景。 + */ private final static int [] BG_EDIT_RESOURCES = new int [] { - R.drawable.edit_yellow, - R.drawable.edit_blue, - R.drawable.edit_white, - R.drawable.edit_green, - R.drawable.edit_red + R.drawable.edit_yellow, // 编辑状态下黄色主题的笔记背景 + R.drawable.edit_blue, // 编辑状态下蓝色主题的笔记背景 + R.drawable.edit_white, // 编辑状态下白色主题的笔记背景 + R.drawable.edit_green, // 编辑状态下绿色主题的笔记背景 + R.drawable.edit_red // 编辑状态下红色主题的笔记背景 }; + /** + * 用于存储编辑状态下不同颜色主题的笔记标题背景资源id。 + * 每个资源id对应一个不同的背景图片,用于在编辑笔记时显示不同颜色主题的标题背景。 + */ private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { - R.drawable.edit_title_yellow, - R.drawable.edit_title_blue, - R.drawable.edit_title_white, - R.drawable.edit_title_green, - R.drawable.edit_title_red + R.drawable.edit_title_yellow, // 编辑状态下黄色主题的笔记标题背景 + R.drawable.edit_title_blue, // 编辑状态下蓝色主题的笔记标题背景 + R.drawable.edit_title_white, // 编辑状态下白色主题的笔记标题背景 + R.drawable.edit_title_green, // 编辑状态下绿色主题的笔记标题背景 + R.drawable.edit_title_red // 编辑状态下红色主题的笔记标题背景 }; + /** + * 获取笔记背景资源。 + * @param id 背景资源id索引。 + * @return 对应的笔记背景资源id。 + */ public static int getNoteBgResource(int id) { return BG_EDIT_RESOURCES[id]; } + /** + * 获取笔记标题背景资源。 + * @param id 标题背景资源id索引。 + * @return 对应的笔记标题背景资源id。 + */ public static int getNoteTitleBgResource(int id) { return BG_EDIT_TITLE_RESOURCES[id]; } } + /** + * 获取默认背景资源id。 + * @param context 上下文。 + * @return 默认背景资源id。 + */ public static int getDefaultBgId(Context context) { if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { @@ -74,60 +115,105 @@ public class ResourceParser { } } + /** + * 笔记项背景资源类,用于获取列表中笔记项的背景资源。 + */ public static class NoteItemBgResources { + /** + * 用于存储列表中处于第一个位置的笔记项的背景资源id。 + * 每个资源id对应一个不同的背景图片,用于区分不同颜色主题的笔记项。 + */ private final static int [] BG_FIRST_RESOURCES = new int [] { - R.drawable.list_yellow_up, - R.drawable.list_blue_up, - R.drawable.list_white_up, - R.drawable.list_green_up, - R.drawable.list_red_up + R.drawable.list_yellow_up, // 黄色主题的列表第一个笔记项背景 + R.drawable.list_blue_up, // 蓝色主题的列表第一个笔记项背景 + R.drawable.list_white_up, // 白色主题的列表第一个笔记项背景 + R.drawable.list_green_up, // 绿色主题的列表第一个笔记项背景 + R.drawable.list_red_up // 红色主题的列表第一个笔记项背景 }; + /** + * 用于存储列表中处于中间位置的笔记项的背景资源id。 + * 每个资源id对应一个不同的背景图片,用于区分不同颜色主题的笔记项。 + */ private final static int [] BG_NORMAL_RESOURCES = new int [] { - R.drawable.list_yellow_middle, - R.drawable.list_blue_middle, - R.drawable.list_white_middle, - R.drawable.list_green_middle, - R.drawable.list_red_middle + R.drawable.list_yellow_middle, // 黄色主题的列表中间笔记项背景 + R.drawable.list_blue_middle, // 蓝色主题的列表中间笔记项背景 + R.drawable.list_white_middle, // 白色主题的列表中间笔记项背景 + R.drawable.list_green_middle, // 绿色主题的列表中间笔记项背景 + R.drawable.list_red_middle // 红色主题的列表中间笔记项背景 }; + /** + * 用于存储列表中处于最后一个位置的笔记项的背景资源id。 + * 每个资源id对应一个不同的背景图片,用于区分不同颜色主题的笔记项。 + */ private final static int [] BG_LAST_RESOURCES = new int [] { - R.drawable.list_yellow_down, - R.drawable.list_blue_down, - R.drawable.list_white_down, - R.drawable.list_green_down, - R.drawable.list_red_down, + R.drawable.list_yellow_down, // 黄色主题的列表最后一个笔记项背景 + R.drawable.list_blue_down, // 蓝色主题的列表最后一个笔记项背景 + R.drawable.list_white_down, // 白色主题的列表最后一个笔记项背景 + R.drawable.list_green_down, // 绿色主题的列表最后一个笔记项背景 + R.drawable.list_red_down // 红色主题的列表最后一个笔记项背景 }; + /** + * 用于存储列表中单个笔记项(列表中只有一个笔记项时)的背景资源id。 + * 每个资源id对应一个不同的背景图片,用于区分不同颜色主题的笔记项。 + */ private final static int [] BG_SINGLE_RESOURCES = new int [] { - R.drawable.list_yellow_single, - R.drawable.list_blue_single, - R.drawable.list_white_single, - R.drawable.list_green_single, - R.drawable.list_red_single + R.drawable.list_yellow_single, // 黄色主题的单个笔记项背景 + R.drawable.list_blue_single, // 蓝色主题的单个笔记项背景 + R.drawable.list_white_single, // 白色主题的单个笔记项背景 + R.drawable.list_green_single, // 绿色主题的单个笔记项背景 + R.drawable.list_red_single // 红色主题的单个笔记项背景 }; - + /** + * 获取列表中第一个笔记项的背景资源。 + * @param id 背景资源id。 + * @return 对应的资源id。 + */ public static int getNoteBgFirstRes(int id) { return BG_FIRST_RESOURCES[id]; } + /** + * 获取列表中最后一个笔记项的背景资源。 + * @param id 背景资源id。 + * @return 对应的资源id。 + */ public static int getNoteBgLastRes(int id) { return BG_LAST_RESOURCES[id]; } + /** + * 获取列表中单个笔记项的背景资源。 + * @param id 背景资源id。 + * @return 对应的资源id。 + */ public static int getNoteBgSingleRes(int id) { return BG_SINGLE_RESOURCES[id]; } + /** + * 获取列表中普通笔记项的背景资源。 + * @param id 背景资源id。 + * @return 对应的资源id。 + */ public static int getNoteBgNormalRes(int id) { return BG_NORMAL_RESOURCES[id]; } + /** + * 获取文件夹背景资源。 + * @return 文件夹背景资源id。 + */ public static int getFolderBgRes() { return R.drawable.list_folder; } } + /** + * 部件背景资源类,用于获取小部件的背景资源。 + */ public static class WidgetBgResources { private final static int [] BG_2X_RESOURCES = new int [] { R.drawable.widget_2x_yellow, @@ -137,6 +223,11 @@ public class ResourceParser { R.drawable.widget_2x_red, }; + /** + * 获取2x小部件背景资源。 + * @param id 背景资源id。 + * @return 对应的资源id。 + */ public static int getWidget2xBgResource(int id) { return BG_2X_RESOURCES[id]; } @@ -149,11 +240,19 @@ public class ResourceParser { R.drawable.widget_4x_red }; + /** + * 获取4x小部件背景资源。 + * @param id 背景资源id。 + * @return 对应的资源id。 + */ public static int getWidget4xBgResource(int id) { return BG_4X_RESOURCES[id]; } } + /** + * 文本外观资源类,用于获取不同字体大小的资源。 + */ public static class TextAppearanceResources { private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { R.style.TextAppearanceNormal, @@ -162,11 +261,16 @@ public class ResourceParser { R.style.TextAppearanceSuper }; + /** + * 获取文本外观资源。 + * @param id 文本外观资源id。 + * @return 对应的资源id。 + */ public static int getTexAppearanceResource(int id) { /** - * HACKME: Fix bug of store the resource id in shared preference. - * The id may larger than the length of resources, in this case, - * return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE} + * HACKME: 修复存储在共享首选项中的资源id的bug。 + * id可能大于资源的长度,在这种情况下, + * 返回{@link ResourceParser#BG_DEFAULT_FONT_SIZE} */ if (id >= TEXTAPPEARANCE_RESOURCES.length) { return BG_DEFAULT_FONT_SIZE; @@ -174,8 +278,12 @@ public class ResourceParser { return TEXTAPPEARANCE_RESOURCES[id]; } + /** + * 获取资源大小。 + * @return 资源数组的长度。 + */ public static int getResourcesSize() { return TEXTAPPEARANCE_RESOURCES.length; } } -} +} \ No newline at end of file