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

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

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

@ -1,39 +1,38 @@
/**
* MetaDataTask
* MetaDataTaskID
* JSON
*/
package net.micode.notes.gtask.data;
import android.database.Cursor;
import android.util.Log;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
public class MetaData extends Task {
private final static String TAG = MetaData.class.getSimpleName(); // 日志标签
private String mRelatedGid = null; // 与任务相关的全局ID
/**
*
* ID
*
* @param gid ID
* @param metaInfo JSON
*/
public void setMeta(String gid, JSONObject metaInfo) {
try {
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); // 将任务的全局ID添加到元信息中
// 在元信息中添加任务的全局ID
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
} catch (JSONException e) {
Log.e(TAG, "failed to put related gid");
Log.e(TAG, "无法添加相关的全局ID");
}
setNotes(metaInfo.toString()); // 将元信息设置为任务的笔记
setName(GTaskStringUtils.META_NOTE_NAME); // 设置任务的名称为特定的元数据标志名称
setNotes(metaInfo.toString()); // 将完整的元信息转换为字符串后存储为任务的笔记
setName(GTaskStringUtils.META_NOTE_NAME); // 将任务名称设置为特定的元数据名称
}
/**
* ID
* ID
*
* @return ID
*/
@ -44,7 +43,7 @@ public class MetaData extends Task {
/**
*
*
* @return true
* @return true
*/
@Override
public boolean isWorthSaving() {
@ -52,54 +51,58 @@ public class MetaData extends Task {
}
/**
* JSON
* JSON
* JSONID
*
* @param js JSON
* @param js JSON
*/
@Override
public void setContentByRemoteJSON(JSONObject js) {
super.setContentByRemoteJSON(js);
super.setContentByRemoteJSON(js); // 调用父类方法设置通用内容
if (getNotes() != null) {
try {
// 从笔记中提取任务相关的全局ID
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) {
Log.w(TAG, "failed to get related gid");
mRelatedGid = null; // 提取失败时设置相关ID为null
Log.w(TAG, "获取相关全局ID失败");
mRelatedGid = null; // 若解析失败相关ID设为null
}
}
}
/**
* JSON
* JSON
*
* @param js JSON
*/
@Override
public void setContentByLocalJSON(JSONObject js) {
// this function should not be called
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
// 此方法不适用于MetaData类直接抛出异常
throw new IllegalAccessError("MetaData:setContentByLocalJSON 不应被调用");
}
/**
* JSON
* JSON
*
* @return JSON
*/
@Override
public JSONObject getLocalJSONFromContent() {
throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called");
// 此方法不适用于MetaData类直接抛出异常
throw new IllegalAccessError("MetaData:getLocalJSONFromContent 不应被调用");
}
/**
*
*
*
* @param c
* @return
*/
@Override
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;
import android.database.Cursor;
import org.json.JSONObject;
// 定义节点同步动作的常量
// 定义节点同步动作的常量,用于区分节点的不同同步操作类型
public abstract class Node {
public static final int SYNC_ACTION_NONE = 0; // 无动作
public static final int SYNC_ACTION_ADD_REMOTE = 1; // 添加远程节点
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_LOCAL = 4; // 删除本地节点
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_CONFLICT = 7; // 更新冲突
public static final int SYNC_ACTION_ERROR = 8; // 同步错误
private String mGid; // 全局唯一标识符
private String mName; // 节点名称
private long mLastModified; // 最后修改时间
private boolean mDeleted; // 节点是否被删除的标志
// 构造函数,初始化节点属性
public static final int SYNC_ACTION_NONE = 0; // 无同步动作
public static final int SYNC_ACTION_ADD_REMOTE = 1; // 添加远程节点
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_LOCAL = 4; // 删除本地节点
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_CONFLICT = 7; // 同步冲突更新
public static final int SYNC_ACTION_ERROR = 8; // 同步错误
private String mGid; // 全局唯一标识符
private String mName; // 节点名称
private long mLastModified; // 最后修改时间
private boolean mDeleted; // 节点是否被删除的标志
// 构造函数,初始化节点的默认属性
public Node() {
mGid = null;
mName = "";
@ -34,22 +33,22 @@ public abstract class Node {
mDeleted = false;
}
// 生成创建节点的JSON动作
// 抽象方法由子类实现生成创建节点的JSON表示
public abstract JSONObject getCreateAction(int actionId);
// 生成更新节点的JSON动作
// 抽象方法由子类实现生成更新节点的JSON表示
public abstract JSONObject getUpdateAction(int actionId);
// 根据远程JSON内容设置节点内容
// 抽象方法由子类实现设置节点内容为远程JSON内容
public abstract void setContentByRemoteJSON(JSONObject js);
// 根据本地JSON内容设置节点内容
// 抽象方法由子类实现设置节点内容为本地JSON内容
public abstract void setContentByLocalJSON(JSONObject js);
// 从内容生成本地JSON表示
// 抽象方法由子类实现从节点内容生成本地JSON对象
public abstract JSONObject getLocalJSONFromContent();
// 根据Cursor获取同步动作
// 抽象方法,由子类实现,根据Cursor对象获取节点的同步动作
public abstract int getSyncAction(Cursor c);
// 设置节点的全局唯一标识符
@ -57,17 +56,17 @@ public abstract class Node {
this.mGid = gid;
}
// 设置节点名称
// 设置节点名称
public void setName(String name) {
this.mName = name;
}
// 设置节点最后修改时间
// 设置节点最后修改时间
public void setLastModified(long lastModified) {
this.mLastModified = lastModified;
}
// 设置节点是否被删除
// 设置节点的删除状态
public void setDeleted(boolean deleted) {
this.mDeleted = deleted;
}
@ -77,19 +76,18 @@ public abstract class Node {
return this.mGid;
}
// 获取节点名称
// 获取节点名称
public String getName() {
return this.mName;
}
// 获取节点最后修改时间
// 获取节点最后修改时间
public long getLastModified() {
return this.mLastModified;
}
// 获取节点是否被删除的标志
// 获取节点的删除状态
public boolean getDeleted() {
return this.mDeleted;
}
}

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

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

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

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

@ -1,23 +1,23 @@
/*
* ActionFailureException
*
* Throwable
*
* RuntimeException
* Throwable
*
*
* :
* :
*/
package net.micode.notes.gtask.exception;
// 引入 Java 运行时异常类
import java.lang.RuntimeException;
import java.lang.RuntimeException; // 引入 RuntimeException 类
/**
* ActionFailureException
* ActionFailureException
*
*/
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 paramThrowable Throwable
* @param paramThrowable Throwable
*/
public ActionFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable);

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

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

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

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

Loading…
Cancel
Save