pull/1/head
zjb 9 months ago
parent 626ce1458d
commit 4f9ecbf086

@ -5,14 +5,14 @@
package net.micode.notes.data; package net.micode.notes.data;
import android.content.Context; import android.content.Context; // 导入Context类用于访问应用程序的环境信息
import android.database.Cursor; import android.database.Cursor; // 导入Cursor类用于遍历查询结果
import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.Phone; // 导入电话号码常量
import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Data; // 导入数据常量
import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils; // 导入电话号码工具类
import android.util.Log; import android.util.Log; // 导入Log类用于记录日志
import java.util.HashMap; import java.util.HashMap; // 导入HashMap类用于缓存联系人信息
public class Contact { public class Contact {
// 缓存已查询过的电话号码和对应的联系人名称,以减少数据库查询次数。 // 缓存已查询过的电话号码和对应的联系人名称,以减少数据库查询次数。
@ -20,13 +20,16 @@ public class Contact {
private static final String TAG = "Contact"; // 日志标签 private static final String TAG = "Contact"; // 日志标签
// 用于查询具有完整国际号码格式的电话号码的selection字符串。 // 用于查询具有完整国际号码格式的电话号码的selection字符串。
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER //static final表明这个静态常量共享于整个类不可更改
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"//+用于拼接字符串Data.MIMETYPE表示数据的MIME类型也就是后面的Phone.CONTENT_ITEM_TYPE电话号码数据确保了查询信息只有电话号码
+ " AND " + Data.RAW_CONTACT_ID + " IN " + " AND " + Data.RAW_CONTACT_ID + " IN "//Data.RAW_CONTACT_ID表示原始联系人的唯一IDIN用于判断某个值是否在给定的集合中
+ "(SELECT raw_contact_id " + "(SELECT raw_contact_id "//这是一个嵌套查询,它将返回符合条件的 raw_contact_id 列表
+ " FROM phone_lookup" + " FROM phone_lookup"//指定查询的数据表
+ " WHERE min_match = '+')"; + " WHERE min_match = '+')";//确保只选择那些包含完整国际号码格式(以 + 开头)的联系人
/**
*
* */
/** /**
* *
* *
@ -37,44 +40,44 @@ public class Contact {
public static String getContact(Context context, String phoneNumber) { public static String getContact(Context context, String phoneNumber) {
// 初始化或获取联系人缓存 // 初始化或获取联系人缓存
if (sContactCache == null) { if (sContactCache == null) {
sContactCache = new HashMap<String, String>(); sContactCache = new HashMap<String, String>(); // 创建缓存对象
} }
// 从缓存中直接获取联系人名称,如果存在。 // 如果存在,从缓存中直接获取联系人名称
if (sContactCache.containsKey(phoneNumber)) { if (sContactCache.containsKey(phoneNumber)) {
return sContactCache.get(phoneNumber); return sContactCache.get(phoneNumber); // 返回缓存中的联系人名称
} }
// 使用PhoneNumberUtils将电话号码格式化为适合查询的形式 // 使用PhoneNumberUtils将电话号码格式化为适合查询的形式
String selection = CALLER_ID_SELECTION.replace("+", String selection = CALLER_ID_SELECTION.replace("+",
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); // 替换selection中的占位符
// 执行查询以获取与电话号码相关联的联系人名称 // 执行查询以获取与电话号码相关联的联系人名称
Cursor cursor = context.getContentResolver().query( Cursor cursor = context.getContentResolver().query(
Data.CONTENT_URI, Data.CONTENT_URI, // 查询的URI
new String[]{Phone.DISPLAY_NAME}, new String[]{Phone.DISPLAY_NAME}, // 查询的列
selection, selection, // 查询条件
new String[]{phoneNumber}, new String[]{phoneNumber}, // 查询参数
null); null); // 排序条件
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) { // 确保游标不为空且移动到第一条记录
try { try {
// 从查询结果中获取联系人名称并加入缓存 // 从查询结果中获取联系人名称并加入缓存
String name = cursor.getString(0); String name = cursor.getString(0); // 获取第一列的值,即联系人名称
sContactCache.put(phoneNumber, name); sContactCache.put(phoneNumber, name); // 将名称缓存
return name; return name; // 返回联系人名称
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
// 处理查询结果异常 // 处理查询结果异常
Log.e(TAG, " Cursor get string error " + e.toString()); Log.e(TAG, " Cursor get string error " + e.toString()); // 记录错误日志
return null; return null; // 返回null
} finally { } finally {
// 关闭游标 // 关闭游标以释放资源
cursor.close(); cursor.close();
} }
} else { } else {
// 如果查询无结果,记录日志 // 如果查询无结果,记录日志
Log.d(TAG, "No contact matched with number:" + phoneNumber); Log.d(TAG, "No contact matched with number:" + phoneNumber); // 记录未找到联系人日志
return null; return null; // 返回null
} }
} }
} }

@ -18,256 +18,109 @@ package net.micode.notes.data;
import android.net.Uri; import android.net.Uri;
// Notes类定义了与笔记和文件夹相关的常量和数据列接口 // Notes类定义了与笔记和文件夹管理相关的常量和数据列接口
public class Notes { public class Notes {
public static final String AUTHORITY = "micode_notes"; // 用于标识内容提供者的授权名称 // AUTHORITY用于标识内容提供者的授权名称
public static final String TAG = "Notes"; // 日志标签 public static final String AUTHORITY = "micode_notes";
public static final int TYPE_NOTE = 0; // 笔记类型 // TAG用于日志输出中的标签
public static final int TYPE_FOLDER = 1; // 文件夹类型 public static final String TAG = "Notes";
public static final int TYPE_SYSTEM = 2; // 系统类型
// 笔记、文件夹和系统类型的常量定义
public static final int TYPE_NOTE = 0;
public static final int TYPE_FOLDER = 1;
public static final int TYPE_SYSTEM = 2;
/** /**
* ID * ID
* {@link Notes#ID_ROOT_FOLDER} * - ID_ROOT_FOLDER
* {@link Notes#ID_TEMPARAY_FOLDER} * - ID_TEMPARAY_FOLDER
* {@link Notes#ID_CALL_RECORD_FOLDER} * - ID_CALL_RECORD_FOLDER
*/ */
public static final int ID_ROOT_FOLDER = 0; // 根文件夹ID public static final int ID_ROOT_FOLDER = 0;
public static final int ID_TEMPARAY_FOLDER = -1; // 临时文件夹ID用于存放不属于任何文件夹的笔记 public static final int ID_TEMPARAY_FOLDER = -1;
public static final int ID_CALL_RECORD_FOLDER = -2; // 通话记录文件夹ID public static final int ID_CALL_RECORD_FOLDER = -2;
public static final int ID_TRASH_FOLER = -3; // 垃圾箱文件夹ID public static final int ID_TRASH_FOLER = -3; // 垃圾箱文件夹ID
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date"; // 用于Intent的提醒日期额外数据 // 定义Intent传递的额外信息用于笔记提醒、背景色、小部件ID等
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id"; // 笔记背景色ID public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date";
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id"; // 小部件ID public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id";
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type"; // 小部件类型 public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id";
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id"; // 文件夹ID public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type";
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date"; // 通话日期 public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id";
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date";
public static final int TYPE_WIDGET_INVALIDE = -1; // 无效的小部件类型 // 小部件类型常量
public static final int TYPE_WIDGET_2X = 0; // 2x小部件类型 public static final int TYPE_WIDGET_INVALIDE = -1; // 无效类型
public static final int TYPE_WIDGET_4X = 1; // 4x小部件类型 public static final int TYPE_WIDGET_2X = 0; // 2x小部件
public static final int TYPE_WIDGET_4X = 1; // 4x小部件
// DataConstants类定义笔记和通话记录的内容项类型
public static class DataConstants { public static class DataConstants {
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; // 笔记的内容项类型 public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; // 笔记类型
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; // 通话记录的内容项类型 public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; // 通话记录类型
} }
/** /**
* Uri * CONTENT_NOTE_URIURI
*/ */
public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note");
/** /**
* Uri * CONTENT_DATA_URIURI
*/ */
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
// 笔记和文件夹的公共列接口 // NoteColumns接口定义笔记和文件夹的公共列
public interface NoteColumns { public interface NoteColumns {
/** public static final String ID = "_id"; // 唯一ID (类型: INTEGER)
* ID public static final String PARENT_ID = "parent_id"; // 父ID (类型: INTEGER)
* <P>: INTEGER (long)</P> public static final String CREATED_DATE = "created_date"; // 创建日期 (类型: INTEGER)
*/ public static final String MODIFIED_DATE = "modified_date"; // 最后修改日期 (类型: INTEGER)
public static final String ID = "_id"; public static final String ALERTED_DATE = "alert_date"; // 提醒日期 (类型: INTEGER)
public static final String SNIPPET = "snippet"; // 摘要信息 (类型: TEXT)
/** public static final String WIDGET_ID = "widget_id"; // 小部件ID (类型: INTEGER)
* ID public static final String WIDGET_TYPE = "widget_type"; // 小部件类型 (类型: INTEGER)
* <P>: INTEGER (long)</P> public static final String BG_COLOR_ID = "bg_color_id"; // 背景色ID (类型: INTEGER)
*/ public static final String HAS_ATTACHMENT = "has_attachment"; // 是否有附件 (类型: INTEGER)
public static final String PARENT_ID = "parent_id"; public static final String NOTES_COUNT = "notes_count"; // 笔记数量 (类型: INTEGER)
public static final String TYPE = "type"; // 文件夹类型 (类型: INTEGER)
/** public static final String SYNC_ID = "sync_id"; // 同步ID (类型: INTEGER)
* public static final String LOCAL_MODIFIED = "local_modified"; // 本地是否修改 (类型: INTEGER)
* <P>: INTEGER (long)</P> public static final String ORIGIN_PARENT_ID = "origin_parent_id"; // 原始父ID (类型: INTEGER)
*/ public static final String GTASK_ID = "gtask_id"; // Google任务ID (类型: TEXT)
public static final String CREATED_DATE = "created_date"; public static final String VERSION = "version"; // 版本号 (类型: INTEGER)
/**
*
* <P>: INTEGER (long)</P>
*/
public static final String MODIFIED_DATE = "modified_date";
/**
*
* <P>: INTEGER (long)</P>
*/
public static final String ALERTED_DATE = "alert_date";
/**
*
* <P>: TEXT</P>
*/
public static final String SNIPPET = "snippet";
/**
* ID
* <P>: INTEGER (long)</P>
*/
public static final String WIDGET_ID = "widget_id";
/**
*
* <P>: INTEGER (long)</P>
*/
public static final String WIDGET_TYPE = "widget_type";
/**
* ID
* <P>: INTEGER (long)</P>
*/
public static final String BG_COLOR_ID = "bg_color_id";
/**
*
* <P>: INTEGER</P>
*/
public static final String HAS_ATTACHMENT = "has_attachment";
/**
*
* <P>: INTEGER (long)</P>
*/
public static final String NOTES_COUNT = "notes_count";
/**
* 0-1-
* <P>: INTEGER</P>
*/
public static final String TYPE = "type";
/**
* ID
* <P>: INTEGER (long)</P>
*/
public static final String SYNC_ID = "sync_id";
/**
*
* <P>: INTEGER</P>
*/
public static final String LOCAL_MODIFIED = "local_modified";
/**
* ID
* <P>: INTEGER</P>
*/
public static final String ORIGIN_PARENT_ID = "origin_parent_id";
/**
* GoogleID
* <P>: TEXT</P>
*/
public static final String GTASK_ID = "gtask_id";
/**
*
* <P>: INTEGER (long)</P>
*/
public static final String VERSION = "version";
} }
// 数据列接口 // DataColumns接口定义数据列
public interface DataColumns { public interface DataColumns {
/** public static final String ID = "_id"; // 唯一ID (类型: INTEGER)
* ID public static final String MIME_TYPE = "mime_type"; // MIME类型 (类型: TEXT)
* <P>: INTEGER (long)</P> public static final String NOTE_ID = "note_id"; // 关联的笔记ID (类型: INTEGER)
*/ public static final String CREATED_DATE = "created_date"; // 创建日期 (类型: INTEGER)
public static final String ID = "_id"; public static final String MODIFIED_DATE = "modified_date"; // 修改日期 (类型: INTEGER)
public static final String CONTENT = "content"; // 数据内容 (类型: TEXT)
/** public static final String DATA1 = "data1"; // 通用数据列 (类型: INTEGER)
* MIME public static final String DATA2 = "data2"; // 通用数据列 (类型: INTEGER)
* <P>: TEXT</P> public static final String DATA3 = "data3"; // 通用数据列 (类型: TEXT)
*/ public static final String DATA4 = "data4"; // 通用数据列 (类型: TEXT)
public static final String MIME_TYPE = "mime_type"; public static final String DATA5 = "data5"; // 通用数据列 (类型: TEXT)
/**
* ID
* <P>: INTEGER (long)</P>
*/
public static final String NOTE_ID = "note_id";
/**
*
* <P>: INTEGER (long)</P>
*/
public static final String CREATED_DATE = "created_date";
/**
*
* <P>: INTEGER (long)</P>
*/
public static final String MODIFIED_DATE = "modified_date";
/**
*
* <P>: TEXT</P>
*/
public static final String CONTENT = "content";
/**
* {@link #MIME_TYPE}
* <P>: INTEGER</P>
*/
public static final String DATA1 = "data1";
/**
* {@link #MIME_TYPE}
* <P>: INTEGER</P>
*/
public static final String DATA2 = "data2";
/**
* {@link #MIME_TYPE}
* <P>: TEXT</P>
*/
public static final String DATA3 = "data3";
/**
* {@link #MIME_TYPE}
* <P>: TEXT</P>
*/
public static final String DATA4 = "data4";
/**
* {@link #MIME_TYPE}
* <P>: TEXT</P>
*/
public static final String DATA5 = "data5";
} }
// 文本笔记类实现了DataColumns接口 // TextNote类实现DataColumns接口定义了文本笔记的结构和相关常量
public static final class TextNote implements DataColumns { public static final class TextNote implements DataColumns {
/** public static final String MODE = DATA1; // 模式:是否为检查列表模式 (类型: INTEGER)
* public static final int MODE_CHECK_LIST = 1; // 检查列表模式标识
* <P>: INTEGER 1: 0: </P> public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; // MIME类型 (文本笔记)
*/ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; // 单项MIME类型
public static final String MODE = DATA1; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); // 内容URI
public static final int MODE_CHECK_LIST = 1;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; // MIME类型定义
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; // 单项MIME类型定义
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); // 内容URI定义
} }
// 通话记录笔记类实现了DataColumns接口 // CallNote类实现DataColumns接口定义了通话记录笔记的结构和相关常量
public static final class CallNote implements DataColumns { public static final class CallNote implements DataColumns {
/** public static final String CALL_DATE = DATA1; // 通话日期 (类型: INTEGER)
* public static final String PHONE_NUMBER = DATA3; // 电话号码 (类型: TEXT)
* <P>: INTEGER (long)</P> public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; // MIME类型 (通话记录)
*/ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; // 单项MIME类型
public static final String CALL_DATE = DATA1; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); // 内容URI
/**
*
* <P>: TEXT</P>
*/
public static final String PHONE_NUMBER = DATA3;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; // MIME类型定义
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; // 单项MIME类型定义
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); // 内容URI定义
} }
} }

@ -1,6 +1,8 @@
/* /*
* Notes * NotesDatabaseHelperNotes
* SQLiteOpenHelper
*/ */
package net.micode.notes.data; package net.micode.notes.data;
import android.content.ContentValues; import android.content.ContentValues;
@ -13,71 +15,69 @@ import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
public class NotesDatabaseHelper extends SQLiteOpenHelper { public class NotesDatabaseHelper extends SQLiteOpenHelper {
// 数据库名称 // 数据库名称
private static final String DB_NAME = "note.db"; private static final String DB_NAME = "note.db";
// 数据库版本号 // 数据库版本号,用于判断数据库结构是否需要升级
private static final int DB_VERSION = 4; private static final int DB_VERSION = 4;
// 表接口,定义了数据库中两个表名 // 表接口,定义了数据库中两个主要表的表名NOTE和DATA
public interface TABLE { public interface TABLE {
public static final String NOTE = "note"; public static final String NOTE = "note"; // 存储笔记信息
public static final String DATA = "data"; // 存储笔记内容的数据表
public static final String DATA = "data";
} }
// 日志标签 // 日志标签,用于输出调试信息
private static final String TAG = "NotesDatabaseHelper"; private static final String TAG = "NotesDatabaseHelper";
// 单例模式,确保数据库辅助类的唯一实例 // 单例模式,确保数据库辅助类的唯一实例
private static NotesDatabaseHelper mInstance; private static NotesDatabaseHelper mInstance;
// 创建NOTE表的SQL语句 // SQL语句创建NOTE表
private static final String CREATE_NOTE_TABLE_SQL = private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" + "CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," + NoteColumns.ID + " INTEGER PRIMARY KEY," + // 笔记唯一ID
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 父文件夹ID
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + // 提醒日期
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + // 背景颜色ID
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建日期
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +// 是否有附件
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改日期
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + // 文件夹内笔记数量
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + // 笔记摘要
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + // 笔记类型
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + // 小部件ID
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + // 小部件类型
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + // 同步ID
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +// 本地是否已修改
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +// 原始父ID
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + // Google任务ID
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + // 笔记版本号
")"; ")";
// 创建DATA表的SQL语句 // SQL语句创建DATA表
private static final String CREATE_DATA_TABLE_SQL = private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" + "CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," + DataColumns.ID + " INTEGER PRIMARY KEY," + // 数据项唯一ID
DataColumns.MIME_TYPE + " TEXT NOT NULL," + DataColumns.MIME_TYPE + " TEXT NOT NULL," + // 数据项的MIME类型
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + // 关联的NOTE表ID
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建日期
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改日期
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," + DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," + // 内容
DataColumns.DATA1 + " INTEGER," + DataColumns.DATA1 + " INTEGER," + // 通用数据列1
DataColumns.DATA2 + " INTEGER," + DataColumns.DATA2 + " INTEGER," + // 通用数据列2
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + // 通用数据列3
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + // 通用数据列4
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + // 通用数据列5
")"; ")";
// 创建DATA表的NOTE_ID索引的SQL语句 // SQL语句创建DATA表的NOTE_ID字段的索引提高查询效率
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL = private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " + "CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");"; TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
// 当更新NOTE表中的PARENT_ID字段时增加目标文件夹的NOTE_COUNT // 触发器在更改NOTE表中PARENT_ID字段时增加目标文件夹的NOTES_COUNT
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update " + "CREATE TRIGGER increase_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
@ -87,7 +87,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END"; " END";
// 当从文件夹移动NOTE时减少源文件夹的NOTE_COUNT // 触发器在更改NOTE表中PARENT_ID字段时减少源文件夹的NOTES_COUNT
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " + "CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
@ -98,7 +98,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" + " AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END"; " END";
// 当插入新NOTE时增加目标文件夹的NOTE_COUNT // 触发器在NOTE表插入新记录时增加目标文件夹的NOTES_COUNT
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " + "CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE + " AFTER INSERT ON " + TABLE.NOTE +
@ -108,7 +108,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END"; " END";
// 当删除NOTE时减少文件夹的NOTE_COUNT // 触发器在NOTE表删除记录时减少文件夹的NOTES_COUNT
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " + "CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + " AFTER DELETE ON " + TABLE.NOTE +
@ -119,7 +119,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" AND " + NoteColumns.NOTES_COUNT + ">0;" + " AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END"; " END";
// 当插入DATA时如果类型为NOTE则更新关联NOTE的内容 // 触发器在DATA表插入新记录时若MIME类型为NOTE更新NOTE表的SNIPPET内容
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER = private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " + "CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA + " AFTER INSERT ON " + TABLE.DATA +
@ -130,7 +130,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END"; " END";
// 当更新DATA时如果类型为NOTE则更新关联NOTE的内容 // 触发器在DATA表更新记录时若MIME类型为NOTE更新NOTE表的SNIPPET内容
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER = private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " + "CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA + " AFTER UPDATE ON " + TABLE.DATA +
@ -141,7 +141,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END"; " END";
// 当删除DATA时如果类型为NOTE则更新关联NOTE的内容为空 // 触发器在DATA表删除记录时若MIME类型为NOTE清空NOTE表的SNIPPET内容
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER = private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " + "CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA + " AFTER delete ON " + TABLE.DATA +
@ -152,7 +152,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END"; " END";
// 当删除NOTE时删除关联的DATA // 触发器在NOTE表删除记录时删除关联的所有DATA记录
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER = private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " + "CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + " AFTER DELETE ON " + TABLE.NOTE +
@ -161,7 +161,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";
// 当删除NOTE时删除属于该NOTE的子NOTE // 触发器在NOTE表删除文件夹记录时删除该文件夹内的所有子NOTE记录
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER = private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " + "CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + " AFTER DELETE ON " + TABLE.NOTE +
@ -170,7 +170,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";
// 当NOTE移动到回收站文件夹时将所有子NOTE也移动到回收站 // 触发器在NOTE表更新记录时若目标为回收站将所有子NOTE也移入回收站
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER = private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " + "CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE + " AFTER UPDATE ON " + TABLE.NOTE +
@ -181,6 +181,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";
/** /**
* *
* *
@ -190,199 +191,264 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
super(context, DB_NAME, null, DB_VERSION); super(context, DB_NAME, null, DB_VERSION);
} }
/** /*
* NOTENOTE * NOTENOTE
* *
* @param db SQLiteDatabaseSQL * @param db SQLiteDatabaseSQL
*/ */
/**
* NOTE
*
* @param db SQLiteDatabaseSQL
*/
public void createNoteTable(SQLiteDatabase db) { public void createNoteTable(SQLiteDatabase db) {
// 执行SQL语句创建NOTE表定义表结构及默认值
db.execSQL(CREATE_NOTE_TABLE_SQL); db.execSQL(CREATE_NOTE_TABLE_SQL);
// 重新创建NOTE表的相关触发器以确保数据完整性和联动效果
reCreateNoteTableTriggers(db); reCreateNoteTableTriggers(db);
// 创建系统文件夹,例如根文件夹、临时文件夹和回收站,以便分类管理笔记
createSystemFolder(db); createSystemFolder(db);
// 输出调试信息确认NOTE表已创建成功
Log.d(TAG, "note table has been created"); Log.d(TAG, "note table has been created");
} }
/** /**
* *
* *
* @param db SQLiteDatabase * @param db SQLiteDatabase
*/ */
/*
* NOTE
* NOTE
*
* @param db SQLiteDatabaseSQL
*/
private void reCreateNoteTableTriggers(SQLiteDatabase db) { private void reCreateNoteTableTriggers(SQLiteDatabase db) {
// 删除旧的触发器 // 删除旧的触发器,以确保不会重复创建触发器或造成冲突
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); // 删除当更新文件夹时增加计数的触发器
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); // 删除当更新文件夹时减少计数的触发器
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete"); db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete"); // 删除当删除笔记时减少计数的触发器
db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete"); db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete"); // 删除当删除笔记时删除相关数据的触发器
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert"); // 删除当插入新笔记时增加计数的触发器
db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete"); db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete"); // 删除当删除文件夹时删除其子笔记的触发器
db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash"); db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash"); // 删除当文件夹被移至回收站时移动其子笔记的触发器
// 创建新的触发器
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); // 创建新的触发器,以确保数据完整性和联动效果
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); // 创建更新时增加文件夹计数的触发器
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER); db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); // 创建更新时减少文件夹计数的触发器
db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER); db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER); // 创建删除时减少文件夹计数的触发器
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER); db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER); // 创建删除笔记时删除关联数据的触发器
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER); db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER); // 创建插入新笔记时增加文件夹计数的触发器
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER); db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER); // 创建删除文件夹时删除其子笔记的触发器
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER); // 创建移动文件夹至回收站时移动子笔记的触发器
} }
/** /**
* *
* -
* -
* -
* -
*
* *
* @param db SQLiteDatabase * @param db SQLiteDatabase
*/ */
private void createSystemFolder(SQLiteDatabase db) { private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues(); // 创建ContentValues对象用于存储列值
// 创建通话记录文件夹
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER); // 创建通话记录文件夹,保存与通话记录相关的笔记
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER); // 设置通话记录文件夹的ID
db.insert(TABLE.NOTE, null, values); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); // 设置文件夹类型为系统文件夹
// 创建根文件夹(默认文件夹) db.insert(TABLE.NOTE, null, values); // 插入通话记录文件夹到NOTE表
values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER); // 创建根文件夹(默认文件夹),用于存放笔记
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.clear(); // 清空ContentValues以重用
db.insert(TABLE.NOTE, null, values); values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER); // 设置根文件夹的ID
// 创建临时文件夹,用于移动笔记 values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); // 设置文件夹类型为系统文件夹
values.clear(); db.insert(TABLE.NOTE, null, values); // 插入根文件夹到NOTE表
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); // 创建临时文件夹,用于存放未归类的笔记或移动中的笔记
db.insert(TABLE.NOTE, null, values); values.clear(); // 清空ContentValues以重用
// 创建回收站文件夹 values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER); // 设置临时文件夹的ID
values.clear(); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); // 设置文件夹类型为系统文件夹
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); db.insert(TABLE.NOTE, null, values); // 插入临时文件夹到NOTE表
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); // 创建回收站文件夹,用于存放已删除的笔记
values.clear(); // 清空ContentValues以重用
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); // 设置回收站文件夹的ID
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); // 设置文件夹类型为系统文件夹
db.insert(TABLE.NOTE, null, values); // 插入回收站文件夹到NOTE表
} }
/** /**
* * DATA
* DATA
* *
* @param db SQLiteDatabase * @param db SQLiteDatabaseSQL
*/ */
public void createDataTable(SQLiteDatabase db) { public void createDataTable(SQLiteDatabase db) {
// 执行SQL语句创建DATA表定义表的结构和字段
db.execSQL(CREATE_DATA_TABLE_SQL); db.execSQL(CREATE_DATA_TABLE_SQL);
// 重新创建DATA表的触发器以确保表的数据一致性和触发器的最新定义
reCreateDataTableTriggers(db); reCreateDataTableTriggers(db);
// 创建NOTE_ID索引提高与NOTE表的关联查询效率
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
// 输出调试信息确认DATA表已创建成功
Log.d(TAG, "data table has been created"); Log.d(TAG, "data table has been created");
} }
/** /**
* * DATA
* DATANOTE
* *
* @param db SQLiteDatabase * @param db SQLiteDatabaseSQL
*/ */
private void reCreateDataTableTriggers(SQLiteDatabase db) { private void reCreateDataTableTriggers(SQLiteDatabase db) {
// 删除旧的触发器 // 删除旧的触发器,确保重新创建时不会出现重复定义的问题
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); // 删除插入操作触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update"); db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update"); // 删除更新操作触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete"); db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete"); // 删除删除操作触发器
// 创建新的触发器
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER); // 创建新的触发器用于管理DATA表和NOTE表之间的关联数据同步
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER); // 当DATA表插入新记录时更新NOTE表内容
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER); // 当DATA表更新记录时更新NOTE表内容
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER); // 当DATA表删除记录时清空NOTE表内容
} }
/** /**
* NotesDatabaseHelper * NotesDatabaseHelper
*
* *
* @param context Context * @param context Context
* @return NotesDatabaseHelper * @return NotesDatabaseHelper
*/ */
static synchronized NotesDatabaseHelper getInstance(Context context) { static synchronized NotesDatabaseHelper getInstance(Context context) {
// 检查是否已有实例
if (mInstance == null) { if (mInstance == null) {
// 如果实例为空,则创建新的 NotesDatabaseHelper 实例
mInstance = new NotesDatabaseHelper(context); mInstance = new NotesDatabaseHelper(context);
} }
// 返回唯一实例
return mInstance; return mInstance;
} }
/** /**
* *
* NOTEDATA
* *
* @param db SQLiteDatabase * @param db SQLiteDatabaseSQL
*/ */
@Override @Override
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {
// 调用createNoteTable方法创建NOTE表并配置相关触发器和系统文件夹
createNoteTable(db); createNoteTable(db);
// 调用createDataTable方法创建DATA表并配置相关触发器和索引
createDataTable(db); createDataTable(db);
} }
/** /**
* *
*
* *
* @param db SQLiteDatabase * @param db SQLiteDatabaseSQL
* @param oldVersion int * @param oldVersion int
* @param newVersion int * @param newVersion int
*/ */
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean reCreateTriggers = false; boolean reCreateTriggers = false; // 标记是否需要重新创建触发器
boolean skipV2 = false; boolean skipV2 = false; // 标记是否需要跳过版本2的升级
// 根据旧版本号逐步升级
// 检查并按顺序执行版本升级
if (oldVersion == 1) { if (oldVersion == 1) {
upgradeToV2(db); upgradeToV2(db); // 从版本1升级到版本2
skipV2 = true; // 这次升级包括从 v2 到 v3 的升级 skipV2 = true; // 跳过后续升级到版本2的操作
oldVersion++; oldVersion++;
} }
if (oldVersion == 2 && !skipV2) { if (oldVersion == 2 && !skipV2) {
upgradeToV3(db); upgradeToV3(db); // 从版本2升级到版本3
reCreateTriggers = true; reCreateTriggers = true; // 设置标记为true表示需要重新创建触发器
oldVersion++; oldVersion++;
} }
if (oldVersion == 3) { if (oldVersion == 3) {
upgradeToV4(db); upgradeToV4(db); // 从版本3升级到版本4
oldVersion++; oldVersion++;
} }
// 如果升级过程中需要重新创建触发器则调用方法重新创建NOTE表和DATA表的触发器
if (reCreateTriggers) { if (reCreateTriggers) {
reCreateNoteTableTriggers(db); reCreateNoteTableTriggers(db); // 重新创建NOTE表的触发器
reCreateDataTableTriggers(db); reCreateDataTableTriggers(db); // 重新创建DATA表的触发器
} }
// 检查是否所有升级已成功完成,如果未完成则抛出异常
if (oldVersion != newVersion) { if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion throw new IllegalStateException("Upgrade notes database to version " + newVersion + " fails");
+ "fails");
} }
} }
/** /**
* 12 * 12NOTEDATA
*
* *
* @param db SQLiteDatabase * @param db SQLiteDatabaseSQL
*/ */
private void upgradeToV2(SQLiteDatabase db) { private void upgradeToV2(SQLiteDatabase db) {
// 删除旧表,创建新表 // 删除旧的NOTE表和DATA表确保版本2的结构重新定义
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); // 删除NOTE表
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); // 删除DATA表
// 重新创建NOTE表和DATA表应用最新的结构和默认数据
createNoteTable(db); createNoteTable(db);
createDataTable(db); createDataTable(db);
} }
/** /**
* 23 * 23使
* *
* @param db SQLiteDatabase * @param db SQLiteDatabaseSQL
*/ */
private void upgradeToV3(SQLiteDatabase db) { private void upgradeToV3(SQLiteDatabase db) {
// 删除未使用的触发器 // 删除未使用的触发器,确保数据库结构的简洁和更新
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert"); // 删除插入触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete"); db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete"); // 删除删除触发器
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update"); db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update"); // 删除更新触发器
// 添加一个用于 gtask id 的列
// 添加新的字段用于存储Google任务ID方便同步外部任务
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''"); + " TEXT NOT NULL DEFAULT ''");
// 添加一个回收站系统文件夹
// 添加一个回收站系统文件夹,专门用于存储已删除的笔记
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); // 设置回收站文件夹的ID
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); // 设置类型为系统文件夹
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values); // 插入回收站文件夹到NOTE表
} }
/** /**
* 34 * 34NOTE
* *
* @param db SQLiteDatabase * @param db SQLiteDatabaseSQL
*/ */
private void upgradeToV4(SQLiteDatabase db) { private void upgradeToV4(SQLiteDatabase db) {
// 添加版本号列 // 添加新的版本号字段,用于记录笔记的版本以支持版本控制或同步机制
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0"); + " INTEGER NOT NULL DEFAULT 0");
} }
} }

@ -1,39 +1,38 @@
/** /**
* MetaDataTask * MetaDataTaskID
* JSON
*/ */
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
import android.database.Cursor; import android.database.Cursor;
import android.util.Log; import android.util.Log;
import net.micode.notes.tool.GTaskStringUtils; import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
public class MetaData extends Task { public class MetaData extends Task {
private final static String TAG = MetaData.class.getSimpleName(); // 日志标签 private final static String TAG = MetaData.class.getSimpleName(); // 日志标签
private String mRelatedGid = null; // 与任务相关的全局ID private String mRelatedGid = null; // 与任务相关的全局ID
/** /**
* * ID
* *
* @param gid ID * @param gid ID
* @param metaInfo JSON * @param metaInfo JSON
*/ */
public void setMeta(String gid, JSONObject metaInfo) { public void setMeta(String gid, JSONObject metaInfo) {
try { try {
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); // 将任务的全局ID添加到元信息中 // 在元信息中添加任务的全局ID
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
} catch (JSONException e) { } catch (JSONException e) {
Log.e(TAG, "failed to put related gid"); Log.e(TAG, "无法添加相关的全局ID");
} }
setNotes(metaInfo.toString()); // 将元信息设置为任务的笔记 setNotes(metaInfo.toString()); // 将完整的元信息转换为字符串后存储为任务的笔记
setName(GTaskStringUtils.META_NOTE_NAME); // 设置任务的名称为特定的元数据标志名称 setName(GTaskStringUtils.META_NOTE_NAME); // 将任务名称设置为特定的元数据名称
} }
/** /**
* ID * ID
* *
* @return ID * @return ID
*/ */
@ -44,7 +43,7 @@ public class MetaData extends Task {
/** /**
* *
* *
* @return true * @return true
*/ */
@Override @Override
public boolean isWorthSaving() { public boolean isWorthSaving() {
@ -52,54 +51,58 @@ public class MetaData extends Task {
} }
/** /**
* JSON * JSON
* JSONID
* *
* @param js JSON * @param js JSON
*/ */
@Override @Override
public void setContentByRemoteJSON(JSONObject js) { public void setContentByRemoteJSON(JSONObject js) {
super.setContentByRemoteJSON(js); super.setContentByRemoteJSON(js); // 调用父类方法设置通用内容
if (getNotes() != null) { if (getNotes() != null) {
try { try {
// 从笔记中提取任务相关的全局ID
JSONObject metaInfo = new JSONObject(getNotes().trim()); JSONObject metaInfo = new JSONObject(getNotes().trim());
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); // 从笔记中提取相关的全局ID mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
} catch (JSONException e) { } catch (JSONException e) {
Log.w(TAG, "failed to get related gid"); Log.w(TAG, "获取相关全局ID失败");
mRelatedGid = null; // 提取失败时设置相关ID为null mRelatedGid = null; // 若解析失败相关ID设为null
} }
} }
} }
/** /**
* JSON * JSON
* *
* @param js JSON * @param js JSON
*/ */
@Override @Override
public void setContentByLocalJSON(JSONObject js) { public void setContentByLocalJSON(JSONObject js) {
// this function should not be called // 此方法不适用于MetaData类直接抛出异常
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); throw new IllegalAccessError("MetaData:setContentByLocalJSON 不应被调用");
} }
/** /**
* JSON * JSON
* *
* @return JSON * @return JSON
*/ */
@Override @Override
public JSONObject getLocalJSONFromContent() { public JSONObject getLocalJSONFromContent() {
throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); // 此方法不适用于MetaData类直接抛出异常
throw new IllegalAccessError("MetaData:getLocalJSONFromContent 不应被调用");
} }
/** /**
* *
* *
* @param c * @param c
* @return * @return
*/ */
@Override @Override
public int getSyncAction(Cursor c) { public int getSyncAction(Cursor c) {
throw new IllegalAccessError("MetaData:getSyncAction should not be called"); // 此方法不适用于MetaData类直接抛出异常
throw new IllegalAccessError("MetaData:getSyncAction 不应被调用");
} }
} }

@ -6,27 +6,26 @@
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
import android.database.Cursor; import android.database.Cursor;
import org.json.JSONObject; import org.json.JSONObject;
// 定义节点同步动作的常量 // 定义节点同步动作的常量,用于区分节点的不同同步操作类型
public abstract class Node { public abstract class Node {
public static final int SYNC_ACTION_NONE = 0; // 无动作 public static final int SYNC_ACTION_NONE = 0; // 无同步动作
public static final int SYNC_ACTION_ADD_REMOTE = 1; // 添加远程节点 public static final int SYNC_ACTION_ADD_REMOTE = 1; // 添加远程节点
public static final int SYNC_ACTION_ADD_LOCAL = 2; // 添加本地节点 public static final int SYNC_ACTION_ADD_LOCAL = 2; // 添加本地节点
public static final int SYNC_ACTION_DEL_REMOTE = 3; // 删除远程节点 public static final int SYNC_ACTION_DEL_REMOTE = 3; // 删除远程节点
public static final int SYNC_ACTION_DEL_LOCAL = 4; // 删除本地节点 public static final int SYNC_ACTION_DEL_LOCAL = 4; // 删除本地节点
public static final int SYNC_ACTION_UPDATE_REMOTE = 5; // 更新远程节点 public static final int SYNC_ACTION_UPDATE_REMOTE = 5; // 更新远程节点
public static final int SYNC_ACTION_UPDATE_LOCAL = 6; // 更新本地节点 public static final int SYNC_ACTION_UPDATE_LOCAL = 6; // 更新本地节点
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; // 更新冲突 public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; // 同步冲突更新
public static final int SYNC_ACTION_ERROR = 8; // 同步错误 public static final int SYNC_ACTION_ERROR = 8; // 同步错误
private String mGid; // 全局唯一标识符 private String mGid; // 全局唯一标识符
private String mName; // 节点名称 private String mName; // 节点名称
private long mLastModified; // 最后修改时间 private long mLastModified; // 最后修改时间
private boolean mDeleted; // 节点是否被删除的标志 private boolean mDeleted; // 节点是否被删除的标志
// 构造函数,初始化节点属性 // 构造函数,初始化节点的默认属性
public Node() { public Node() {
mGid = null; mGid = null;
mName = ""; mName = "";
@ -34,22 +33,22 @@ public abstract class Node {
mDeleted = false; mDeleted = false;
} }
// 生成创建节点的JSON动作 // 抽象方法由子类实现生成创建节点的JSON表示
public abstract JSONObject getCreateAction(int actionId); public abstract JSONObject getCreateAction(int actionId);
// 生成更新节点的JSON动作 // 抽象方法由子类实现生成更新节点的JSON表示
public abstract JSONObject getUpdateAction(int actionId); public abstract JSONObject getUpdateAction(int actionId);
// 根据远程JSON内容设置节点内容 // 抽象方法由子类实现设置节点内容为远程JSON内容
public abstract void setContentByRemoteJSON(JSONObject js); public abstract void setContentByRemoteJSON(JSONObject js);
// 根据本地JSON内容设置节点内容 // 抽象方法由子类实现设置节点内容为本地JSON内容
public abstract void setContentByLocalJSON(JSONObject js); public abstract void setContentByLocalJSON(JSONObject js);
// 从内容生成本地JSON表示 // 抽象方法由子类实现从节点内容生成本地JSON对象
public abstract JSONObject getLocalJSONFromContent(); public abstract JSONObject getLocalJSONFromContent();
// 根据Cursor获取同步动作 // 抽象方法,由子类实现,根据Cursor对象获取节点的同步动作
public abstract int getSyncAction(Cursor c); public abstract int getSyncAction(Cursor c);
// 设置节点的全局唯一标识符 // 设置节点的全局唯一标识符
@ -57,17 +56,17 @@ public abstract class Node {
this.mGid = gid; this.mGid = gid;
} }
// 设置节点名称 // 设置节点名称
public void setName(String name) { public void setName(String name) {
this.mName = name; this.mName = name;
} }
// 设置节点最后修改时间 // 设置节点最后修改时间
public void setLastModified(long lastModified) { public void setLastModified(long lastModified) {
this.mLastModified = lastModified; this.mLastModified = lastModified;
} }
// 设置节点是否被删除 // 设置节点的删除状态
public void setDeleted(boolean deleted) { public void setDeleted(boolean deleted) {
this.mDeleted = deleted; this.mDeleted = deleted;
} }
@ -77,19 +76,18 @@ public abstract class Node {
return this.mGid; return this.mGid;
} }
// 获取节点名称 // 获取节点名称
public String getName() { public String getName() {
return this.mName; return this.mName;
} }
// 获取节点最后修改时间 // 获取节点最后修改时间
public long getLastModified() { public long getLastModified() {
return this.mLastModified; return this.mLastModified;
} }
// 获取节点是否被删除的标志 // 获取节点的删除状态
public boolean getDeleted() { public boolean getDeleted() {
return this.mDeleted; return this.mDeleted;
} }
} }

@ -1,7 +1,8 @@
/* /*
* SqlData * SqlData
* JSON Cursor * JSON Cursor
*/ */
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
import android.content.ContentResolver; import android.content.ContentResolver;
@ -22,53 +23,46 @@ import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
public class SqlData { public class SqlData {
// 日志标签 // 日志标签,用于日志输出
private static final String TAG = SqlData.class.getSimpleName(); private static final String TAG = SqlData.class.getSimpleName();
// 无效ID常量 // 无效ID常量
private static final int INVALID_ID = -99999; private static final int INVALID_ID = -99999;
// 查询时使用的字段投影 // 查询时使用的字段投影,定义要从数据库查询的列
public static final String[] PROJECTION_DATA = new String[]{ public static final String[] PROJECTION_DATA = new String[]{
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1, DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3 DataColumns.DATA3
}; };
// 字段在Cursor中的索引 // 数据列在Cursor中的索引
public static final int DATA_ID_COLUMN = 0; public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1; public static final int DATA_MIME_TYPE_COLUMN = 1;
public static final int DATA_CONTENT_COLUMN = 2; public static final int DATA_CONTENT_COLUMN = 2;
public static final int DATA_CONTENT_DATA_1_COLUMN = 3; public static final int DATA_CONTENT_DATA_1_COLUMN = 3;
public static final int DATA_CONTENT_DATA_3_COLUMN = 4; public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
// ContentResolver用于操作内容提供者 // ContentResolver用于操作内容提供者的接口
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
// 标记当前对象是创建状态还是更新状态 // 标记当前对象的状态,是新建状态还是已有状态
private boolean mIsCreate; private boolean mIsCreate;
// 数据项ID // 数据项ID、MIME类型、内容、附加数据等字段
private long mDataId; private long mDataId;
// 数据项的MIME类型
private String mDataMimeType; private String mDataMimeType;
// 数据项的内容
private String mDataContent; private String mDataContent;
// 数据项的附加数据1
private long mDataContentData1; private long mDataContentData1;
// 数据项的附加数据3
private String mDataContentData3; private String mDataContentData3;
// 存储与数据库不同步的数据变化 // 存储对数据库中的数据项的未提交更改
private ContentValues mDiffDataValues; private ContentValues mDiffDataValues;
/* /*
* SqlData *
*
*
* @param context ContentResolver * @param context ContentResolver
*/ */
public SqlData(Context context) { public SqlData(Context context) {
@ -83,7 +77,9 @@ public class SqlData {
} }
/* /*
* SqlData *
* Cursor
*
* @param context ContentResolver * @param context ContentResolver
* @param c Cursor * @param c Cursor
*/ */
@ -95,7 +91,8 @@ public class SqlData {
} }
/* /*
* Cursor * CursorSqlData
*
* @param c Cursor * @param c Cursor
*/ */
private void loadFromCursor(Cursor c) { private void loadFromCursor(Cursor c) {
@ -107,7 +104,9 @@ public class SqlData {
} }
/* /*
* JSON * JSON
* JSON
*
* @param js JSON * @param js JSON
* @throws JSONException JSON * @throws JSONException JSON
*/ */
@ -145,13 +144,14 @@ public class SqlData {
} }
/* /*
* JSON * JSON
* @return JSON *
* @return JSON
* @throws JSONException JSON * @throws JSONException JSON
*/ */
public JSONObject getContent() throws JSONException { public JSONObject getContent() throws JSONException {
if (mIsCreate) { if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet"); Log.e(TAG, "尚未将数据项创建到数据库中");
return null; return null;
} }
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
@ -164,37 +164,35 @@ public class SqlData {
} }
/* /*
* *
*
*
* @param noteId ID * @param noteId ID
* @param validateVersion * @param validateVersion
* @param version * @param version
*/ */
public void commit(long noteId, boolean validateVersion, long version) { public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) { if (mIsCreate) {
// 处理新数据项的插入 // 处理新数据项的插入
if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) { if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) {
mDiffDataValues.remove(DataColumns.ID); mDiffDataValues.remove(DataColumns.ID);
} }
mDiffDataValues.put(DataColumns.NOTE_ID, noteId); mDiffDataValues.put(DataColumns.NOTE_ID, noteId);
Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues); Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues);
try { try {
mDataId = Long.valueOf(uri.getPathSegments().get(1)); mDataId = Long.valueOf(uri.getPathSegments().get(1));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString()); Log.e(TAG, "获取笔记ID出错: " + e.toString());
throw new ActionFailureException("create note failed"); throw new ActionFailureException("创建笔记失败");
} }
} else { } else {
// 处理现有数据项的更新 // 更新已有数据项
if (mDiffDataValues.size() > 0) { if (mDiffDataValues.size() > 0) {
int result = 0; int result = 0;
if (!validateVersion) { if (!validateVersion) {
// 不验证版本号时直接更新
result = mContentResolver.update(ContentUris.withAppendedId( result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null); Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else { } else {
// 验证版本号时条件更新
result = mContentResolver.update(ContentUris.withAppendedId( result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE " ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
@ -203,22 +201,20 @@ public class SqlData {
}); });
} }
if (result == 0) { if (result == 0) {
Log.w(TAG, "there is no update. maybe user updates note when syncing"); Log.w(TAG, "没有更新,可能是在同步过程中用户更新了笔记");
} }
} }
} }
mDiffDataValues.clear(); // 清空待更新数据并重置状态
// 清理并重置状态 mIsCreate = false; // 设置为更新状态
mDiffDataValues.clear();
mIsCreate = false;
} }
/* /*
* ID * ID
* @return ID *
* @return ID
*/ */
public long getId() { public long getId() {
return mDataId; return mDataId;
} }
} }

@ -152,42 +152,73 @@ public class SqlNote {
/** /**
* ID * ID
* `SqlNote` ID
*
* *
* @param context ActivityApplication * @param context Activity Application 访
* @param id ID * @param id ID
*/ */
public SqlNote(Context context, long id) { public SqlNote(Context context, long id) {
// 初始化上下文和内容解析器,用于后续数据库操作
mContext = context; mContext = context;
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
// 设置标志为false表示该实例是从已有笔记加载而非创建新的笔记
mIsCreate = false; mIsCreate = false;
// 调用辅助方法从数据库中加载指定 ID 的笔记内容,并初始化属性
loadFromCursor(id); loadFromCursor(id);
// 初始化数据列表,用于存储与该笔记关联的数据项
mDataList = new ArrayList<SqlData>(); mDataList = new ArrayList<SqlData>();
// 检查笔记类型是否为普通笔记类型
// 如果是普通笔记类型,则加载该笔记的所有关联数据内容
if (mType == Notes.TYPE_NOTE) if (mType == Notes.TYPE_NOTE)
loadDataContent(); loadDataContent();
// 初始化差异值容器,用于记录该笔记对象的更改,便于后续同步或提交更新到数据库
mDiffNoteValues = new ContentValues(); mDiffNoteValues = new ContentValues();
} }
// 从数据库中加载笔记数据
/**
* ID
* `SqlNote`
*
* @param id ID
*/
private void loadFromCursor(long id) { private void loadFromCursor(long id) {
Cursor c = null; Cursor c = null; // 定义游标,用于处理数据库查询结果
try { try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)", // 执行查询,使用 ContentResolver 通过 URI 和 ID 从数据库中检索笔记信息
new String[]{ c = mContentResolver.query(
String.valueOf(id) Notes.CONTENT_NOTE_URI, // 笔记内容 URI
}, null); PROJECTION_NOTE, // 查询所需列的投影
"(_id=?)", // 查询条件,指定笔记 ID
new String[]{String.valueOf(id)}, // 查询条件参数,转换为字符串格式的 ID
null // 不指定排序顺序
);
// 检查查询结果是否非空,并尝试移动到第一条记录
if (c != null) { if (c != null) {
if (c.moveToNext()) { if (c.moveToNext()) {
// 调用 `loadFromCursor(Cursor)` 方法,从游标中提取数据并设置实例属性
loadFromCursor(c); loadFromCursor(c);
} else { } else {
// 如果查询结果为空,记录警告日志信息
Log.w(TAG, "loadFromCursor: cursor = null"); Log.w(TAG, "loadFromCursor: cursor = null");
} }
} }
} finally { } finally {
if (c != null) // 确保游标在使用完后关闭,防止资源泄露
if (c != null) {
c.close(); c.close();
}
} }
} }
// 从Cursor中加载笔记数据到实例属性 // 从Cursor中加载笔记数据到实例属性
private void loadFromCursor(Cursor c) { private void loadFromCursor(Cursor c) {
mId = c.getLong(ID_COLUMN); mId = c.getLong(ID_COLUMN);
@ -206,39 +237,45 @@ public class SqlNote {
/** /**
* *
* note_idmDataList * `note_id` `mDataList`
*/ */
private void loadDataContent() { private void loadDataContent() {
Cursor c = null; Cursor c = null; // 定义游标,用于处理数据库查询结果
mDataList.clear(); mDataList.clear(); // 清空现有的 `mDataList` 列表,以准备加载新的数据项
try { try {
// 查询指定note_id的数据 // 执行查询,通过 URI 从数据库中检索与当前笔记 ID 关联的数据
c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA, c = mContentResolver.query(
"(note_id=?)", new String[]{ Notes.CONTENT_DATA_URI, // 数据内容的 URI
String.valueOf(mId) SqlData.PROJECTION_DATA, // 查询所需的列
}, null); "(note_id=?)", // 查询条件,匹配当前笔记 ID
new String[]{String.valueOf(mId)}, // 查询条件参数,当前笔记 ID 的字符串表示
null // 不指定排序顺序
);
// 检查查询结果是否为空
if (c != null) { if (c != null) {
// 如果查询结果为空,打印警告信息并返回 // 如果查询结果为空(无数据),记录警告日志并返回
if (c.getCount() == 0) { if (c.getCount() == 0) {
Log.w(TAG, "it seems that the note has not data"); Log.w(TAG, "it seems that the note has not data");
return; return;
} }
// 遍历查询结果并加载到mDataList中 // 遍历查询结果的每一行,将数据项添加到 `mDataList` 列表
while (c.moveToNext()) { while (c.moveToNext()) {
SqlData data = new SqlData(mContext, c); SqlData data = new SqlData(mContext, c); // 通过 `Cursor` 创建 `SqlData` 实例
mDataList.add(data); mDataList.add(data); // 将数据项添加到 `mDataList` 列表
} }
} else { } else {
// 如果查询结果为null打印警告信息 // 如果查询结果为 `null`,记录警告日志
Log.w(TAG, "loadDataContent: cursor = null"); Log.w(TAG, "loadDataContent: cursor = null");
} }
} finally { } finally {
// 释放资源 // 确保游标在使用完后关闭,防止资源泄露
if (c != null) if (c != null)
c.close(); c.close();
} }
} }
/** /**
* *
* JSONObject * JSONObject
@ -312,37 +349,41 @@ public class SqlNote {
/** /**
* *
* JSONObject * `JSONObject`
* *
* @return JSONObjectnull * @return `JSONObject` `null`
*/ */
public JSONObject getContent() { public JSONObject getContent() {
try { try {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject(); // 初始化一个空的 JSON 对象,用于存放笔记数据
// 如果当前笔记尚未在数据库中创建,返回 null
if (mIsCreate) { if (mIsCreate) {
// 如果笔记尚未在数据库中创建返回null
Log.e(TAG, "it seems that we haven't created this in database yet"); Log.e(TAG, "it seems that we haven't created this in database yet");
return null; return null;
} }
JSONObject note = new JSONObject(); JSONObject note = new JSONObject(); // 初始化一个空的 JSON 对象,用于存放具体的笔记内容
// 根据笔记类型填充不同的信息到note JSONObject中
// 该部分通过条件判断根据mType选择需要填充的信息 // 根据笔记的类型,选择性地填充不同的数据字段到 `note` JSON 对象中
// 如:类型为文件夹或笔记时处理的字段会有所不同
// 将note和data信息添加到js中 // 将 `note` 和关联的 `data` 信息添加到主 JSON 对象 `js` 中
js.put(GTaskStringUtils.META_HEAD_NOTE, note); js.put(GTaskStringUtils.META_HEAD_NOTE, note); // 添加 `note` 到主 JSON 对象中
// 处理数据项数组将其添加到js中
return js; // 处理 `mDataList` 数据项数组,将其逐项转换为 JSON 并添加到 `js` 中
// 每一个数据项会被转换成 JSON 格式并包含在 `js` 中,以便完整描述当前笔记的内容
return js; // 返回最终生成的 JSON 对象
} catch (JSONException e) { } catch (JSONException e) {
// 处理JSON构建异常 // 捕获 JSON 构建过程中可能出现的异常,记录错误日志
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
} }
return null; return null; // 如果出现异常或转换失败,返回 `null`
} }
/** /**
* id * id
* *

@ -124,44 +124,54 @@ public class Task extends Node {
} }
/** /**
* JSON * JSON
* JSON
* *
* @param actionId ID * @param actionId ID
* @return JSON * @return JSON
* @throws ActionFailureException JSON * @throws ActionFailureException JSON
*/ */
public JSONObject getUpdateAction(int actionId) { public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject(); // 主 JSON 对象,用于存放更新任务信息
try { try {
// 设置动作类型为更新 // 设置动作类型为 "更新",此字段用于标识请求的具体操作
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// 设置动作ID // 设置动作 ID,用于唯一标识此更新动作,便于追踪请求
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 设置任务ID // 设置任务的全局唯一 ID,用于远程系统识别此任务
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// 设置任务实体信息 // 创建任务实体信息的子 JSON 对象,包含任务的具体属性
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 设置任务名称
// 如果任务包含笔记,则添加笔记字段
if (getNotes() != null) { if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
} }
// 设置任务的删除状态,若为已删除则该字段为 true
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
// 将任务实体信息添加到主 JSON 对象的 "entity_delta" 字段中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) { } catch (JSONException e) {
// 如果 JSON 构建过程中出现异常,记录错误日志并抛出自定义异常
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
throw new ActionFailureException("fail to generate task-update jsonobject"); throw new ActionFailureException("fail to generate task-update jsonobject");
} }
// 返回最终生成的 JSON 对象
return js; return js;
} }
/** /**
* JSON * JSON
* *
@ -204,41 +214,49 @@ public class Task extends Node {
} }
/** /**
* JSON * JSON
* JSON
* *
* @param js JSON * @param js JSON
* @throws ActionFailureException JSON
*/ */
public void setContentByLocalJSON(JSONObject js) { public void setContentByLocalJSON(JSONObject js) {
// 检查 JSON 对象是否为 null并检查必要的键是否存在
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE) if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) { || !js.has(GTaskStringUtils.META_HEAD_DATA)) {
Log.w(TAG, "setContentByLocalJSON: nothing is available"); Log.w(TAG, "setContentByLocalJSON: nothing is available"); // 打印警告信息
return; return; // 如果条件不满足,则退出方法
} }
try { try {
// 获取 JSON 对象中的 "note" 部分,包含任务的主要信息
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 获取 "data" 数组部分,包含任务的相关数据
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 验证任务类型是否为笔记类型
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) { if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {
Log.e(TAG, "invalid type"); Log.e(TAG, "invalid type"); // 记录错误信息
return; return; // 如果类型无效,则退出方法
} }
// 遍历 "data" 数组,查找 MIME 类型为 "note" 的数据
for (int i = 0; i < dataArray.length(); i++) { for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i); JSONObject data = dataArray.getJSONObject(i);
// 如果找到 MIME 类型为 NOTE 的数据项,提取内容并设置为任务名称
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) { if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
setName(data.getString(DataColumns.CONTENT)); setName(data.getString(DataColumns.CONTENT)); // 设置任务的名称
break; break; // 找到后退出循环
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
// 如果在 JSON 解析过程中遇到异常,记录错误并打印堆栈跟踪
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
} }
} }
/** /**
* JSON * JSON
* *
@ -289,20 +307,26 @@ public class Task extends Node {
/** /**
* *
* `MetaData` JSON
* *
* @param metaData * @param metaData `MetaData`
*/ */
public void setMetaInfo(MetaData metaData) { public void setMetaInfo(MetaData metaData) {
// 检查元数据对象是否非空,且包含有效的笔记内容
if (metaData != null && metaData.getNotes() != null) { if (metaData != null && metaData.getNotes() != null) {
try { try {
// 将元数据对象中的笔记内容转换为 JSON 对象并赋值给 `mMetaInfo`
mMetaInfo = new JSONObject(metaData.getNotes()); mMetaInfo = new JSONObject(metaData.getNotes());
} catch (JSONException e) { } catch (JSONException e) {
// 记录 JSON 解析异常信息
Log.w(TAG, e.toString()); Log.w(TAG, e.toString());
// 设置 `mMetaInfo` 为 null表明元信息未成功解析
mMetaInfo = null; mMetaInfo = null;
} }
} }
} }
/** /**
* *
* *

@ -53,79 +53,90 @@ public class TaskList extends Node {
} }
/** /**
* JSON * JSON
* JSON
* *
* @param actionId * @param actionId
* @return JSON * @return JSON
* @throws ActionFailureException JSON * @throws ActionFailureException JSON
*/ */
public JSONObject getCreateAction(int actionId) throws ActionFailureException { public JSONObject getCreateAction(int actionId) throws ActionFailureException {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// 设置动作类型为创建 // 将动作类型设置为 "创建"
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
// 设置动作标识符 // 设置当前动作标识符
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 设置索引 // 指定任务列表的索引位置
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// 设置实体变化信息 // 构建包含任务列表具体信息的实体 JSON 对象
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 任务列表名称
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); // 创建者 ID未指定时为 "null"
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP); GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 设置实体类型为任务组
// 将实体信息添加到主 JSON 对象中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) { } catch (JSONException e) {
// 捕获 JSON 异常,记录错误日志并抛出自定义异常
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
throw new ActionFailureException("fail to generate tasklist-create jsonobject"); throw new ActionFailureException("fail to generate tasklist-create jsonobject");
} }
// 返回构建的 JSON 对象
return js; return js;
} }
/** /**
* JSON * JSON
* JSON
* *
* @param actionId * @param actionId
* @return JSON * @return JSON
* @throws ActionFailureException JSON * @throws ActionFailureException JSON
*/ */
public JSONObject getUpdateAction(int actionId) throws ActionFailureException { public JSONObject getUpdateAction(int actionId) throws ActionFailureException {
// 创建一个新的 JSON 对象来存储更新操作的细节
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// 设置动作类型为更新 // 将动作类型设置为 "更新"
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// 设置动作标识符 // 设置当前动作标识符
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 设置任务列表ID // 指定需要更新的任务列表 ID
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// 设置实体变化信息 // 构建包含任务列表更新信息的实体 JSON 对象
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 设置任务列表名称
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); // 设置任务列表删除状态
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); // 添加实体信息到主 JSON 对象中
} catch (JSONException e) { } catch (JSONException e) {
// 捕获 JSON 异常,记录错误日志并抛出自定义异常
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
throw new ActionFailureException("fail to generate tasklist-update jsonobject"); throw new ActionFailureException("fail to generate tasklist-update jsonobject");
} }
// 返回构建的 JSON 对象
return js; return js;
} }
/** /**
* JSON * JSON
* *
@ -159,42 +170,49 @@ public class TaskList extends Node {
} }
/** /**
* JSON * JSON
* JSON
* *
* @param js JSON * @param js JSON
* @throws ActionFailureException JSON * @throws ActionFailureException JSON
*/ */
public void setContentByLocalJSON(JSONObject js) throws ActionFailureException { public void setContentByLocalJSON(JSONObject js) throws ActionFailureException {
// 检查 JSON 对象是否有效并包含必要的元数据
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); Log.w(TAG, "setContentByLocalJSON: nothing is available");
return; return;
} }
try { try {
// 从 JSON 对象中获取任务列表信息
JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 根据类型设置任务列表名称 // 根据任务列表类型设置名称
if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
// 如果类型为普通文件夹,从 JSON 中提取名称,并加上前缀
String name = folder.getString(NoteColumns.SNIPPET); String name = folder.getString(NoteColumns.SNIPPET);
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name);
} else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { } else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) // 如果类型为系统文件夹,根据文件夹 ID 设置默认名称
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) {
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT); setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT);
else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) } else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) {
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE);
+ GTaskStringUtils.FOLDER_CALL_NOTE); } else {
else Log.e(TAG, "invalid system folder"); // 无效的系统文件夹类型
Log.e(TAG, "invalid system folder"); }
} else { } else {
Log.e(TAG, "error type"); Log.e(TAG, "error type"); // 无效的任务类型
} }
} catch (JSONException e) { } catch (JSONException e) {
// 捕获 JSON 异常,记录错误日志并抛出自定义异常
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
throw new ActionFailureException("fail to set tasklist content from local json object"); throw new ActionFailureException("fail to set tasklist content from local json object");
} }
} }
/** /**
* JSON * JSON
* *
@ -230,43 +248,49 @@ public class TaskList extends Node {
/** /**
* *
*
* *
* @param c * @param c
* @return * @return
*/ */
public int getSyncAction(Cursor c) { public int getSyncAction(Cursor c) {
try { try {
// 检查是否有本地更新LOCAL_MODIFIED_COLUMN为0表示无本地更新
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
// 无本地更新 // 无本地更新的情况下比较同步IDSYNC_ID_COLUMN和最后修改时间
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// 双方均无更新 // 双方均无更新,返回无动作
return SYNC_ACTION_NONE; return SYNC_ACTION_NONE;
} else { } else {
// 应用远程更新到本地 // 若本地无更新但远程有更新,则应将远程更新应用到本地
return SYNC_ACTION_UPDATE_LOCAL; return SYNC_ACTION_UPDATE_LOCAL;
} }
} else { } else {
// 验证GTask ID是否匹配 // 如果本地有更新,则首先验证 GTask ID 是否匹配
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "gtask id doesn't match"); Log.e(TAG, "gtask id doesn't match"); // GTask ID 不匹配,返回同步错误
return SYNC_ACTION_ERROR; return SYNC_ACTION_ERROR;
} }
// 检查同步ID是否匹配最后修改时间以确定是否仅有本地修改
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// 仅本地有修改 // 若远程无修改,则仅将本地更新同步到远程
return SYNC_ACTION_UPDATE_REMOTE; return SYNC_ACTION_UPDATE_REMOTE;
} else { } else {
// 对于文件夹冲突,仅应用本地修改 // 若本地和远程均有修改(冲突),对于文件夹同步,优先应用本地修改
return SYNC_ACTION_UPDATE_REMOTE; return SYNC_ACTION_UPDATE_REMOTE;
} }
} }
} catch (Exception e) { } catch (Exception e) {
// 捕获异常并记录日志,返回同步错误
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
} }
return SYNC_ACTION_ERROR; return SYNC_ACTION_ERROR; // 发生异常或错误时,返回同步错误
} }
/** /**
* *
* *

@ -1,23 +1,23 @@
/* /*
* ActionFailureException * ActionFailureException
* *
* Throwable * RuntimeException
* * Throwable
*
* *
* : * :
*/ */
package net.micode.notes.gtask.exception; package net.micode.notes.gtask.exception;
// 引入 Java 运行时异常类 import java.lang.RuntimeException; // 引入 RuntimeException 类
import java.lang.RuntimeException;
/** /**
* ActionFailureException * ActionFailureException
*
*/ */
public class ActionFailureException extends RuntimeException { public class ActionFailureException extends RuntimeException {
private static final long serialVersionUID = 4425249765923293627L; // 序列化 ID private static final long serialVersionUID = 4425249765923293627L; // 序列化 ID,用于确保一致的类版本
/** /**
* *
@ -36,10 +36,11 @@ public class ActionFailureException extends RuntimeException {
} }
/** /**
* Throwable *
* Throwable
* *
* @param paramString * @param paramString
* @param paramThrowable Throwable * @param paramThrowable Throwable
*/ */
public ActionFailureException(String paramString, Throwable paramThrowable) { public ActionFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable); super(paramString, paramThrowable);

@ -1,26 +1,38 @@
/* /*
* NetworkFailureException * NetworkFailureException
* *
* Exception * Exception
* NetworkFailureException * NetworkFailureException
*/ */
package net.micode.notes.gtask.exception; package net.micode.notes.gtask.exception;
public class NetworkFailureException extends Exception { public class NetworkFailureException extends Exception {
private static final long serialVersionUID = 2107610287180234136L; private static final long serialVersionUID = 2107610287180234136L; // 序列化 ID
// 无参构造函数,用于创建一个不带详细信息的 NetworkFailureException 实例。 /**
* NetworkFailureException
*/
public NetworkFailureException() { public NetworkFailureException() {
super(); super();
} }
// 带有详细信息的构造函数,用于创建一个包含错误信息的 NetworkFailureException 实例。 /**
* NetworkFailureException
*
* @param paramString
*/
public NetworkFailureException(String paramString) { public NetworkFailureException(String paramString) {
super(paramString); super(paramString);
} }
// 带有详细信息和导致异常的 Throwable 对象的构造函数,用于创建包含错误信息和原因的 NetworkFailureException 实例。 /**
*
* Throwable NetworkFailureException
*
* @param paramString
* @param paramThrowable Throwable
*/
public NetworkFailureException(String paramString, Throwable paramThrowable) { public NetworkFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable); super(paramString, paramThrowable);
} }

@ -1,8 +1,9 @@
/* /*
* GTaskASyncTask : * GTaskASyncTask :
* AsyncTaskGoogle线 * AsyncTask Google 线
* *
*/ */
package net.micode.notes.gtask.remote; package net.micode.notes.gtask.remote;
import android.app.Notification; import android.app.Notification;
@ -16,21 +17,20 @@ import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity; import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity; import net.micode.notes.ui.NotesPreferenceActivity;
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> { public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
// 同步通知的唯一ID // 同步通知的唯一 ID
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
// 定义完成监听器接口 // 定义同步完成监听器接口
public interface OnCompleteListener { public interface OnCompleteListener {
void onComplete(); void onComplete();
} }
private Context mContext; // 上下文对象,用于访问应用资源和通知管理器 private Context mContext; // 上下文对象,用于访问应用资源和通知管理器
private NotificationManager mNotifiManager; // 通知管理器 private NotificationManager mNotifiManager; // 通知管理器,用于管理通知的显示和隐藏
private GTaskManager mTaskManager; // Google任务管理器,用于执行实际的同步操作 private GTaskManager mTaskManager; // Google 任务管理器,用于实际执行同步操作
private OnCompleteListener mOnCompleteListener; // 同步完成监听器 private OnCompleteListener mOnCompleteListener; // 同步完成监听器
/* /*
* *
@ -40,8 +40,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
public GTaskASyncTask(Context context, OnCompleteListener listener) { public GTaskASyncTask(Context context, OnCompleteListener listener) {
mContext = context; mContext = context;
mOnCompleteListener = listener; mOnCompleteListener = listener;
mNotifiManager = (NotificationManager) mContext mNotifiManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
.getSystemService(Context.NOTIFICATION_SERVICE);
mTaskManager = GTaskManager.getInstance(); mTaskManager = GTaskManager.getInstance();
} }
@ -52,29 +51,24 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
// 发布进度更新的方法 // 发布进度更新的方法
public void publishProgess(String message) { public void publishProgess(String message) {
publishProgress(new String[]{ publishProgress(new String[]{message});
message
});
} }
/* /*
* *
* @param tickerId TickerID * @param tickerId Ticker ID
* @param content * @param content
*/ */
private void showNotification(int tickerId, String content) { private void showNotification(int tickerId, String content) {
PendingIntent pendingIntent; PendingIntent pendingIntent;
// 根据不同的通知状态设置不同的Intent // 根据通知状态,设置点击通知时打开的 Activity
if (tickerId != R.string.ticker_success) { if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, NotesPreferenceActivity.class), 0);
NotesPreferenceActivity.class), 0);
} else { } else {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, NotesListActivity.class), 0);
NotesListActivity.class), 0);
} }
// 构建通知并显示 // 构建通知对象
Notification.Builder builder = new Notification.Builder(mContext) Notification.Builder builder = new Notification.Builder(mContext)
.setAutoCancel(true) .setAutoCancel(true)
.setContentTitle(mContext.getString(R.string.app_name)) .setContentTitle(mContext.getString(R.string.app_name))
@ -83,7 +77,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
.setWhen(System.currentTimeMillis()) .setWhen(System.currentTimeMillis())
.setOngoing(true); .setOngoing(true);
Notification notification = builder.getNotification(); Notification notification = builder.getNotification();
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); // 显示通知
} }
/* /*
@ -92,21 +86,20 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
*/ */
@Override @Override
protected Integer doInBackground(Void... unused) { protected Integer doInBackground(Void... unused) {
// 开始同步时的进度更新 // 登录并开始同步,显示进度
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity.getSyncAccountName(mContext)));
.getSyncAccountName(mContext))); return mTaskManager.sync(mContext, this); // 调用 GTaskManager 开始同步
return mTaskManager.sync(mContext, this);
} }
/* /*
* publishProgress * publishProgress
* @param progress * @param progress
*/ */
@Override @Override
protected void onProgressUpdate(String... progress) { protected void onProgressUpdate(String... progress) {
// 显示当前同步进度 // 显示当前同步进度
showNotification(R.string.ticker_syncing, progress[0]); showNotification(R.string.ticker_syncing, progress[0]);
// 如果上下文是一个GTaskSyncService实例,发送广播更新进度 // 如果上下文是 GTaskSyncService 实例,发送广播更新进度
if (mContext instanceof GTaskSyncService) { if (mContext instanceof GTaskSyncService) {
((GTaskSyncService) mContext).sendBroadcast(progress[0]); ((GTaskSyncService) mContext).sendBroadcast(progress[0]);
} }
@ -118,23 +111,20 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
*/ */
@Override @Override
protected void onPostExecute(Integer result) { protected void onPostExecute(Integer result) {
// 根据不同的状态显示不同的通知 // 根据状态显示不同的通知
if (result == GTaskManager.STATE_SUCCESS) { if (result == GTaskManager.STATE_SUCCESS) {
showNotification(R.string.ticker_success, mContext.getString( showNotification(R.string.ticker_success, mContext.getString(R.string.success_sync_account, mTaskManager.getSyncAccount()));
R.string.success_sync_account, mTaskManager.getSyncAccount()));
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis()); NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis());
} else if (result == GTaskManager.STATE_NETWORK_ERROR) { } else if (result == GTaskManager.STATE_NETWORK_ERROR) {
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network)); showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network));
} else if (result == GTaskManager.STATE_INTERNAL_ERROR) { } else if (result == GTaskManager.STATE_INTERNAL_ERROR) {
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal)); showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal));
} else if (result == GTaskManager.STATE_SYNC_CANCELLED) { } else if (result == GTaskManager.STATE_SYNC_CANCELLED) {
showNotification(R.string.ticker_cancel, mContext showNotification(R.string.ticker_cancel, mContext.getString(R.string.error_sync_cancelled));
.getString(R.string.error_sync_cancelled));
} }
// 如果设置了完成监听器,则在一个新线程中调用其onComplete方法 // 如果设置了完成监听器,异步调用 onComplete 方法
if (mOnCompleteListener != null) { if (mOnCompleteListener != null) {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
mOnCompleteListener.onComplete(); mOnCompleteListener.onComplete();
} }

@ -151,32 +151,51 @@ public class Note {
* @param noteId ID * @param noteId ID
* @return truefalse * @return truefalse
*/ */
/**
*
*
* @param context 访
* @param noteId IDID
* @return true false
* @throws IllegalArgumentException noteId 0
*/
public boolean syncNote(Context context, long noteId) { public boolean syncNote(Context context, long noteId) {
// 检查 noteId 的有效性,如果 noteId 不合法则抛出异常
if (noteId <= 0) { if (noteId <= 0) {
throw new IllegalArgumentException("错误的笔记ID:" + noteId); throw new IllegalArgumentException("错误的笔记ID:" + noteId);
} }
// 如果笔记没有被本地修改,则无需同步,直接返回 true 表示同步成功
if (!isLocalModified()) { if (!isLocalModified()) {
return true; return true;
} }
// 理论上,一旦数据改变,笔记应该在本地修改标记和修改日期上更新。为了数据安全,即使更新笔记失败,我们也更新笔记的数据信息 // 如果本地内容有改动,尝试将笔记属性更新到数据库
// 使用 noteId 来定位到具体的笔记条目
// 调用 ContentResolver.update 方法,传入更新的数据
if (context.getContentResolver().update( if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) { null) == 0) {
// 若更新失败,记录日志以提示意外情况
Log.e(TAG, "更新笔记错误,不应该发生"); Log.e(TAG, "更新笔记错误,不应该发生");
// 不返回,继续执行 // 即使更新笔记失败,也继续执行,确保数据清理
} }
// 清除记录的属性差异值,因为已经提交到数据库
mNoteDiffValues.clear(); mNoteDiffValues.clear();
// 如果笔记的 NoteData 内容存在本地修改
// 调用 pushIntoContentResolver 将其推送到数据库
// 如果推送失败(返回 null则同步失败返回 false
if (mNoteData.isLocalModified() if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) { && (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false; return false;
} }
// 所有更改成功推送到数据库,返回 true 表示同步成功
return true; return true;
} }
/** /**
* NoteData * NoteData
*/ */
@ -224,25 +243,41 @@ public class Note {
* *
* @param id ID * @param id ID
*/ */
/**
*
*
*
* @param id ID
* @throws IllegalArgumentException id 0 ID
*/
void setCallDataId(long id) { void setCallDataId(long id) {
// 检查参数 id 的有效性。ID 必须为正整数,否则抛出非法参数异常
if (id <= 0) { if (id <= 0) {
throw new IllegalArgumentException("通话数据ID应该大于0"); throw new IllegalArgumentException("通话数据ID应该大于0");
} }
// 设置通话数据的唯一标识符
mCallDataId = id; mCallDataId = id;
} }
/** /**
* *
* `mCallDataValues`
* 便
* *
* @param key * @param key `ContentValues`
* @param value * @param value
*/ */
void setCallData(String key, String value) { void setCallData(String key, String value) {
// 在通话数据的ContentValues中插入或更新指定的键值对
mCallDataValues.put(key, value); mCallDataValues.put(key, value);
// 标记笔记已被本地修改,并设置最新的修改时间
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
} }
/** /**
* *
* *

@ -119,47 +119,52 @@ public class WorkingNote {
private static final int NOTE_MODIFIED_DATE_COLUMN = 5; private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
/** /**
* * `WorkingNote` ID
* ID
* *
* @param context 访 * @param context 访
* @param folderId ID * @param folderId ID
*/ */
private WorkingNote(Context context, long folderId) { private WorkingNote(Context context, long folderId) {
mContext = context; mContext = context; // 存储上下文以便后续使用系统资源和服务
mAlertDate = 0; mAlertDate = 0; // 默认提醒时间为0即没有提醒
mModifiedDate = System.currentTimeMillis(); mModifiedDate = System.currentTimeMillis(); // 设置笔记的创建时间为当前时间
mFolderId = folderId; mFolderId = folderId; // 记录该笔记所属的文件夹ID
mNote = new Note(); mNote = new Note(); // 创建一个新的 Note 实例,用于存储笔记内容
mNoteId = 0; mNoteId = 0; // 初始化笔记ID为0表示该笔记尚未保存到数据库
mIsDeleted = false; mIsDeleted = false; // 标记该笔记当前没有被删除
mMode = 0; mMode = 0; // 设置默认模式为0具体模式含义可根据需求定义
mWidgetType = Notes.TYPE_WIDGET_INVALIDE; mWidgetType = Notes.TYPE_WIDGET_INVALIDE; // 设置小部件类型为无效,初始状态不绑定小部件
} }
/** /**
* * `WorkingNote`
* 使 `noteId`
* *
* @param context 访 * @param context 访
* @param noteId ID * @param noteId
* @param folderId ID * @param folderId ID
*/ */
private WorkingNote(Context context, long noteId, long folderId) { private WorkingNote(Context context, long noteId, long folderId) {
mContext = context; mContext = context; // 赋值上下文对象,用于后续系统资源和服务访问
mNoteId = noteId; mNoteId = noteId; // 初始化笔记ID以便加载对应的笔记内容
mFolderId = folderId; mFolderId = folderId; // 设置笔记所属的文件夹ID表示其归属
mIsDeleted = false; mIsDeleted = false; // 初始化删除标记为 false表示该笔记未被删除
mNote = new Note(); mNote = new Note(); // 创建一个新的 Note 实例,用于存储笔记内容
loadNote(); loadNote(); // 调用 loadNote 方法从数据库加载该笔记的内容和属性
} }
/** /**
* *
* ID * ID
* *
* ID
*/ */
private void loadNote() { private void loadNote() {
// 查询指定ID的笔记信息 // 使用内容提供者查询数据库,获取与指定笔记ID匹配的笔记信息
Cursor cursor = mContext.getContentResolver().query( Cursor cursor = mContext.getContentResolver().query(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null,
null, null); null, null);
@ -167,25 +172,26 @@ public class WorkingNote {
if (cursor != null) { if (cursor != null) {
// 如果查询结果不为空,尝试读取数据 // 如果查询结果不为空,尝试读取数据
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
// 从查询结果中获取笔记的各个属性 // 从查询结果中获取笔记的各个属性值,并更新当前实例的状态
mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); // 获取并设置笔记所属文件夹ID
mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); // 获取并设置笔记背景颜色ID
mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); // 获取并设置关联的小部件ID
mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); // 获取并设置小部件的类型
mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); // 获取并设置笔记的提醒时间
mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); // 获取并设置笔记的上次修改时间
} }
// 关闭查询结果集 // 关闭查询游标以释放资源
cursor.close(); cursor.close();
} else { } else {
// 如果查询结果为空,记录错误并抛出异常 // 查询失败,未找到匹配的笔记,记录错误日志并抛出异常
Log.e(TAG, "No note with id:" + mNoteId); Log.e(TAG, "No note with id:" + mNoteId);
throw new IllegalArgumentException("Unable to find note with id " + mNoteId); throw new IllegalArgumentException("Unable to find note with id " + mNoteId);
} }
// 加载笔记的附加数据,如内容、设置等 // 加载笔记的附加数据,例如内容和设置
loadNoteData(); loadNoteData();
} }
/** /**
* *
* ID * ID
@ -229,23 +235,34 @@ public class WorkingNote {
/** /**
* *
* ID
* *
* @param context 访 * @param context 访
* @param folderId ID * @param folderId ID
* @param widgetId ID * @param widgetId ID
* @param widgetType * @param widgetType
* @param defaultBgColorId ID * @param defaultBgColorId ID
* @return * @return
*/ */
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
int widgetType, int defaultBgColorId) { int widgetType, int defaultBgColorId) {
// 创建一个新的 WorkingNote 实例指定所属文件夹ID
WorkingNote note = new WorkingNote(context, folderId); WorkingNote note = new WorkingNote(context, folderId);
// 设置笔记的默认背景颜色
note.setBgColorId(defaultBgColorId); note.setBgColorId(defaultBgColorId);
// 设置与笔记关联的小部件ID
note.setWidgetId(widgetId); note.setWidgetId(widgetId);
// 设置与笔记关联的小部件类型
note.setWidgetType(widgetType); note.setWidgetType(widgetType);
// 返回初始化好的空笔记对象
return note; return note;
} }
/** /**
* ID * ID
* *
@ -259,38 +276,42 @@ public class WorkingNote {
/** /**
* *
* *
* *
* *
* @return truefalse * @return true false
*/ */
public synchronized boolean saveNote() { public synchronized boolean saveNote() {
// 判断是否值得保存该笔记 // 检查该笔记是否符合保存条件(即内容有意义且未被删除)
if (isWorthSaving()) { if (isWorthSaving()) {
// 检查数据库中是否已存在该笔记 // 检查笔记是否已存在于数据库中
if (!existInDatabase()) { if (!existInDatabase()) {
// 为笔记生成新的ID // 如果笔记不在数据库中,笔记生成一个新的ID
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
// 若生成新ID失败记录日志并返回 false 表示保存失败
Log.e(TAG, "Create new note fail with id:" + mNoteId); Log.e(TAG, "Create new note fail with id:" + mNoteId);
return false; return false;
} }
} }
mNote.syncNote(mContext, mNoteId); // 同步笔记到数据库 // 将当前笔记内容同步到数据库
mNote.syncNote(mContext, mNoteId);
// 如果存在对应的小部件,更新小部件内容 // 如果笔记关联了小部件,更新小部件的显示内容
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mWidgetType != Notes.TYPE_WIDGET_INVALIDE
&& mNoteSettingStatusListener != null) { && mNoteSettingStatusListener != null) {
// 通过监听器通知小部件已更新
mNoteSettingStatusListener.onWidgetChanged(); mNoteSettingStatusListener.onWidgetChanged();
} }
return true; return true; // 保存成功,返回 true
} else { } else {
return false; return false; // 笔记内容无意义,不进行保存,返回 false
} }
} }
/** /**
* *
* *
@ -301,21 +322,26 @@ public class WorkingNote {
} }
/** /**
* *
* *
* 1.
* 2.
* 3.
* *
* @return truefalse * @return true false
*/ */
private boolean isWorthSaving() { private boolean isWorthSaving() {
// 判断笔记是否值得保存 // 检查三种情况下笔记不值得保存的条件
if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) if (mIsDeleted || // 情况 1笔记已被标记为删除
|| (existInDatabase() && !mNote.isLocalModified())) { (!existInDatabase() && TextUtils.isEmpty(mContent)) || // 情况 2笔记不存在且内容为空
return false; (existInDatabase() && !mNote.isLocalModified())) { // 情况 3笔记已存在且没有本地修改
return false; // 不值得保存,返回 false
} else { } else {
return true; return true; // 符合保存条件,返回 true
} }
} }
/** /**
* *
* *
@ -328,20 +354,24 @@ public class WorkingNote {
/** /**
* *
* *
* @param date * @param date
* @param set * @param set true false
*/ */
public void setAlertDate(long date, boolean set) { public void setAlertDate(long date, boolean set) {
// 更新提醒日期并触发监听器 // 如果提醒日期发生更改,则更新提醒日期并记录到笔记对象中
if (date != mAlertDate) { if (date != mAlertDate) {
mAlertDate = date; mAlertDate = date;
// 更新笔记对象的提醒日期字段
mNote.setNoteValue(NoteColumns.ALERTED_DATE, String.valueOf(mAlertDate)); mNote.setNoteValue(NoteColumns.ALERTED_DATE, String.valueOf(mAlertDate));
} }
// 如果已设置提醒状态监听器,则触发监听器的提醒更改事件
if (mNoteSettingStatusListener != null) { if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onClockAlertChanged(date, set); mNoteSettingStatusListener.onClockAlertChanged(date, set);
} }
} }
/** /**
* *
* *
@ -362,17 +392,23 @@ public class WorkingNote {
* @param id ID * @param id ID
*/ */
public void setBgColorId(int id) { public void setBgColorId(int id) {
// 更新背景颜色ID并触发监听器 // 检查新颜色ID是否不同于当前ID避免重复操作
if (id != mBgColorId) { if (id != mBgColorId) {
// 更新笔记的背景颜色ID
mBgColorId = id; mBgColorId = id;
// 如果设置了笔记状态监听器,则通知监听器背景颜色已更改
if (mNoteSettingStatusListener != null) { if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onBackgroundColorChanged(); mNoteSettingStatusListener.onBackgroundColorChanged();
} }
// 在笔记对象中保存新的背景颜色ID
mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id));
} }
} }
/** /**
* *
* *
@ -409,13 +445,17 @@ public class WorkingNote {
* @param id ID * @param id ID
*/ */
public void setWidgetId(int id) { public void setWidgetId(int id) {
// 检查新传入的小部件ID是否不同于当前的小部件ID避免重复操作
if (id != mWidgetId) { if (id != mWidgetId) {
// 更新小部件ID属性
mWidgetId = id; mWidgetId = id;
// 更新笔记中小部件ID的值
// 在笔记对象中更新小部件ID的值以同步到数据库
mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId));
} }
} }
/** /**
* *
* *
@ -436,12 +476,17 @@ public class WorkingNote {
* @param callDate * @param callDate
*/ */
public void convertToCallNote(String phoneNumber, long callDate) { public void convertToCallNote(String phoneNumber, long callDate) {
// 设置通话日期和电话号码,并关联至通话记录文件夹 // 将通话日期设置为笔记的通话数据
mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate));
// 将电话号码设置为笔记的通话数据
mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber);
// 将笔记的父文件夹ID设置为通话记录文件夹使其分类为通话记录
mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER));
} }
/** /**
* *
* *

Loading…
Cancel
Save