diff --git a/doc b/doc deleted file mode 100644 index 66dc905..0000000 --- a/doc +++ /dev/null @@ -1 +0,0 @@ -undefined \ No newline at end of file diff --git a/doc/xiaomi notes 质量分析报告.doc b/doc/xiaomi notes 质量分析报告.doc new file mode 100644 index 0000000..0b2afba Binary files /dev/null and b/doc/xiaomi notes 质量分析报告.doc differ diff --git a/doc/xiaomi notes技术博客.doc b/doc/xiaomi notes技术博客.doc new file mode 100644 index 0000000..e63e2e1 Binary files /dev/null and b/doc/xiaomi notes技术博客.doc differ diff --git a/doc/xiaomi notes泛读报告.docx b/doc/xiaomi notes泛读报告.docx new file mode 100644 index 0000000..1c727db Binary files /dev/null and b/doc/xiaomi notes泛读报告.docx differ diff --git a/doc/运行截图.doc b/doc/运行截图.doc new file mode 100644 index 0000000..5ed9578 Binary files /dev/null and b/doc/运行截图.doc differ diff --git a/src b/src deleted file mode 100644 index 66dc905..0000000 --- a/src +++ /dev/null @@ -1 +0,0 @@ -undefined \ No newline at end of file diff --git a/src/Note.java b/src/Note.java new file mode 100644 index 0000000..1c55a33 --- /dev/null +++ b/src/Note.java @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package net.micode.notes.model; + + import android.content.ContentProviderOperation; + import android.content.ContentProviderResult; + import android.content.ContentUris; + import android.content.ContentValues; + import android.content.Context; + import android.content.OperationApplicationException; + import android.net.Uri; + import android.os.RemoteException; + import android.util.Log; + + import net.micode.notes.data.Notes; + import net.micode.notes.data.Notes.CallNote; + import net.micode.notes.data.Notes.DataColumns; + import net.micode.notes.data.Notes.NoteColumns; + import net.micode.notes.data.Notes.TextNote; + + import java.util.ArrayList; + + /** + * 笔记实体模型类,封装笔记的核心业务逻辑 + * 功能包括: + * 1. 创建新笔记记录 + * 2. 管理笔记元数据变更 + * 3. 处理文本/通话类型笔记的具体数据 + * 4. 同步数据到Android Content Provider + */ + public class Note { + // 存储笔记元数据字段的变更(如标题、父目录等) + private ContentValues mNoteDiffValues; + + // 处理笔记具体数据(文本内容/通话记录)的内部类实例 + private NoteData mNoteData; + + // 日志标签 + private static final String TAG = "Note"; + + /** + * 创建新笔记记录并返回笔记ID + * 同步方法保证在多线程环境下的ID唯一性 + * + * @param context 上下文对象,用于访问ContentResolver + * @param folderId 笔记所属文件夹ID(0表示根目录) + * @return 新笔记的数据库ID(创建失败返回0) + * @throws IllegalStateException 当数据库返回非法ID时抛出 + */ + public static synchronized long getNewNoteId(Context context, long folderId) { + // 初始化笔记元数据默认值 + 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); // 所属文件夹 + + // 通过ContentResolver插入新记录 + Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); + + // 解析URI获取新插入记录的ID + long noteId = 0; + try { + // URI格式:content://net.micode.notes/note/{id} + noteId = Long.parseLong(uri.getPathSegments().get(1)); + } catch (NumberFormatException e) { + Log.e(TAG, "解析笔记ID失败:" + e.getMessage()); + noteId = 0; // 返回0表示创建失败 + } + + // 数据库返回-1表示插入失败 + if (noteId == -1) { + throw new IllegalStateException("数据库返回非法笔记ID:" + noteId); + } + return noteId; + } + + /** + * 构造函数初始化数据容器 + */ + public Note() { + mNoteDiffValues = new ContentValues(); // 初始化元数据变更容器 + mNoteData = new NoteData(); // 初始化具体数据处理对象 + } + + /** + * 设置笔记元数据字段 + * 自动更新修改时间和本地修改标记 + * + * @param key 元数据字段名(对应NoteColumns中的常量) + * @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 数据字段名(对应TextNote中的常量) + * @param value 文本内容 + */ + public void setTextData(String key, String value) { + mNoteData.setTextData(key, value); + } + + /** + * 设置文本数据在数据库中的ID(用于更新现有记录) + */ + public void setTextDataId(long id) { + mNoteData.setTextDataId(id); + } + + /** + * 获取文本数据ID(用于后续更新操作) + */ + public long getTextDataId() { + return mNoteData.mTextDataId; + } + + /** + * 设置通话记录数据ID(用于更新现有记录) + */ + public void setCallDataId(long id) { + mNoteData.setCallDataId(id); + } + + /** + * 设置通话记录数据 + * + * @param key 数据字段名(对应CallNote中的常量) + * @param value 通话相关信息 + */ + public void setCallData(String key, String value) { + mNoteData.setCallData(key, value); + } + + /** + * 检查是否存在未提交的修改 + * + * @return true表示存在元数据或具体数据的修改 + */ + public boolean isLocalModified() { + return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); + } + + /** + * 同步所有修改到数据库 + * 执行顺序: + * 1. 先更新笔记元数据 + * 2. 再更新具体数据(文本/通话记录) + * + * @param context 上下文对象 + * @param noteId 要同步的笔记ID + * @return 同步是否成功 + * @throws IllegalArgumentException 当noteId不合法时抛出 + */ + public boolean syncNote(Context context, long noteId) { + if (noteId <= 0) { + throw new IllegalArgumentException("非法的笔记ID:" + noteId + ",必须大于0"); + } + + if (!isLocalModified()) { + return true; // 无修改时快速返回 + } + + /* 第一阶段:更新元数据 */ + int updateCount = context.getContentResolver().update( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), + mNoteDiffValues, // 包含修改字段的容器 + null, // WHERE条件(null表示更新指定ID的记录) + null); // WHERE参数 + + // 即使更新失败也继续处理数据更新(保持数据一致性) + if (updateCount == 0) { + Log.e(TAG, "笔记元数据更新失败,ID:" + noteId); + } + mNoteDiffValues.clear(); // 清空已提交的修改 + + /* 第二阶段:更新具体数据 */ + if (mNoteData.isLocalModified()) { + Uri resultUri = mNoteData.pushIntoContentResolver(context, noteId); + if (resultUri == null) { + Log.e(TAG, "笔记数据更新失败,ID:" + noteId); + return false; + } + } + + return true; + } + + /** + * 内部类:处理笔记具体数据的存储逻辑 + * 支持两种数据类型: + * 1. 文本内容(TextNote) + * 2. 通话记录(CallNote) + */ + private class NoteData { + // 文本数据相关字段 + private long mTextDataId; // 文本数据在数据库中的ID + private ContentValues mTextDataValues; // 文本数据修改容器 + + // 通话记录相关字段 + private long mCallDataId; // 通话数据在数据库中的ID + private ContentValues mCallDataValues; // 通话数据修改容器 + + private static final String TAG = "NoteData"; + + /** + * 初始化数据容器 + */ + public NoteData() { + mTextDataValues = new ContentValues(); + mCallDataValues = new ContentValues(); + mTextDataId = 0; // 0表示新数据需要插入 + mCallDataId = 0; + } + + /** + * 检查是否存在未提交的数据修改 + */ + boolean isLocalModified() { + return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; + } + + /** + * 设置文本数据ID(用于更新操作) + * @throws IllegalArgumentException 当id<=0时抛出 + */ + void setTextDataId(long id) { + if (id <= 0) { + throw new IllegalArgumentException("文本数据ID必须大于0,当前值:" + id); + } + mTextDataId = id; + } + + /** + * 设置通话数据ID(用于更新操作) + * @throws IllegalArgumentException 当id<=0时抛出 + */ + void setCallDataId(long id) { + if (id <= 0) { + throw new IllegalArgumentException("通话数据ID必须大于0,当前值:" + id); + } + mCallDataId = id; + } + + /** + * 设置通话记录字段 + * 自动触发笔记元数据的修改标记 + */ + void setCallData(String key, String value) { + mCallDataValues.put(key, value); + // 同步更新笔记的修改状态 + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + + /** + * 设置文本内容字段 + * 自动触发笔记元数据的修改标记 + */ + void setTextData(String key, String value) { + mTextDataValues.put(key, value); + // 同步更新笔记的修改状态 + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + + /** + * 将数据变更提交到Content Provider + * 使用事务处理保证数据一致性: + * 1. 新数据执行INSERT操作 + * 2. 已有数据执行UPDATE操作 + * + * @param context 上下文对象 + * @param noteId 关联的笔记ID + * @return 操作结果的URI,失败返回null + * @throws IllegalArgumentException 当noteId非法时抛出 + */ + Uri pushIntoContentResolver(Context context, long noteId) { + if (noteId <= 0) { + throw new IllegalArgumentException("非法的关联笔记ID:" + noteId); + } + + ArrayList operationList = + new ArrayList(); + ContentProviderOperation.Builder builder; + + /* 处理文本数据 */ + if (mTextDataValues.size() > 0) { + mTextDataValues.put(DataColumns.NOTE_ID, noteId); // 绑定笔记ID + + 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 + long newId = Long.parseLong(uri.getLastPathSegment()); + setTextDataId(newId); + } catch (NumberFormatException e) { + Log.e(TAG, "插入文本数据失败,笔记ID:" + noteId); + mTextDataValues.clear(); + return null; + } + } else { // 更新现有文本数据 + builder = ContentProviderOperation.newUpdate( + ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, mTextDataId) + ); + builder.withValues(mTextDataValues); + operationList.add(builder.build()); + } + mTextDataValues.clear(); + } + + /* 处理通话记录数据(逻辑与文本类似) */ + if (mCallDataValues.size() > 0) { + 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 { + long newId = Long.parseLong(uri.getLastPathSegment()); + setCallDataId(newId); + } catch (NumberFormatException e) { + Log.e(TAG, "插入通话数据失败,笔记ID:" + noteId); + mCallDataValues.clear(); + return null; + } + } else { // 更新现有通话记录 + builder = ContentProviderOperation.newUpdate( + ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, mCallDataId) + ); + builder.withValues(mCallDataValues); + operationList.add(builder.build()); + } + mCallDataValues.clear(); + } + + /* 执行批量操作(如果有需要更新的记录) */ + if (!operationList.isEmpty()) { + try { + // 使用事务批量执行操作 + ContentProviderResult[] results = context.getContentResolver().applyBatch( + Notes.AUTHORITY, + operationList + ); + + // 返回笔记URI表示成功 + return (results != null && results.length > 0) + ? ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId) + : null; + } catch (RemoteException e) { + Log.e(TAG, "远程调用失败:" + e.getMessage()); + } catch (OperationApplicationException e) { + Log.e(TAG, "操作应用失败:" + e.getMessage()); + } + return null; + } + return null; // 无数据操作时返回null + } + } + } \ No newline at end of file diff --git a/src/WorkingNote.java b/src/WorkingNote.java new file mode 100644 index 0000000..a837b17 --- /dev/null +++ b/src/WorkingNote.java @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package net.micode.notes.model; + + import android.appwidget.AppWidgetManager; + import android.content.ContentUris; + import android.content.Context; + import android.database.Cursor; + import android.text.TextUtils; + import android.util.Log; + + import net.micode.notes.data.Notes; + import net.micode.notes.data.Notes.CallNote; + import net.micode.notes.data.Notes.DataColumns; + import net.micode.notes.data.Notes.DataConstants; + import net.micode.notes.data.Notes.NoteColumns; + import net.micode.notes.data.Notes.TextNote; + import net.micode.notes.tool.ResourceParser.NoteBgResources; + + /** + * 工作笔记实体类,处理笔记的核心业务逻辑 + * 主要功能包括: + * 1. 创建新笔记/加载已有笔记 + * 2. 管理笔记元数据(颜色、提醒时间等) + * 3. 处理笔记内容(文本/清单模式) + * 4. 与小部件交互 + * 5. 数据持久化操作 + */ + public class WorkingNote { + // 核心笔记对象 + private Note mNote; + // 笔记数据库ID(0表示新笔记) + private long mNoteId; + // 笔记文本内容 + private String mContent; + // 笔记模式(普通模式/清单模式) + private int mMode; + + // 提醒时间(0表示未设置) + 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, + }; + + // 笔记表查询字段 + 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 + }; + + // 数据表字段索引 + 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; + + /** + * 新建笔记构造函数 + * @param context 上下文对象 + * @param folderId 所属文件夹ID + */ + private WorkingNote(Context context, long folderId) { + mContext = context; + mAlertDate = 0; // 默认不设置提醒 + mModifiedDate = System.currentTimeMillis(); + mFolderId = folderId; + mNote = new Note(); + mNoteId = 0; // 0表示新笔记 + mIsDeleted = false; + mMode = 0; // 默认普通模式 + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; // 默认无小部件 + } + + /** + * 加载已有笔记构造函数 + * @param context 上下文对象 + * @param noteId 存在的笔记ID + * @param folderId 所属文件夹ID + */ + private WorkingNote(Context context, long noteId, long folderId) { + mContext = context; + mNoteId = noteId; + mFolderId = folderId; + mIsDeleted = false; + mNote = new Note(); + loadNote(); // 从数据库加载笔记数据 + } + + /** + * 加载笔记元数据 + * @throws IllegalArgumentException 当笔记不存在时抛出 + */ + private void loadNote() { + // 构建笔记URI + Uri noteUri = ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId); + Cursor cursor = mContext.getContentResolver().query(noteUri, 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); + mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); + mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); + mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); + } + cursor.close(); + } else { + Log.e(TAG, "找不到ID为" + mNoteId + "的笔记"); + throw new IllegalArgumentException("无法找到ID为" + mNoteId + "的笔记"); + } + loadNoteData(); // 加载具体内容数据 + } + + /** + * 加载笔记内容数据 + * @throws IllegalArgumentException 当数据不存在时抛出 + */ + private void loadNoteData() { + // 查询数据表 + Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, + DataColumns.NOTE_ID + "=?", new String[] { String.valueOf(mNoteId) }, null); + + if (cursor != null) { + if (cursor.moveToFirst()) { + do { + String type = cursor.getString(DATA_MIME_TYPE_COLUMN); + 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)) { // 通话记录数据 + mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); + } else { + Log.d(TAG, "未知笔记类型:" + type); + } + } while (cursor.moveToNext()); + } + cursor.close(); + } else { + Log.e(TAG, "找不到ID为" + mNoteId + "的笔记数据"); + throw new IllegalArgumentException("无法找到ID为" + mNoteId + "的笔记数据"); + } + } + + /** + * 创建空白笔记 + * @param context 上下文对象 + * @param folderId 所属文件夹ID + * @param widgetId 关联小部件ID + * @param widgetType 小部件类型 + * @param defaultBgColorId 默认背景颜色ID + * @return 新创建的WorkingNote实例 + */ + 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; + } + + /** + * 加载已有笔记 + * @param context 上下文对象 + * @param id 要加载的笔记ID + * @return 加载的WorkingNote实例 + */ + public static WorkingNote load(Context context, long id) { + return new WorkingNote(context, id, 0); + } + + /** + * 保存笔记(同步方法保证线程安全) + * @return 保存是否成功 + */ + public synchronized boolean saveNote() { + if (isWorthSaving()) { // 检查是否需要保存 + // 处理新笔记的情况 + if (!existInDatabase()) { + if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { + Log.e(TAG, "创建新笔记失败,ID:" + mNoteId); + return false; + } + } + + // 同步数据到数据库 + mNote.syncNote(mContext, mNoteId); + + // 如果有关联小部件,触发更新 + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE + && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + } + return true; + } + return false; + } + + /** + * 检查笔记是否已存在于数据库 + * @return 存在返回true + */ + public boolean existInDatabase() { + return mNoteId > 0; + } + + /** + * 判断是否需要保存 + * 以下情况不需要保存: + * 1. 笔记已标记删除 + * 2. 新笔记且内容为空 + * 3. 已有笔记且无修改 + */ + private boolean isWorthSaving() { + return !(mIsDeleted + || (!existInDatabase() && TextUtils.isEmpty(mContent)) + || (existInDatabase() && !mNote.isLocalModified())); + } + + /** + * 设置笔记设置变更监听器 + */ + public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { + mNoteSettingStatusListener = l; + } + + /** + * 设置提醒时间 + * @param date 提醒时间戳(毫秒) + * @param set 是否设置提醒(true表示设置) + */ + public void setAlertDate(long date, boolean set) { + if (date != mAlertDate) { + mAlertDate = date; + mNote.setNoteValue(NoteColumns.ALERTED_DATE, String.valueOf(mAlertDate)); + } + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onClockAlertChanged(date, set); + } + } + + /** + * 标记删除状态 + * @param mark true表示标记删除 + */ + public void markDeleted(boolean mark) { + mIsDeleted = mark; + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE + && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + } + } + + /** + * 设置背景颜色 + * @param id 颜色资源ID + */ + public void setBgColorId(int id) { + if (id != mBgColorId) { + mBgColorId = id; + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onBackgroundColorChanged(); + } + mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); + } + } + + /** + * 设置清单模式 + * @param mode 模式标识(见TextNote常量) + */ + public void setCheckListMode(int mode) { + if (mMode != mode) { + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode); + } + mMode = mode; + 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)); + } + } + + /** + * 更新笔记内容 + * @param text 新的文本内容 + */ + public void setWorkingText(String text) { + if (!TextUtils.equals(mContent, text)) { + mContent = text; + mNote.setTextData(DataColumns.CONTENT, mContent); + } + } + + /** + * 转换为通话记录笔记 + * @param phoneNumber 电话号码 + * @param callDate 通话时间 + */ + 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; + } + + public String getContent() { + return mContent; + } + + public long getAlertDate() { + return mAlertDate; + } + + public long getModifiedDate() { + return mModifiedDate; + } + + public int getBgColorResId() { + return NoteBgResources.getNoteBgResource(mBgColorId); + } + + public int getBgColorId() { + return mBgColorId; + } + + public int getTitleBgResId() { + return NoteBgResources.getNoteTitleBgResource(mBgColorId); + } + + public int getCheckListMode() { + return mMode; + } + + public long getNoteId() { + return mNoteId; + } + + public long getFolderId() { + return mFolderId; + } + + public int getWidgetId() { + return mWidgetId; + } + + public int getWidgetType() { + return mWidgetType; + } + + /** + * 笔记设置变更监听接口 + */ + public interface NoteSettingChangedListener { + /** + * 背景颜色变更回调 + */ + void onBackgroundColorChanged(); + + /** + * 提醒时间变更回调 + * @param date 新的提醒时间 + * @param set 是否设置提醒 + */ + void onClockAlertChanged(long date, boolean set); + + /** + * 小部件变更回调 + */ + void onWidgetChanged(); + + /** + * 清单模式切换回调 + * @param oldMode 原模式 + * @param newMode 新模式 + */ + void onCheckListModeChanged(int oldMode, int newMode); + } + } \ No newline at end of file