From ec0ea1cced69c993eaec058bc9a922a93deba307 Mon Sep 17 00:00:00 2001 From: hyf <2173636536@qq.com> Date: Wed, 25 Dec 2024 19:17:04 +0800 Subject: [PATCH] =?UTF-8?q?=E8=83=A1=E4=BA=91=E9=A3=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/net/micode/notes/model/Note.java | 117 ++++++++++++--- .../net/micode/notes/model/WorkingNote.java | 140 ++++++++++-------- .../micode/notes/ui/AlarmAlertActivity.java | 60 ++++++-- .../notes/widget/NoteWidgetProvider.java | 50 +++++-- .../notes/widget/NoteWidgetProvider_2x.java | 13 +- .../notes/widget/NoteWidgetProvider_4x.java | 13 +- 6 files changed, 275 insertions(+), 118 deletions(-) diff --git a/src/Notes-master/src/net/micode/notes/model/Note.java b/src/Notes-master/src/net/micode/notes/model/Note.java index 6706cf6..bcfc524 100644 --- a/src/Notes-master/src/net/micode/notes/model/Note.java +++ b/src/Notes-master/src/net/micode/notes/model/Note.java @@ -33,73 +33,121 @@ import net.micode.notes.data.Notes.TextNote; import java.util.ArrayList; - +// 定义 Note 类,用于管理笔记相关的数据和操作 public class Note { + // 存储笔记的不同部分的变更数据 private ContentValues mNoteDiffValues; + // 存储笔记的数据 private NoteData mNoteData; + // 日志标记 private static final String TAG = "Note"; /** * Create a new note id for adding a new note to databases */ + + /** + * 创建一个新的笔记 ID 并添加到数据库 + * 此方法是同步的,避免并发创建笔记时出现问题 + * @param context 应用程序上下文 + * @param folderId 笔记所在的文件夹 ID + * @return 新创建的笔记 ID + */ public static synchronized long getNewNoteId(Context context, long folderId) { // Create a new note in the database + // 创建一个新的 ContentValues 对象来存储笔记的初始信息 ContentValues values = new ContentValues(); + // 获取当前时间作为创建时间 long createdTime = System.currentTimeMillis(); values.put(NoteColumns.CREATED_DATE, createdTime); values.put(NoteColumns.MODIFIED_DATE, createdTime); values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); values.put(NoteColumns.LOCAL_MODIFIED, 1); values.put(NoteColumns.PARENT_ID, folderId); + // 将笔记信息插入到内容提供者的 URI 中 Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); long noteId = 0; try { + // 从 URI 中提取笔记 ID,通常 URI 包含笔记的路径信息,路径中的一部分是笔记 ID noteId = Long.valueOf(uri.getPathSegments().get(1)); } catch (NumberFormatException e) { + // 若出现异常,打印错误日志并将笔记 ID 设为 0 Log.e(TAG, "Get note id error :" + e.toString()); noteId = 0; } if (noteId == -1) { + // 若笔记 ID 为 -1,抛出异常 throw new IllegalStateException("Wrong note id:" + noteId); } return noteId; } - + // 构造函数,初始化笔记的数据存储和变更存储 public Note() { mNoteDiffValues = new ContentValues(); mNoteData = new NoteData(); } + /** + * 设置笔记的值 + * @param key 要设置的键 + * @param value 要设置的值 + */ public void setNoteValue(String key, String value) { mNoteDiffValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } + /** + * 设置文本数据的键值对 + * @param key 文本数据的键 + * @param value 文本数据的值 + */ public void setTextData(String key, String value) { mNoteData.setTextData(key, value); } - + /** + * 设置文本数据的 ID + * @param id 文本数据的 ID + */ public void setTextDataId(long id) { mNoteData.setTextDataId(id); } - + /** + * 获取文本数据的 ID + * @return 文本数据的 ID + */ public long getTextDataId() { return mNoteData.mTextDataId; } - + /** + * 设置通话数据的 ID + * @param id 通话数据的 ID + */ public void setCallDataId(long id) { mNoteData.setCallDataId(id); } - + /** + * 设置通话数据的键值对 + * @param key 通话数据的键 + * @param value 通话数据的值 + */ public void setCallData(String key, String value) { mNoteData.setCallData(key, value); } - + /** + * 检查笔记是否在本地被修改 + * @return 若笔记在本地被修改,返回 true,否则返回 false + */ public boolean isLocalModified() { return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); } - + /** + * 同步笔记数据到数据库 + * @param context 应用程序上下文 + * @param noteId 笔记的 ID + * @return 若同步成功,返回 true,否则返回 false + */ public boolean syncNote(Context context, long noteId) { if (noteId <= 0) { throw new IllegalArgumentException("Wrong note id:" + noteId); @@ -110,15 +158,14 @@ public class Note { } /** - * In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and - * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the - * note data info + * 理论上,一旦数据发生变化,笔记应该更新 LOCAL_MODIFIED 和 MODIFIED_DATE 字段。 + * 即使更新笔记失败,为了数据安全,我们也会更新笔记的数据信息 */ if (context.getContentResolver().update( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, null) == 0) { Log.e(TAG, "Update note error, should not happen"); - // Do not return, fall through + // 不返回,继续执行后续代码 } mNoteDiffValues.clear(); @@ -129,7 +176,7 @@ public class Note { return true; } - + // 内部类 NoteData,用于存储笔记的数据 private class NoteData { private long mTextDataId; @@ -140,44 +187,67 @@ public class Note { private ContentValues mCallDataValues; private static final String TAG = "NoteData"; - + // 构造函数,初始化数据存储 public NoteData() { mTextDataValues = new ContentValues(); mCallDataValues = new ContentValues(); mTextDataId = 0; mCallDataId = 0; } - + /** + * 检查数据是否在本地被修改 + * @return 若数据在本地被修改,返回 true,否则返回 false + */ boolean isLocalModified() { return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; } - + + /** + * 设置文本数据的 ID + * @param id 文本数据的 ID + */ void setTextDataId(long id) { if(id <= 0) { throw new IllegalArgumentException("Text data id should larger than 0"); } mTextDataId = id; } - + /** + * 设置通话数据的 ID + * @param id 通话数据的 ID + */ void setCallDataId(long id) { if (id <= 0) { throw new IllegalArgumentException("Call data id should larger than 0"); } mCallDataId = id; } - + /** + * 设置通话数据的键值对 + * @param key 通话数据的键 + * @param value 通话数据的值 + */ void setCallData(String key, String value) { mCallDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } - + /** + * 设置文本数据的键值对 + * @param key 文本数据的键 + * @param value 文本数据的值 + */ void setTextData(String key, String value) { mTextDataValues.put(key, value); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); } - + /** + * 将数据更新到内容提供者中 + * @param context 应用程序上下文 + * @param noteId 笔记的 ID + * @return 更新操作的结果 URI,若失败返回 null + */ Uri pushIntoContentResolver(Context context, long noteId) { /** * Check for safety @@ -193,9 +263,11 @@ public class Note { mTextDataValues.put(DataColumns.NOTE_ID, noteId); if (mTextDataId == 0) { mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); + // 插入新的文本数据 Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mTextDataValues); try { + // 从 URI 中提取新插入的文本数据的 ID setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); } catch (NumberFormatException e) { Log.e(TAG, "Insert new text data fail with noteId" + noteId); @@ -203,6 +275,7 @@ public class Note { return null; } } else { + // 更新已有的文本数据 builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mTextDataId)); builder.withValues(mTextDataValues); @@ -215,9 +288,11 @@ public class Note { mCallDataValues.put(DataColumns.NOTE_ID, noteId); if (mCallDataId == 0) { mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); + // 插入新的通话数据 Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, mCallDataValues); try { + // 从 URI 中提取新插入的通话数据的 ID setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); } catch (NumberFormatException e) { Log.e(TAG, "Insert new call data fail with noteId" + noteId); @@ -225,6 +300,7 @@ public class Note { return null; } } else { + // 更新已有的通话数据 builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( Notes.CONTENT_DATA_URI, mCallDataId)); builder.withValues(mCallDataValues); @@ -235,6 +311,7 @@ public class Note { if (operationList.size() > 0) { try { + // 执行批量操作 ContentProviderResult[] results = context.getContentResolver().applyBatch( Notes.AUTHORITY, operationList); return (results == null || results.length == 0 || results[0] == null) ? null diff --git a/src/Notes-master/src/net/micode/notes/model/WorkingNote.java b/src/Notes-master/src/net/micode/notes/model/WorkingNote.java index be081e4..67c7f3c 100644 --- a/src/Notes-master/src/net/micode/notes/model/WorkingNote.java +++ b/src/Notes-master/src/net/micode/notes/model/WorkingNote.java @@ -31,37 +31,37 @@ import net.micode.notes.data.Notes.NoteColumns; 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, @@ -71,7 +71,7 @@ public class WorkingNote { DataColumns.DATA3, DataColumns.DATA4, }; - + // 笔记投影,用于查询笔记时指定要查询的列 public static final String[] NOTE_PROJECTION = new String[] { NoteColumns.PARENT_ID, NoteColumns.ALERTED_DATE, @@ -80,7 +80,7 @@ public class WorkingNote { NoteColumns.WIDGET_TYPE, NoteColumns.MODIFIED_DATE }; - + // 数据投影中各列的索引 private static final int DATA_ID_COLUMN = 0; private static final int DATA_CONTENT_COLUMN = 1; @@ -88,7 +88,7 @@ public class WorkingNote { 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; @@ -101,20 +101,22 @@ public class WorkingNote { private static final int NOTE_MODIFIED_DATE_COLUMN = 5; - // New note construct + // 创建新笔记的构造函数 private WorkingNote(Context context, long folderId) { mContext = context; mAlertDate = 0; + //初始化修改日期为当前系统时间 mModifiedDate = System.currentTimeMillis(); mFolderId = folderId; mNote = new Note(); mNoteId = 0; + // 标记笔记未删除 mIsDeleted = false; mMode = 0; mWidgetType = Notes.TYPE_WIDGET_INVALIDE; } - // Existing note construct + // 加载现有笔记的构造函数 private WorkingNote(Context context, long noteId, long folderId) { mContext = context; mNoteId = noteId; @@ -123,18 +125,25 @@ public class WorkingNote { mNote = new Note(); loadNote(); } - + // 加载笔记的方法,从数据库中查询笔记的基本信息 private void loadNote() { + // 1. 通过 ContentResolver 查询笔记信息,使用 NOTE_PROJECTION 投影指定要查询的列 Cursor cursor = mContext.getContentResolver().query( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, null, null); if (cursor != null) { + // 2. 将游标移动到第一个结果 if (cursor.moveToFirst()) { + // 3. 从游标中读取并存储父文件夹 ID mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); + // 4. 从游标中读取并存储背景颜色 ID mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); + // 5. 从游标中读取并存储小部件 ID mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); + // 6. 从游标中读取并存储小部件类型 mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); + // 7. 从游标中读取并存储提醒日期 mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); } @@ -145,24 +154,30 @@ public class WorkingNote { } loadNoteData(); } - + // 加载笔记的数据,从数据库中查询笔记的数据信息 private void loadNoteData() { + // 1. 通过 ContentResolver 查询笔记数据,使用 DATA_PROJECTION 投影指定要查询的列,并通过 NOTE_ID 筛选 Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { String.valueOf(mNoteId) }, null); if (cursor != null) { + // 2. 将游标移动到第一个结果 if (cursor.moveToFirst()) { do { + // 3. 读取数据的 MIME 类型 String type = cursor.getString(DATA_MIME_TYPE_COLUMN); if (DataConstants.NOTE.equals(type)) { + // 4. 如果是普通笔记,存储内容和模式,并设置文本数据的 ID 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)) { + // 5. 如果是通话笔记,设置通话数据的 ID mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); } else { + // 6. 对于不识别的类型,打印调试日志 Log.d(TAG, "Wrong note type with type:" + type); } } while (cursor.moveToNext()); @@ -173,7 +188,7 @@ public class WorkingNote { 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); @@ -182,24 +197,25 @@ public class WorkingNote { note.setWidgetType(widgetType); return note; } - + // 从数据库加载一个笔记 public static WorkingNote load(Context context, long id) { return new WorkingNote(context, id, 0); } - + // 保存笔记到数据库 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; } } - + // 调用 Note 对象的 syncNote 方法同步笔记信息 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 @@ -212,11 +228,13 @@ public class WorkingNote { } } + // 检查笔记是否存在于数据库中 public boolean existInDatabase() { return mNoteId > 0; } - + // 判断笔记是否值得保存 private boolean isWorthSaving() { + // 1. 判断笔记是否已删除,或者如果笔记不存在且内容为空,或者笔记存在但未被本地修改,则不值得保存 if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) || (existInDatabase() && !mNote.isLocalModified())) { return false; @@ -224,11 +242,11 @@ public class WorkingNote { return true; } } - + // 设置笔记设置变更监听器 public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { mNoteSettingStatusListener = l; } - + // 设置提醒日期 public void setAlertDate(long date, boolean set) { if (date != mAlertDate) { mAlertDate = date; @@ -238,7 +256,7 @@ public class WorkingNote { mNoteSettingStatusListener.onClockAlertChanged(date, set); } } - + // 标记笔记是否已删除 public void markDeleted(boolean mark) { mIsDeleted = mark; if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID @@ -246,7 +264,7 @@ public class WorkingNote { mNoteSettingStatusListener.onWidgetChanged(); } } - + // 设置背景颜色 ID public void setBgColorId(int id) { if (id != mBgColorId) { mBgColorId = id; @@ -256,7 +274,7 @@ public class WorkingNote { mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); } } - + // 设置检查列表模式 public void setCheckListMode(int mode) { if (mMode != mode) { if (mNoteSettingStatusListener != null) { @@ -266,102 +284,102 @@ public class WorkingNote { mNote.setTextData(TextNote.MODE, String.valueOf(mMode)); } } - +// 设置小部件类型 public void setWidgetType(int type) { if (type != mWidgetType) { mWidgetType = type; mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType)); } } - + // 设置小部件 ID public void setWidgetId(int id) { if (id != mWidgetId) { mWidgetId = id; mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); } } - + // 设置笔记的工作文本 public void setWorkingText(String text) { if (!TextUtils.equals(mContent, text)) { mContent = text; mNote.setTextData(DataColumns.CONTENT, mContent); } } - + // 将笔记转换为通话笔记 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 + /** + * 当在检查列表模式和普通模式之间切换时调用 + * @param oldMode 切换前的模式 + * @param newMode 切换后的模式 */ void onCheckListModeChanged(int oldMode, int newMode); } diff --git a/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java b/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java index 85723be..42b7810 100644 --- a/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java +++ b/src/Notes-master/src/net/micode/notes/ui/AlarmAlertActivity.java @@ -39,33 +39,42 @@ import net.micode.notes.tool.DataUtils; import java.io.IOException; - +// 闹钟提醒活动类,继承自 Activity 并实现 OnClickListener 和 OnDismissListener 接口 public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { + // 笔记的 ID private long mNoteId; + // 笔记的摘要 private String mSnippet; + // 摘要的最大长度 private static final int SNIPPET_PREW_MAX_LEN = 60; + // 媒体播放器,用于播放闹钟声音 MediaPlayer mPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // 隐藏标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); final Window win = getWindow(); + // 当屏幕锁定时也显示该窗口 win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); - +// 如果屏幕未开启,添加相关标志保持屏幕开启等操作 if (!isScreenOn()) { win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); } - + // 获取启动该活动的 Intent Intent intent = getIntent(); try { + // 从 Intent 的数据中提取笔记 ID mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); + // 根据笔记 ID 获取笔记的摘要 mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + // 如果摘要长度超过最大长度,截取并添加额外信息 mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) : mSnippet; @@ -73,36 +82,45 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD e.printStackTrace(); return; } - + // 创建媒体播放器 mPlayer = new MediaPlayer(); + // 检查笔记是否存在于数据库中 if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { + // 显示操作对话框 showActionDialog(); + // 播放闹钟声音 playAlarmSound(); } else { + // 若笔记不存在,结束活动 finish(); } } - + // 检查屏幕是否开启的方法 private boolean isScreenOn() { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); return pm.isScreenOn(); } - + // 播放闹钟声音的方法 private void playAlarmSound() { + // 获取闹钟的铃声 URI Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); - - int silentModeStreams = Settings.System.getInt(getContentResolver(), + // 获取系统的静音模式设置 + int silentModeStreams = Settings.System.getInt(getContentResolver(), Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); - + // 根据静音模式设置音频流类型 if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { mPlayer.setAudioStreamType(silentModeStreams); } else { mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); } try { + // 设置媒体播放器的数据源 mPlayer.setDataSource(this, url); + // 准备播放 mPlayer.prepare(); + // 设置为循环播放 mPlayer.setLooping(true); + // 开始播放 mPlayer.start(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block @@ -118,39 +136,53 @@ public class AlarmAlertActivity extends Activity implements OnClickListener, OnD e.printStackTrace(); } } - + // 显示操作对话框的方法 private void showActionDialog() { + // 创建对话框构建器 AlertDialog.Builder dialog = new AlertDialog.Builder(this); + // 设置对话框标题 dialog.setTitle(R.string.app_name); + // 设置对话框消息为笔记摘要 dialog.setMessage(mSnippet); + // 设置对话框的确认按钮及点击事件 dialog.setPositiveButton(R.string.notealert_ok, this); + // 如果屏幕开启,设置进入按钮及点击事件 if (isScreenOn()) { dialog.setNegativeButton(R.string.notealert_enter, this); } + // 显示对话框并设置对话框关闭监听器 dialog.show().setOnDismissListener(this); } - + // 点击事件处理方法 public void onClick(DialogInterface dialog, int which) { switch (which) { + // 点击进入按钮 case DialogInterface.BUTTON_NEGATIVE: - Intent intent = new Intent(this, NoteEditActivity.class); + // 创建一个新的 Intent 指向 NoteEditActivity + Intent intent = new Intent(this, NoteEditActivity.class); intent.setAction(Intent.ACTION_VIEW); + // 传递笔记的唯一标识符 intent.putExtra(Intent.EXTRA_UID, mNoteId); + // 启动活动 startActivity(intent); break; default: break; } } - + // 对话框关闭时的处理方法 public void onDismiss(DialogInterface dialog) { + // 停止播放闹钟声音 stopAlarmSound(); + // 结束活动 finish(); } - + // 停止播放闹钟声音的方法 private void stopAlarmSound() { if (mPlayer != null) { + // 停止播放 mPlayer.stop(); + // 释放资源 mPlayer.release(); mPlayer = null; } diff --git a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java index ec6f819..573530a 100644 --- a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java +++ b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider.java @@ -32,31 +32,37 @@ import net.micode.notes.tool.ResourceParser; import net.micode.notes.ui.NoteEditActivity; import net.micode.notes.ui.NotesListActivity; + +// 抽象的笔记小部件提供者类,继承自 AppWidgetProvider public abstract class NoteWidgetProvider extends AppWidgetProvider { + // 投影数组,用于查询笔记小部件信息时指定要查询的列 public static final String [] PROJECTION = new String [] { NoteColumns.ID, NoteColumns.BG_COLOR_ID, NoteColumns.SNIPPET }; - + // 投影列的索引 public static final int COLUMN_ID = 0; public static final int COLUMN_BG_COLOR_ID = 1; public static final int COLUMN_SNIPPET = 2; - + // 日志标记 private static final String TAG = "NoteWidgetProvider"; - + // 当小部件被删除时调用的方法 @Override public void onDeleted(Context context, int[] appWidgetIds) { + // 创建一个 ContentValues 对象,将 WIDGET_ID 设为无效 ContentValues values = new ContentValues(); values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + // 遍历要删除的小部件 ID 数组 for (int i = 0; i < appWidgetIds.length; i++) { + // 通过 ContentResolver 更新笔记信息,将对应小部件 ID 的 WIDGET_ID 设为无效 context.getContentResolver().update(Notes.CONTENT_NOTE_URI, values, NoteColumns.WIDGET_ID + "=?", new String[] { String.valueOf(appWidgetIds[i])}); } } - + // 获取笔记小部件信息的私有方法,通过 ContentResolver 查询 private Cursor getNoteWidgetInfo(Context context, int widgetId) { return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, @@ -64,34 +70,45 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) }, null); } - + // 更新小部件的方法,调用另一个重载的 update 方法 protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, false); } - + // 真正执行更新小部件的私有方法 private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, boolean privacyMode) { + // 遍历要更新的小部件 ID 数组 for (int i = 0; i < appWidgetIds.length; i++) { if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { + // 获取默认背景颜色 ID int bgId = ResourceParser.getDefaultBgId(context); + // 初始化 snippet 为一个空字符串 String snippet = ""; + // 创建一个 Intent,指向 NoteEditActivity Intent intent = new Intent(context, NoteEditActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + // 向 Intent 中添加小部件 ID 和小部件类型信息 intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); - + // 获取小部件的笔记信息 Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); if (c != null && c.moveToFirst()) { if (c.getCount() > 1) { + // 如果查询结果数量大于 1,打印错误日志并关闭游标 Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); c.close(); return; } + // 获取 snippet 信息 snippet = c.getString(COLUMN_SNIPPET); + // 获取背景颜色 ID bgId = c.getInt(COLUMN_BG_COLOR_ID); + // 向 Intent 中添加笔记的唯一标识符 intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); + // 设置 Intent 的动作 intent.setAction(Intent.ACTION_VIEW); } else { + // 如果没有找到笔记信息,设置默认的 snippet 信息并设置 Intent 动作 snippet = context.getResources().getString(R.string.widget_havenot_content); intent.setAction(Intent.ACTION_INSERT_OR_EDIT); } @@ -99,34 +116,37 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { if (c != null) { c.close(); } - + // 创建一个 RemoteViews 对象,使用抽象方法 getLayoutId 获取布局 ID RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); + // 设置小部件背景图片资源,使用抽象方法 getBgResourceId 获取资源 ID rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); + // 向 Intent 中添加背景颜色 ID 信息 intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); - /** - * Generate the pending intent to start host for the widget - */ + // 创建一个 PendingIntent,根据隐私模式不同创建不同的 PendingIntent PendingIntent pendingIntent = null; if (privacyMode) { + // 在隐私模式下,设置文本视图内容并创建一个指向 NotesListActivity 的 PendingIntent rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode)); pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent( context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); } else { + // 正常模式下,设置文本视图内容为 snippet 并创建一个指向 NoteEditActivity 的 PendingIntent rv.setTextViewText(R.id.widget_text, snippet); pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, PendingIntent.FLAG_UPDATE_CURRENT); } - + // 为小部件的文本视图设置点击事件的 PendingIntent rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); + // 更新小部件 appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } } } - + // 抽象方法,用于获取背景资源 ID,需要子类实现 protected abstract int getBgResourceId(int bgId); - + // 抽象方法,用于获取布局 ID,需要子类实现 protected abstract int getLayoutId(); - + // 抽象方法,用于获取小部件类型,需要子类实现 protected abstract int getWidgetType(); } diff --git a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java index adcb2f7..6759fa7 100644 --- a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java +++ b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -23,25 +23,30 @@ import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; - +// 继承自 NoteWidgetProvider 的 2x 笔记小部件提供者类 public class NoteWidgetProvider_2x extends NoteWidgetProvider { + // 当小部件更新时调用此方法 @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类的 update 方法进行更新操作 super.update(context, appWidgetManager, appWidgetIds); } - + // 实现父类的抽象方法,获取布局 ID @Override protected int getLayoutId() { + // 返回 2x 小部件的布局资源 ID return R.layout.widget_2x; } - + // 实现父类的抽象方法,获取背景资源 ID @Override protected int getBgResourceId(int bgId) { + // 使用 ResourceParser 的 WidgetBgResources 类获取 2x 小部件的背景资源 ID return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); } - + // 实现父类的抽象方法,获取小部件类型 @Override protected int getWidgetType() { + // 返回 2x 小部件的类型 return Notes.TYPE_WIDGET_2X; } } diff --git a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java index c12a02e..a46bb85 100644 --- a/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java +++ b/src/Notes-master/src/net/micode/notes/widget/NoteWidgetProvider_4x.java @@ -23,24 +23,29 @@ import net.micode.notes.R; import net.micode.notes.data.Notes; import net.micode.notes.tool.ResourceParser; - +// 继承自 NoteWidgetProvider 的 4x 笔记小部件提供者类 public class NoteWidgetProvider_4x extends NoteWidgetProvider { + // 当小部件更新时调用此方法 @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类的 update 方法进行更新操作 super.update(context, appWidgetManager, appWidgetIds); } - + // 实现父类的抽象方法,获取布局 ID protected int getLayoutId() { + // 返回 4x 小部件的布局资源 ID return R.layout.widget_4x; } - + // 实现父类的抽象方法,获取背景资源 ID @Override protected int getBgResourceId(int bgId) { + // 使用 ResourceParser 的 WidgetBgResources 类获取 4x 小部件的背景资源 ID return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); } - + // 实现父类的抽象方法,获取小部件类型 @Override protected int getWidgetType() { + // 返回 4x 小部件的类型 return Notes.TYPE_WIDGET_4X; } }