付佳代码精读

master
Jia 1 year ago
parent c607dfa504
commit 653753a7bd

@ -26,57 +26,109 @@ 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();
// 相关GID的字符串变量初始化为null
private String mRelatedGid = null; private String mRelatedGid = null;
/**
*
*
* @param gid GID
* @param metaInfo JSONObject
*/
public void setMeta(String gid, JSONObject metaInfo) { public void setMeta(String gid, JSONObject metaInfo) {
try { try {
// 将GID放入metaInfo中键为GTaskStringUtils.META_HEAD_GTASK_ID
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
} catch (JSONException e) { } catch (JSONException e) {
// 如果放入GID失败输出错误日志
Log.e(TAG, "failed to put related gid"); Log.e(TAG, "failed to put related gid");
} }
// 将metaInfo转换为字符串并设置为便签的备注
setNotes(metaInfo.toString()); setNotes(metaInfo.toString());
// 设置便签的名称为预定义的元数据名称
setName(GTaskStringUtils.META_NOTE_NAME); setName(GTaskStringUtils.META_NOTE_NAME);
} }
/**
* GID
*
* @return GIDnull
*/
public String getRelatedGid() { public String getRelatedGid() {
return mRelatedGid; return mRelatedGid;
} }
/**
* 便
*
* @return 便truefalse
*/
@Override @Override
public boolean isWorthSaving() { public boolean isWorthSaving() {
return getNotes() != null; return getNotes() != null;
} }
/**
* JSON便
*
* @param js 便JSONObject
*/
@Override @Override
public void setContentByRemoteJSON(JSONObject js) { public void setContentByRemoteJSON(JSONObject js) {
// 调用父类的方法处理JSON对象
super.setContentByRemoteJSON(js); super.setContentByRemoteJSON(js);
// 如果便签有备注
if (getNotes() != null) { if (getNotes() != null) {
try { try {
// 将备注转换为JSONObject对象
JSONObject metaInfo = new JSONObject(getNotes().trim()); JSONObject metaInfo = new JSONObject(getNotes().trim());
// 从metaInfo中获取相关GID
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
} catch (JSONException e) { } catch (JSONException e) {
// 如果获取GID失败输出警告日志并将相关GID设置为null
Log.w(TAG, "failed to get related gid"); Log.w(TAG, "failed to get related gid");
mRelatedGid = null; mRelatedGid = null;
} }
} }
} }
/**
* JSON便
*
* @param js 便JSONObject
* @throws IllegalAccessError
*/
@Override @Override
public void setContentByLocalJSON(JSONObject js) { public void setContentByLocalJSON(JSONObject js) {
// this function should not be called // 抛出错误,因为此方法不应被调用
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
} }
/**
* 便JSON
*
* @return
* @throws IllegalAccessError
*/
@Override @Override
public JSONObject getLocalJSONFromContent() { public JSONObject getLocalJSONFromContent() {
// 抛出错误,因为此方法不应被调用
throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called");
} }
/**
*
*
* @param c
* @return
* @throws IllegalAccessError
*/
@Override @Override
public int getSyncAction(Cursor c) { public int getSyncAction(Cursor c) {
// 抛出错误,因为此方法不应被调用
throw new IllegalAccessError("MetaData:getSyncAction should not be called"); throw new IllegalAccessError("MetaData:getSyncAction should not be called");
} }
} }

@ -21,79 +21,108 @@ 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_LOCAL = 4; // 本地删除
public static final int SYNC_ACTION_DEL_REMOTE = 3; public static final int SYNC_ACTION_UPDATE_REMOTE = 5; // 远程更新
public static final int SYNC_ACTION_UPDATE_LOCAL = 6; // 本地更新
public static final int SYNC_ACTION_DEL_LOCAL = 4; public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; // 更新冲突
public static final int SYNC_ACTION_ERROR = 8; // 同步错误
public static final int SYNC_ACTION_UPDATE_REMOTE = 5;
// 节点的GID全局唯一标识符
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 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; // GID初始化为null
mName = ""; mName = ""; // 名称初始化为空字符串
mLastModified = 0; mLastModified = 0; // 最后修改时间初始化为0
mDeleted = false; mDeleted = false; // 删除标记初始化为false
} }
// 抽象方法获取创建动作的JSON对象
// @param actionId 同步动作的ID
// @return 包含创建动作的JSON对象
public abstract JSONObject getCreateAction(int actionId); public abstract JSONObject getCreateAction(int actionId);
// 抽象方法获取更新动作的JSON对象
// @param actionId 同步动作的ID
// @return 包含更新动作的JSON对象
public abstract JSONObject getUpdateAction(int actionId); public abstract JSONObject getUpdateAction(int actionId);
// 抽象方法通过远程JSON对象设置节点内容
// @param js 包含节点内容的JSON对象
public abstract void setContentByRemoteJSON(JSONObject js); public abstract void setContentByRemoteJSON(JSONObject js);
// 抽象方法通过本地JSON对象设置节点内容
// @param js 包含节点内容的JSON对象
public abstract void setContentByLocalJSON(JSONObject js); public abstract void setContentByLocalJSON(JSONObject js);
// 抽象方法从节点内容获取本地JSON对象
// @return 包含节点内容的本地JSON对象
public abstract JSONObject getLocalJSONFromContent(); public abstract JSONObject getLocalJSONFromContent();
// 抽象方法,获取同步动作
// @param c 数据库游标,用于获取节点的同步状态
// @return 同步动作的ID
public abstract int getSyncAction(Cursor c); public abstract int getSyncAction(Cursor c);
// 设置节点的GID
// @param gid 要设置的GID
public void setGid(String gid) { public void setGid(String gid) {
this.mGid = gid; this.mGid = gid;
} }
// 设置节点的名称
// @param name 要设置的名称
public void setName(String name) { public void setName(String name) {
this.mName = name; this.mName = name;
} }
// 设置节点的最后修改时间
// @param lastModified 要设置的最后修改时间
public void setLastModified(long lastModified) { public void setLastModified(long lastModified) {
this.mLastModified = lastModified; this.mLastModified = lastModified;
} }
// 设置节点的删除标记
// @param deleted 要设置的删除标记
public void setDeleted(boolean deleted) { public void setDeleted(boolean deleted) {
this.mDeleted = deleted; this.mDeleted = deleted;
} }
// 获取节点的GID
// @return 节点的GID
public String getGid() { public String getGid() {
return this.mGid; return this.mGid;
} }
// 获取节点的名称
// @return 节点的名称
public String getName() { public String getName() {
return this.mName; return this.mName;
} }
// 获取节点的最后修改时间
// @return 节点的最后修改时间
public long getLastModified() { public long getLastModified() {
return this.mLastModified; return this.mLastModified;
} }
// 获取节点的删除标记
// @return 节点的删除标记
public boolean getDeleted() { public boolean getDeleted() {
return this.mDeleted; return this.mDeleted;
} }

@ -31,41 +31,44 @@ import java.util.ArrayList;
public class TaskList extends Node { public class TaskList extends Node {
private static final String TAG = TaskList.class.getSimpleName(); private static final String TAG = TaskList.class.getSimpleName(); // 获取当前类的简单名称作为日志标签
private int mIndex; private int mIndex; // 任务列表的索引
private ArrayList<Task> mChildren; private ArrayList<Task> mChildren; // 存储子任务的列表
// 构造方法,初始化任务列表和索引
public TaskList() { public TaskList() {
super(); super();
mChildren = new ArrayList<Task>(); mChildren = new ArrayList<Task>();
mIndex = 1; mIndex = 1;
} }
// 生成创建任务的JSON对象
public JSONObject getCreateAction(int actionId) { public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// action_type // 设置动作类型为创建
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);
// action_id // 设置动作ID
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// index // 设置索引
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// entity_delta // 设置实体变化信息
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这里为空
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP); GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 实体类型为组
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");
@ -74,27 +77,29 @@ public class TaskList extends Node {
return js; return js;
} }
// 生成更新任务的JSON对象
public JSONObject getUpdateAction(int actionId) { public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// action_type // 设置动作类型为更新
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);
// action_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());
// entity_delta // 设置实体变化信息
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);
} 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");
@ -103,25 +108,27 @@ public class TaskList extends Node {
return js; return js;
} }
// 根据远程JSON对象设置任务列表内容
public void setContentByRemoteJSON(JSONObject js) { public void setContentByRemoteJSON(JSONObject js) {
if (js != null) { if (js != null) {
try { try {
// id // 设置任务列表ID
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
} }
// last_modified // 设置最后修改时间
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
} }
// name // 设置任务列表名称
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
} }
} 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 get tasklist content from jsonobject"); throw new ActionFailureException("fail to get tasklist content from jsonobject");
@ -129,14 +136,16 @@ public class TaskList extends Node {
} }
} }
// 根据本地JSON对象设置任务列表内容
public void setContentByLocalJSON(JSONObject js) { public void setContentByLocalJSON(JSONObject js) {
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 avaiable"); // 本地JSON对象无效或没有头部信息
} }
try { try {
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) {
String name = folder.getString(NoteColumns.SNIPPET); String name = folder.getString(NoteColumns.SNIPPET);
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name);
@ -147,16 +156,18 @@ public class TaskList extends Node {
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();
} }
} }
// 获取任务列表的本地JSON对象
public JSONObject getLocalJSONFromContent() { public JSONObject getLocalJSONFromContent() {
try { try {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
@ -167,6 +178,7 @@ public class TaskList extends Node {
folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(), folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(),
folderName.length()); folderName.length());
folder.put(NoteColumns.SNIPPET, folderName); folder.put(NoteColumns.SNIPPET, folderName);
// 根据文件夹名称设置文件夹类型
if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT) if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT)
|| folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE)) || folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE))
folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
@ -177,38 +189,41 @@ public class TaskList extends Node {
return js; return js;
} catch (JSONException e) { } catch (JSONException e) {
// 捕获JSON异常打印错误日志并返回null
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} }
// 获取同步动作(根据游标数据判断)
public int getSyncAction(Cursor c) { public int getSyncAction(Cursor c) {
try { try {
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
// there is no local update // 本地没有更新
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// no update both side // 远程和本地都没有更新
return SYNC_ACTION_NONE; return SYNC_ACTION_NONE;
} else { } else {
// apply remote to local // 应用远程更新到本地
return SYNC_ACTION_UPDATE_LOCAL; return SYNC_ACTION_UPDATE_LOCAL;
} }
} else { } else {
// validate gtask id // 验证任务列表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"); // 任务列表ID不匹配
return SYNC_ACTION_ERROR; return SYNC_ACTION_ERROR;
} }
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// local modification only // 只有本地更新
return SYNC_ACTION_UPDATE_REMOTE; return SYNC_ACTION_UPDATE_REMOTE;
} else { } else {
// for folder conflicts, just apply local modification // 文件夹冲突,只应用本地更新
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();
} }
@ -216,10 +231,13 @@ public class TaskList extends Node {
return SYNC_ACTION_ERROR; return SYNC_ACTION_ERROR;
} }
// 获取子任务数量
public int getChildTaskCount() { public int getChildTaskCount() {
return mChildren.size(); return mChildren.size();
} }
// 添加子任务
public boolean addChildTask(Task task) { public boolean addChildTask(Task task) {
boolean ret = false; boolean ret = false;
if (task != null && !mChildren.contains(task)) { if (task != null && !mChildren.contains(task)) {

@ -15,7 +15,7 @@
*/ */
package net.micode.notes.gtask.exception; package net.micode.notes.gtask.exception;
//行为失败后抛出异常
public class ActionFailureException extends RuntimeException { public class ActionFailureException extends RuntimeException {
private static final long serialVersionUID = 4425249765923293627L; private static final long serialVersionUID = 4425249765923293627L;

@ -15,7 +15,7 @@
*/ */
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;

@ -23,29 +23,42 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
// 定义一个服务类用于处理Google任务的同步
public class GTaskSyncService extends Service { public class GTaskSyncService extends Service {
// 定义一个字符串常量,表示同步操作的类型
public final static String ACTION_STRING_NAME = "sync_action_type"; public final static String ACTION_STRING_NAME = "sync_action_type";
// 定义常量,表示开始同步的操作
public final static int ACTION_START_SYNC = 0; public final static int ACTION_START_SYNC = 0;
// 定义常量,表示取消同步的操作
public final static int ACTION_CANCEL_SYNC = 1; public final static int ACTION_CANCEL_SYNC = 1;
// 定义常量,表示无效的操作
public final static int ACTION_INVALID = 2; public final static int ACTION_INVALID = 2;
// 定义一个广播的名称,用于通知同步状态的变化
public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service"; public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service";
// 定义广播的附加数据键,表示是否正在同步
public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing"; public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing";
// 定义广播的附加数据键,表示同步的进度信息
public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg"; public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg";
// 定义一个异步任务,用于执行同步操作
private static GTaskASyncTask mSyncTask = null; private static GTaskASyncTask mSyncTask = null;
// 定义一个字符串,用于保存同步的进度信息
private static String mSyncProgress = ""; private static String mSyncProgress = "";
// 开始同步的方法
private void startSync() { private void startSync() {
// 如果当前没有正在执行的同步任务,则创建一个新的异步任务开始同步
if (mSyncTask == null) { if (mSyncTask == null) {
mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() { mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
public void onComplete() { public void onComplete() {
// 同步完成后将异步任务设置为null发送一个空消息的广播并停止服务
mSyncTask = null; mSyncTask = null;
sendBroadcast(""); sendBroadcast("");
stopSelf(); stopSelf();
@ -56,21 +69,27 @@ public class GTaskSyncService extends Service {
} }
} }
// 取消同步的方法
private void cancelSync() { private void cancelSync() {
// 如果当前有正在执行的同步任务,则取消它
if (mSyncTask != null) { if (mSyncTask != null) {
mSyncTask.cancelSync(); mSyncTask.cancelSync();
} }
} }
// 服务创建时调用的方法
@Override @Override
public void onCreate() { public void onCreate() {
mSyncTask = null; mSyncTask = null;
} }
// 服务启动时调用的方法
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
// 从启动服务的Intent中获取附加数据
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) { if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
// 根据附加数据中的操作类型,执行相应的操作
switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) { switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {
case ACTION_START_SYNC: case ACTION_START_SYNC:
startSync(); startSync();
@ -81,22 +100,26 @@ public class GTaskSyncService extends Service {
default: default:
break; break;
} }
return START_STICKY; return START_STICKY; // 服务被杀死后,系统会尝试重新创建并启动服务
} }
return super.onStartCommand(intent, flags, startId); return super.onStartCommand(intent, flags, startId);
} }
// 系统内存不足时调用的方法
@Override @Override
public void onLowMemory() { public void onLowMemory() {
// 如果当前有正在执行的同步任务,则取消它
if (mSyncTask != null) { if (mSyncTask != null) {
mSyncTask.cancelSync(); mSyncTask.cancelSync();
} }
} }
// 服务绑定时调用的方法此处直接返回null表示不支持绑定
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return null;
} }
// 发送广播的方法,通知同步状态的变化
public void sendBroadcast(String msg) { public void sendBroadcast(String msg) {
mSyncProgress = msg; mSyncProgress = msg;
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);
@ -105,6 +128,7 @@ public class GTaskSyncService extends Service {
sendBroadcast(intent); sendBroadcast(intent);
} }
// 静态方法用于从Activity中启动同步服务
public static void startSync(Activity activity) { public static void startSync(Activity activity) {
GTaskManager.getInstance().setActivityContext(activity); GTaskManager.getInstance().setActivityContext(activity);
Intent intent = new Intent(activity, GTaskSyncService.class); Intent intent = new Intent(activity, GTaskSyncService.class);
@ -112,16 +136,19 @@ public class GTaskSyncService extends Service {
activity.startService(intent); activity.startService(intent);
} }
// 静态方法,用于取消同步服务
public static void cancelSync(Context context) { public static void cancelSync(Context context) {
Intent intent = new Intent(context, GTaskSyncService.class); Intent intent = new Intent(context, GTaskSyncService.class);
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC); intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC);
context.startService(intent); context.startService(intent);
} }
// 静态方法,用于判断当前是否有正在执行的同步任务
public static boolean isSyncing() { public static boolean isSyncing() {
return mSyncTask != null; return mSyncTask != null;
} }
// 静态方法,用于获取同步的进度信息
public static String getProgressString() { public static String getProgressString() {
return mSyncProgress; return mSyncProgress;
} }

@ -15,6 +15,7 @@
*/ */
package net.micode.notes.model; package net.micode.notes.model;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;
import android.content.ContentProviderResult; import android.content.ContentProviderResult;
import android.content.ContentUris; import android.content.ContentUris;
@ -33,16 +34,19 @@ import net.micode.notes.data.Notes.TextNote;
import java.util.ArrayList; import java.util.ArrayList;
public class Note { public class Note {
private ContentValues mNoteDiffValues; private ContentValues mNoteDiffValues; // 用于存储笔记的差异值
private NoteData mNoteData; private NoteData mNoteData; // 笔记数据对象
private static final String TAG = "Note"; private static final String TAG = "Note"; // 日志标签
/** /**
* Create a new note id for adding a new note to databases * ID
* @param context
* @param folderId ID
* @return ID
*/ */
public static synchronized long getNewNoteId(Context context, long folderId) { public static synchronized long getNewNoteId(Context context, long folderId) {
// Create a new note in the database // 在数据库中创建一个新笔记
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
long createdTime = System.currentTimeMillis(); long createdTime = System.currentTimeMillis();
values.put(NoteColumns.CREATED_DATE, createdTime); values.put(NoteColumns.CREATED_DATE, createdTime);
@ -56,72 +60,109 @@ public class Note {
try { try {
noteId = Long.valueOf(uri.getPathSegments().get(1)); noteId = 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());
noteId = 0; noteId = 0;
} }
if (noteId == -1) { if (noteId == -1) {
throw new IllegalStateException("Wrong note id:" + noteId); throw new IllegalStateException("错误的笔记ID:" + noteId);
} }
return noteId; return noteId;
} }
/**
*
*/
public Note() { public Note() {
mNoteDiffValues = new ContentValues(); mNoteDiffValues = new ContentValues();
mNoteData = new NoteData(); mNoteData = new NoteData();
} }
/**
*
* @param key
* @param value
*/
public void setNoteValue(String key, String value) { public void setNoteValue(String key, String value) {
mNoteDiffValues.put(key, value); mNoteDiffValues.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());
} }
/**
*
* @param key
* @param value
*/
public void setTextData(String key, String value) { public void setTextData(String key, String value) {
mNoteData.setTextData(key, value); mNoteData.setTextData(key, value);
} }
/**
* ID
* @param id ID
*/
public void setTextDataId(long id) { public void setTextDataId(long id) {
mNoteData.setTextDataId(id); mNoteData.setTextDataId(id);
} }
/**
* ID
* @return ID
*/
public long getTextDataId() { public long getTextDataId() {
return mNoteData.mTextDataId; return mNoteData.mTextDataId;
} }
/**
* ID
* @param id ID
*/
public void setCallDataId(long id) { public void setCallDataId(long id) {
mNoteData.setCallDataId(id); mNoteData.setCallDataId(id);
} }
/**
*
* @param key
* @param value
*/
public void setCallData(String key, String value) { public void setCallData(String key, String value) {
mNoteData.setCallData(key, value); mNoteData.setCallData(key, value);
} }
/**
*
* @return truefalse
*/
public boolean isLocalModified() { public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
} }
/**
*
* @param context
* @param noteId ID
* @return truefalse
*/
public boolean syncNote(Context context, long noteId) { public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) { if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId); throw new IllegalArgumentException("错误的笔记ID:" + noteId);
} }
if (!isLocalModified()) { if (!isLocalModified()) {
return true; return true;
} }
/** // 更新笔记的修改状态和修改时间
* In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and
* {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the
* note data info
*/
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, "Update note error, should not happen"); Log.e(TAG, "更新笔记出错,不应发生");
// Do not return, fall through // 不要返回,继续执行
} }
mNoteDiffValues.clear(); mNoteDiffValues.clear();
// 如果笔记数据被修改且推送到ContentResolver失败则返回false
if (mNoteData.isLocalModified() if (mNoteData.isLocalModified()
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) { && (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
return false; return false;
@ -130,17 +171,19 @@ public class Note {
return true; return true;
} }
/**
*
*/
private class NoteData { private class NoteData {
private long mTextDataId; private long mTextDataId; // 文本数据ID
private ContentValues mTextDataValues; // 文本数据值
private ContentValues mTextDataValues; private long mCallDataId; // 通话数据ID
private ContentValues mCallDataValues; // 通话数据值
private long mCallDataId; private static final String TAG = "NoteData"; // 日志标签
private ContentValues mCallDataValues;
private static final String TAG = "NoteData";
/**
*
*/
public NoteData() { public NoteData() {
mTextDataValues = new ContentValues(); mTextDataValues = new ContentValues();
mCallDataValues = new ContentValues(); mCallDataValues = new ContentValues();
@ -148,36 +191,64 @@ public class Note {
mCallDataId = 0; mCallDataId = 0;
} }
/**
*
* @return truefalse
*/
boolean isLocalModified() { boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
} }
/**
* ID
* @param id ID
*/
void setTextDataId(long id) { void setTextDataId(long id) {
if(id <= 0) { if(id <= 0) {
throw new IllegalArgumentException("Text data id should larger than 0"); throw new IllegalArgumentException("文本数据ID应大于0");
} }
mTextDataId = id; mTextDataId = id;
} }
/**
* ID
* @param id ID
*/
void setCallDataId(long id) { void setCallDataId(long id) {
if (id <= 0) { if (id <= 0) {
throw new IllegalArgumentException("Call data id should larger than 0"); throw new IllegalArgumentException("通话数据ID应大于0");
} }
mCallDataId = id; mCallDataId = id;
} }
/**
*
* @param key
* @param value
*/
void setCallData(String key, String value) { void setCallData(String key, String value) {
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());
} }
/**
*
* @param key
* @param value
*/
void setTextData(String key, String value) { void setTextData(String key, String value) {
mTextDataValues.put(key, value); mTextDataValues.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());
} }
/**
* ContentResolver
* @param context
* @param noteId ID
* @return Urinull
*/
Uri pushIntoContentResolver(Context context, long noteId) { Uri pushIntoContentResolver(Context context, long noteId) {
/** /**
* Check for safety * Check for safety

@ -33,35 +33,36 @@ import net.micode.notes.tool.ResourceParser.NoteBgResources;
public class WorkingNote { public class WorkingNote {
// Note for the working note // 便签的Note对象
private Note mNote; private Note mNote;
// Note Id // 便签的ID
private long mNoteId; private long mNoteId;
// Note content // 便签的内容
private String mContent; private String mContent;
// Note mode // 便签的模式(可能是检查列表模式等)
private int mMode; private int mMode;
private long mAlertDate; private long mAlertDate; // 提醒日期
private long mModifiedDate; private long mModifiedDate; // 修改日期
private int mBgColorId; private int mBgColorId; // 背景颜色ID
private int mWidgetId; private int mWidgetId; // 小部件ID
private int mWidgetType; private int mWidgetType; // 小部件类型
private long mFolderId; private long mFolderId; // 文件夹ID
private Context mContext; private Context mContext; // 上下文对象
private static final String TAG = "WorkingNote"; private static final String TAG = "WorkingNote"; // 日志标签
private boolean mIsDeleted; private boolean mIsDeleted; // 是否已删除
private NoteSettingChangedListener mNoteSettingStatusListener; private NoteSettingChangedListener mNoteSettingStatusListener; // 便签设置状态监听器
// 数据列的投影,用于数据库查询
public static final String[] DATA_PROJECTION = new String[] { public static final String[] DATA_PROJECTION = new String[] {
DataColumns.ID, DataColumns.ID,
DataColumns.CONTENT, DataColumns.CONTENT,
@ -72,6 +73,7 @@ public class WorkingNote {
DataColumns.DATA4, DataColumns.DATA4,
}; };
// 便签列的投影,用于数据库查询
public static final String[] NOTE_PROJECTION = new String[] { public static final String[] NOTE_PROJECTION = new String[] {
NoteColumns.PARENT_ID, NoteColumns.PARENT_ID,
NoteColumns.ALERTED_DATE, NoteColumns.ALERTED_DATE,
@ -81,27 +83,21 @@ public class WorkingNote {
NoteColumns.MODIFIED_DATE NoteColumns.MODIFIED_DATE
}; };
// 数据列在投影中的索引
private static final int DATA_ID_COLUMN = 0; private static final int DATA_ID_COLUMN = 0;
private static final int DATA_CONTENT_COLUMN = 1; private static final int DATA_CONTENT_COLUMN = 1;
private static final int DATA_MIME_TYPE_COLUMN = 2; private static final int DATA_MIME_TYPE_COLUMN = 2;
private static final int DATA_MODE_COLUMN = 3; private static final int DATA_MODE_COLUMN = 3;
// 便签列在投影中的索引
private static final int NOTE_PARENT_ID_COLUMN = 0; private static final int NOTE_PARENT_ID_COLUMN = 0;
private static final int NOTE_ALERTED_DATE_COLUMN = 1; private static final int NOTE_ALERTED_DATE_COLUMN = 1;
private static final int NOTE_BG_COLOR_ID_COLUMN = 2; private static final int NOTE_BG_COLOR_ID_COLUMN = 2;
private static final int NOTE_WIDGET_ID_COLUMN = 3; private static final int NOTE_WIDGET_ID_COLUMN = 3;
private static final int NOTE_WIDGET_TYPE_COLUMN = 4; private static final int NOTE_WIDGET_TYPE_COLUMN = 4;
private static final int NOTE_MODIFIED_DATE_COLUMN = 5; private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
// New note construct // 新建便签的构造函数
private WorkingNote(Context context, long folderId) { private WorkingNote(Context context, long folderId) {
mContext = context; mContext = context;
mAlertDate = 0; mAlertDate = 0;
@ -111,19 +107,20 @@ public class WorkingNote {
mNoteId = 0; mNoteId = 0;
mIsDeleted = false; mIsDeleted = false;
mMode = 0; mMode = 0;
mWidgetType = Notes.TYPE_WIDGET_INVALIDE; mWidgetType = Notes.TYPE_WIDGET_INVALIDE; // 无效的小部件类型
} }
// Existing note construct // 现有便签的构造函数
private WorkingNote(Context context, long noteId, long folderId) { private WorkingNote(Context context, long noteId, long folderId) {
mContext = context; mContext = context;
mNoteId = noteId; mNoteId = noteId;
mFolderId = folderId; mFolderId = folderId;
mIsDeleted = false; mIsDeleted = false;
mNote = new Note(); mNote = new Note();
loadNote(); loadNote(); // 加载便签数据
} }
// 从数据库中加载便签数据
private void loadNote() { private void loadNote() {
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,
@ -143,13 +140,14 @@ public class WorkingNote {
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(); // 加载便签的具体内容
} }
// 从数据库中加载便签的具体内容
private void loadNoteData() { private void loadNoteData() {
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
DataColumns.NOTE_ID + "=?", new String[] { DataColumns.NOTE_ID + "=?", new String[] {
String.valueOf(mNoteId) String.valueOf(mNoteId)
}, null); }, null);
if (cursor != null) { if (cursor != null) {
@ -174,8 +172,9 @@ public class WorkingNote {
} }
} }
// 创建一个空的便签
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 note = new WorkingNote(context, folderId); WorkingNote note = new WorkingNote(context, folderId);
note.setBgColorId(defaultBgColorId); note.setBgColorId(defaultBgColorId);
note.setWidgetId(widgetId); note.setWidgetId(widgetId);
@ -183,10 +182,12 @@ public class WorkingNote {
return note; return note;
} }
// 加载一个已存在的便签
public static WorkingNote load(Context context, long id) { public static WorkingNote load(Context context, long id) {
return new WorkingNote(context, id, 0); return new WorkingNote(context, id, 0);
} }
// 保存便签
public synchronized boolean saveNote() { public synchronized boolean saveNote() {
if (isWorthSaving()) { if (isWorthSaving()) {
if (!existInDatabase()) { if (!existInDatabase()) {
@ -198,9 +199,7 @@ public class WorkingNote {
mNote.syncNote(mContext, mNoteId); mNote.syncNote(mContext, mNoteId);
/** // 如果存在与此便签相关的小部件,则更新小部件内容
* Update widget content if there exist any widget of this note
*/
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) {
@ -212,10 +211,12 @@ public class WorkingNote {
} }
} }
// 检查便签是否存在于数据库中
public boolean existInDatabase() { public boolean existInDatabase() {
return mNoteId > 0; return mNoteId > 0;
} }
// 检查便签是否值得保存
private boolean isWorthSaving() { private boolean isWorthSaving() {
if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent))
|| (existInDatabase() && !mNote.isLocalModified())) { || (existInDatabase() && !mNote.isLocalModified())) {
@ -225,10 +226,12 @@ public class WorkingNote {
} }
} }
// 设置便签设置状态监听器
public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) {
mNoteSettingStatusListener = l; mNoteSettingStatusListener = l;
} }
// 设置提醒日期
public void setAlertDate(long date, boolean set) { public void setAlertDate(long date, boolean set) {
if (date != mAlertDate) { if (date != mAlertDate) {
mAlertDate = date; mAlertDate = date;
@ -238,6 +241,7 @@ public class WorkingNote {
mNoteSettingStatusListener.onClockAlertChanged(date, set); mNoteSettingStatusListener.onClockAlertChanged(date, set);
} }
} }
// 标记便签为已删除或未删除
public void markDeleted(boolean mark) { public void markDeleted(boolean mark) {
mIsDeleted = mark; mIsDeleted = mark;

@ -36,123 +36,208 @@ import java.util.HashSet;
public class DataUtils { public class DataUtils {
// 常量标签,用于日志输出
public static final String TAG = "DataUtils"; public static final String TAG = "DataUtils";
/**
*
*
* @param resolver 访
* @param ids ID
* @return truefalse
*/
public static boolean batchDeleteNotes(ContentResolver resolver, HashSet<Long> ids) { public static boolean batchDeleteNotes(ContentResolver resolver, HashSet<Long> ids) {
// 如果ID集合为空则直接返回true表示删除成功实际未进行删除操作
if (ids == null) { if (ids == null) {
Log.d(TAG, "the ids is null"); Log.d(TAG, "the ids is null");
return true; return true;
} }
// 如果ID集合大小为0也直接返回true
if (ids.size() == 0) { if (ids.size() == 0) {
Log.d(TAG, "no id is in the hashset"); Log.d(TAG, "no id is in the hashset");
return true; return true;
} }
// 创建一个内容提供者操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
// 遍历ID集合构建删除操作
for (long id : ids) { for (long id : ids) {
// 如果是系统根文件夹,则跳过删除操作,并输出错误日志
if(id == Notes.ID_ROOT_FOLDER) { if(id == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Don't delete system folder root"); Log.e(TAG, "Don't delete system folder root");
continue; continue;
} }
// 构建删除操作,并添加到操作列表
ContentProviderOperation.Builder builder = ContentProviderOperation ContentProviderOperation.Builder builder = ContentProviderOperation
.newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id));
operationList.add(builder.build()); operationList.add(builder.build());
} }
try { try {
// 批量执行操作,并获取结果
ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList);
// 如果结果为空或长度为0或第一个结果为空则认为删除失败
if (results == null || results.length == 0 || results[0] == null) { if (results == null || results.length == 0 || results[0] == null) {
Log.d(TAG, "delete notes failed, ids:" + ids.toString()); Log.d(TAG, "delete notes failed, ids:" + ids.toString());
return false; return false;
} }
// 删除成功
return true; return true;
} catch (RemoteException e) { } catch (RemoteException e) {
// 捕获远程异常,并输出错误日志
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
} catch (OperationApplicationException e) { } catch (OperationApplicationException e) {
// 捕获操作应用异常,并输出错误日志
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
} }
// 发生异常返回false
return false; return false;
} }
/**
*
*
* @param resolver 访
* @param id ID
* @param srcFolderId ID
* @param desFolderId ID
*/
public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) {
// 创建内容值对象,用于存储要更新的字段及其新值
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
// 设置目标文件夹ID
values.put(NoteColumns.PARENT_ID, desFolderId); values.put(NoteColumns.PARENT_ID, desFolderId);
// 设置源文件夹ID
values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId);
// 设置本地修改标志为1
values.put(NoteColumns.LOCAL_MODIFIED, 1); values.put(NoteColumns.LOCAL_MODIFIED, 1);
// 更新笔记信息
resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null);
} }
public static boolean batchMoveToFolder(ContentResolver resolver, HashSet<Long> ids, /**
long folderId) { *
*
* @param resolver 访
* @param ids ID
* @param folderId ID
* @return truefalse
*/
public static boolean batchMoveToFolder(ContentResolver resolver, HashSet<Long> ids, long folderId) {
// 如果ID集合为空则直接返回true表示移动成功实际未进行移动操作
if (ids == null) { if (ids == null) {
Log.d(TAG, "the ids is null"); Log.d(TAG, "the ids is null");
return true; return true;
} }
// 创建一个内容提供者操作列表
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
// 遍历ID集合构建更新操作
for (long id : ids) { for (long id : ids) {
ContentProviderOperation.Builder builder = ContentProviderOperation ContentProviderOperation.Builder builder = ContentProviderOperation
.newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id));
// 设置目标文件夹ID
builder.withValue(NoteColumns.PARENT_ID, folderId); builder.withValue(NoteColumns.PARENT_ID, folderId);
// 设置本地修改标志为1
builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); builder.withValue(NoteColumns.LOCAL_MODIFIED, 1);
// 将构建的操作添加到操作列表
operationList.add(builder.build()); operationList.add(builder.build());
} }
try { try {
// 批量执行操作,并获取结果
ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList);
// 如果结果为空或长度为0或第一个结果为空则认为移动失败
if (results == null || results.length == 0 || results[0] == null) { if (results == null || results.length == 0 || results[0] == null) {
Log.d(TAG, "delete notes failed, ids:" + ids.toString()); Log.d(TAG, "delete notes failed, ids:" + ids.toString());
return false; return false;
} }
// 移动成功
return true; return true;
} catch (RemoteException e) { } catch (RemoteException e) {
// 捕获远程异常,并输出错误日志
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
} catch (OperationApplicationException e) { } catch (OperationApplicationException e) {
// 捕获操作应用异常,并输出错误日志
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
} }
// 发生异常返回false
return false; return false;
} }
/** /**
* Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} *
*
* @param resolver 访
* @return
*/ */
public static int getUserFolderCount(ContentResolver resolver) { public static int getUserFolderCount(ContentResolver resolver) {
Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, // 查询非系统文件夹且非垃圾文件夹的数量
Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
new String[] { "COUNT(*)" }, new String[] { "COUNT(*)" },
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?",
new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)},
null); null);
int count = 0; int count = 0;
if(cursor != null) { // 如果游标不为空
if(cursor.moveToFirst()) { if (cursor != null) {
// 移动到结果集的第一条记录
if (cursor.moveToFirst()) {
try { try {
// 获取文件夹数量
count = cursor.getInt(0); count = cursor.getInt(0);
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
// 捕获索引越界异常,并输出错误日志
Log.e(TAG, "get folder count failed:" + e.toString()); Log.e(TAG, "get folder count failed:" + e.toString());
} finally { } finally {
// 关闭游标
cursor.close(); cursor.close();
} }
} }
} }
// 返回文件夹数量
return count; return count;
} }
/**
*
*
* @param resolver 访
* @param noteId ID
* @param type
* @return truefalse
*/
public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) {
// 查询指定ID和类型的笔记且不在垃圾文件夹中
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
null, null,
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER,
new String [] {String.valueOf(type)}, new String[] { String.valueOf(type) },
null); null);
boolean exist = false; boolean exist = false;
// 如果游标不为空
if (cursor != null) { if (cursor != null) {
// 如果查询结果的数量大于0则表示笔记存在
if (cursor.getCount() > 0) { if (cursor.getCount() > 0) {
exist = true; exist = true;
} }
// 关闭游标
cursor.close(); cursor.close();
} }
// 返回笔记是否存在
return exist; return exist;
} }
/**
*
*
* @param resolver 访
* @param noteId ID
* @return truefalse
*/
public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) {
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
null, null, null, null); null, null, null, null);

@ -32,23 +32,31 @@ import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NoteEditActivity; import net.micode.notes.ui.NoteEditActivity;
import net.micode.notes.ui.NotesListActivity; import net.micode.notes.ui.NotesListActivity;
// 这是一个抽象类,用于提供笔记小部件的功能
public abstract class NoteWidgetProvider extends AppWidgetProvider { public abstract class NoteWidgetProvider extends AppWidgetProvider {
// 定义查询数据库时需要获取的列
public static final String [] PROJECTION = new String [] { public static final String [] PROJECTION = new String [] {
NoteColumns.ID, NoteColumns.ID, // 笔记ID
NoteColumns.BG_COLOR_ID, NoteColumns.BG_COLOR_ID, // 笔记背景颜色ID
NoteColumns.SNIPPET NoteColumns.SNIPPET // 笔记摘要
}; };
// 定义列索引常量,方便后续通过索引获取数据
public static final int COLUMN_ID = 0; public static final int COLUMN_ID = 0;
public static final int COLUMN_BG_COLOR_ID = 1; public static final int COLUMN_BG_COLOR_ID = 1;
public static final int COLUMN_SNIPPET = 2; public static final int COLUMN_SNIPPET = 2;
// 定义日志标签
private static final String TAG = "NoteWidgetProvider"; private static final String TAG = "NoteWidgetProvider";
// 当小部件被删除时调用此方法
@Override @Override
public void onDeleted(Context context, int[] appWidgetIds) { public void onDeleted(Context context, int[] appWidgetIds) {
// 创建一个ContentValues对象用于更新数据库中的数据
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
// 将小部件ID设置为无效ID
values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
// 遍历所有被删除的小部件ID并更新数据库中对应的数据
for (int i = 0; i < appWidgetIds.length; i++) { for (int i = 0; i < appWidgetIds.length; i++) {
context.getContentResolver().update(Notes.CONTENT_NOTE_URI, context.getContentResolver().update(Notes.CONTENT_NOTE_URI,
values, values,
@ -57,7 +65,9 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider {
} }
} }
// 私有方法用于获取指定小部件ID的笔记信息
private Cursor getNoteWidgetInfo(Context context, int widgetId) { private Cursor getNoteWidgetInfo(Context context, int widgetId) {
// 查询数据库获取指定小部件ID且不在垃圾箱中的笔记信息
return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, return context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION, PROJECTION,
NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?",
@ -65,47 +75,61 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider {
null); null);
} }
// 保护方法,用于更新小部件,不开启隐私模式
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false); update(context, appWidgetManager, appWidgetIds, false);
} }
// 私有方法,用于更新小部件,可选择是否开启隐私模式
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean privacyMode) { boolean privacyMode) {
// 遍历所有需要更新的小部件ID
for (int i = 0; i < appWidgetIds.length; i++) { for (int i = 0; i < appWidgetIds.length; i++) {
// 如果小部件ID有效
if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {
// 初始化背景颜色ID和摘要
int bgId = ResourceParser.getDefaultBgId(context); int bgId = ResourceParser.getDefaultBgId(context);
String snippet = ""; String snippet = "";
// 创建一个指向NoteEditActivity的Intent用于点击小部件时跳转
Intent intent = new Intent(context, NoteEditActivity.class); Intent intent = new Intent(context, NoteEditActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());
// 获取指定小部件ID的笔记信息
Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
// 如果获取到笔记信息
if (c != null && c.moveToFirst()) { if (c != null && c.moveToFirst()) {
// 如果有多条笔记信息使用相同的小部件ID记录错误日志并返回
if (c.getCount() > 1) { if (c.getCount() > 1) {
Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]);
c.close(); c.close();
return; return;
} }
// 获取摘要和背景颜色ID并设置到Intent中
snippet = c.getString(COLUMN_SNIPPET); snippet = c.getString(COLUMN_SNIPPET);
bgId = c.getInt(COLUMN_BG_COLOR_ID); bgId = c.getInt(COLUMN_BG_COLOR_ID);
intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID));
intent.setAction(Intent.ACTION_VIEW); intent.setAction(Intent.ACTION_VIEW);
} else { } else {
// 如果没有获取到笔记信息设置默认摘要并设置Intent动作为插入或编辑
snippet = context.getResources().getString(R.string.widget_havenot_content); snippet = context.getResources().getString(R.string.widget_havenot_content);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT); intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
} }
// 关闭Cursor
if (c != null) { if (c != null) {
c.close(); c.close();
} }
// 创建一个RemoteViews对象用于设置小部件的UI
RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
// 设置背景图片
rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId));
// 将背景颜色ID设置到Intent中
intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);
/**
* Generate the pending intent to start host for the widget // 根据是否开启隐私模式,设置不同的文本和点击行为
*/
PendingIntent pendingIntent = null; PendingIntent pendingIntent = null;
if (privacyMode) { if (privacyMode) {
rv.setTextViewText(R.id.widget_text, rv.setTextViewText(R.id.widget_text,
@ -118,15 +142,20 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider {
PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
} }
// 设置小部件的点击行为
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
// 更新小部件的UI
appWidgetManager.updateAppWidget(appWidgetIds[i], rv); appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
} }
} }
} }
// 抽象方法由子类实现用于获取背景资源ID
protected abstract int getBgResourceId(int bgId); protected abstract int getBgResourceId(int bgId);
// 抽象方法由子类实现用于获取布局ID
protected abstract int getLayoutId(); protected abstract int getLayoutId();
// 抽象方法,由子类实现,用于获取小部件类型
protected abstract int getWidgetType(); protected abstract int getWidgetType();
} }

@ -24,24 +24,34 @@ import net.micode.notes.data.Notes;
import net.micode.notes.tool.ResourceParser; import net.micode.notes.tool.ResourceParser;
// 这是一个名为NoteWidgetProvider_2x的类它继承自NoteWidgetProvider类
public class NoteWidgetProvider_2x extends NoteWidgetProvider { public class NoteWidgetProvider_2x extends NoteWidgetProvider {
// 重写父类的onUpdate方法用于更新小部件
@Override @Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// 调用父类的update方法来进行实际的更新操作传递上下文、小部件管理器和小部件ID数组
super.update(context, appWidgetManager, appWidgetIds); super.update(context, appWidgetManager, appWidgetIds);
} }
// 重写父类的getLayoutId方法用于获取小部件的布局ID
@Override @Override
protected int getLayoutId() { protected int getLayoutId() {
// 返回widget_2x布局资源的ID
return R.layout.widget_2x; return R.layout.widget_2x;
} }
// 重写父类的getBgResourceId方法用于根据背景ID获取对应的资源ID
@Override @Override
protected int getBgResourceId(int bgId) { protected int getBgResourceId(int bgId) {
// 使用ResourceParser.WidgetBgResources的getWidget2xBgResource方法根据传入的背景ID获取对应的2x小部件背景资源ID
return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId);
} }
// 重写父类的getWidgetType方法用于获取小部件的类型
@Override @Override
protected int getWidgetType() { protected int getWidgetType() {
// 返回表示2x类型小部件的常量值
return Notes.TYPE_WIDGET_2X; return Notes.TYPE_WIDGET_2X;
} }
} }
Loading…
Cancel
Save