From e01f8e9e8282e1b4cc05a865ef5bc68619003aa2 Mon Sep 17 00:00:00 2001 From: pcoifxtab <1508386176@qq.com> Date: Wed, 25 Dec 2024 13:18:11 +0800 Subject: [PATCH] Delete 'GTaskManager.java' --- GTaskManager.java | 1065 --------------------------------------------- 1 file changed, 1065 deletions(-) delete mode 100644 GTaskManager.java diff --git a/GTaskManager.java b/GTaskManager.java deleted file mode 100644 index cf77515..0000000 --- a/GTaskManager.java +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * GTaskManager 负责管理本地笔记数据库与 Google Tasks 之间的同步过程。 - */ -package net.micode.notes.gtask.remote; - -import android.app.Activity; -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.util.Log; - -import net.micode.notes.R; -import net.micode.notes.data.Notes; -import net.micode.notes.data.Notes.DataColumns; -import net.micode.notes.data.Notes.NoteColumns; -import net.micode.notes.gtask.data.MetaData; -import net.micode.notes.gtask.data.Node; -import net.micode.notes.gtask.data.SqlNote; -import net.micode.notes.gtask.data.Task; -import net.micode.notes.gtask.data.TaskList; -import net.micode.notes.gtask.exception.ActionFailureException; -import net.micode.notes.gtask.exception.NetworkFailureException; -import net.micode.notes.tool.DataUtils; -import net.micode.notes.tool.GTaskStringUtils; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; - -/* - * GTaskManager 负责管理本地笔记数据库与 Google Tasks 之间的同步过程。 - */ -public class GTaskManager { - private static final String TAG = GTaskManager.class.getSimpleName(); - // 同步状态常量 - public static final int STATE_SUCCESS = 0; - - public static final int STATE_NETWORK_ERROR = 1; - - public static final int STATE_INTERNAL_ERROR = 2; - - public static final int STATE_SYNC_IN_PROGRESS = 3; - - public static final int STATE_SYNC_CANCELLED = 4; - // 单例实例 - private static GTaskManager mInstance = null; - // 用于获取认证令牌的活动上下文 - private Activity mActivity; - // 应用程序上下文 - private Context mContext; - // 内容解析器用于数据库操作 - private ContentResolver mContentResolver; - // 同步状态标志 - private boolean mSyncing; - - private boolean mCancelled; - // 用于管理任务列表、节点、元数据和 GID 与 NID 映射的哈希表 - private HashMap mGTaskListHashMap; - - private HashMap mGTaskHashMap; - - private HashMap mMetaHashMap; - - private TaskList mMetaList; - - private HashSet mLocalDeleteIdMap; - - private HashMap mGidToNid; - - private HashMap mNidToGid; - - private GTaskManager() { - // 初始化同步状态标志,表示当前没有正在进行同步 - mSyncing = false; - // 初始化取消同步标志,表示当前没有取消同步 - mCancelled = false; - // 初始化用于存储 Google Task 列表的哈希表 - mGTaskListHashMap = new HashMap();、 - // 初始化用于存储 Google Task 节点的哈希表 - mGTaskHashMap = new HashMap(); - // 初始化用于存储元数据的哈希表 - mMetaHashMap = new HashMap(); - // 初始化元数据列表,初始值为 null - mMetaList = null; - // 初始化用于存储本地删除的笔记 ID 的集合 - mLocalDeleteIdMap = new HashSet(); - // 初始化用于存储 Google Task ID 到本地笔记 ID 映射的哈希表 - mGidToNid = new HashMap(); - // 初始化用于存储本地笔记 ID 到 Google Task ID 映射的哈希表 - mNidToGid = new HashMap(); - } -/* - * 获取 GTaskManager 的单例实例。 - * 该方法使用 synchronized 关键字确保线程安全,防止多个线程同时创建实例。 - * @return GTaskManager 的单例实例 - */ - public static synchronized GTaskManager getInstance() { - // 检查单例实例是否已经创建 - if (mInstance == null) { - // 如果未创建,则创建一个新的 GTaskManager 实例 - mInstance = new GTaskManager(); - } - return mInstance; // 返回单例实例 - } -/* - * 设置活动上下文,用于获取认证令牌。 - * 该方法使用 synchronized 关键字确保线程安全,防止多个线程同时修改 mActivity 变量。 - * @param activity 活动上下文 - */ - public synchronized void setActivityContext(Activity activity) { - // used for getting authtoken - // 将传入的活动上下文赋值给 mActivity 变量 - mActivity = activity; - } -/* - * 同步本地笔记数据库与 Google Tasks。 - * 该方法负责初始化同步过程,处理同步过程中的各种异常,并返回同步结果状态。 - * @param context 应用程序上下文 - * @param asyncTask 异步任务对象,用于发布同步进度 - * @return 同步结果状态,可能的值为 STATE_SUCCESS, STATE_NETWORK_ERROR, STATE_INTERNAL_ERROR, STATE_SYNC_IN_PROGRESS, STATE_SYNC_CANCELLED - */ - public int sync(Context context, GTaskASyncTask asyncTask) { - // 检查是否已经有同步正在进行 - if (mSyncing) { - Log.d(TAG, "Sync is in progress"); - return STATE_SYNC_IN_PROGRESS; - } - // 设置应用程序上下文和内容解析器 - mContext = context; - mContentResolver = mContext.getContentResolver(); - // 标记同步正在进行 - mSyncing = true; - mCancelled = false; - // 清空所有数据结构 - mGTaskListHashMap.clear(); - mGTaskHashMap.clear(); - mMetaHashMap.clear(); - mLocalDeleteIdMap.clear(); - mGidToNid.clear(); - mNidToGid.clear(); - - try { - // 获取 GTaskClient 实例并重置更新数组 - GTaskClient client = GTaskClient.getInstance(); - client.resetUpdateArray(); - - // login google task - // 登录 Google Task - if (!mCancelled) { - if (!client.login(mActivity)) { - throw new NetworkFailureException("login google task failed"); - } - } - - // get the task list from google - // 从 Google 获取任务列表 - asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list)); - initGTaskList(); - - // do content sync work - // 执行内容同步工作 - asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing)); - syncContent(); - } catch (NetworkFailureException e) { - // 处理网络失败异常 - Log.e(TAG, e.toString()); - return STATE_NETWORK_ERROR; - } catch (ActionFailureException e) { - // 处理操作失败异常 - Log.e(TAG, e.toString()); - return STATE_INTERNAL_ERROR; - } catch (Exception e) { - // 处理其他异常 - Log.e(TAG, e.toString()); - e.printStackTrace(); - return STATE_INTERNAL_ERROR; - } finally { - // 清空所有数据结构并标记同步结束 - mGTaskListHashMap.clear(); - mGTaskHashMap.clear(); - mMetaHashMap.clear(); - mLocalDeleteIdMap.clear(); - mGidToNid.clear(); - mNidToGid.clear(); - mSyncing = false; - } - - return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; // 返回同步结果状态 - } -/* - * 初始化 Google Task 列表。 - * 该方法从 Google Task 获取任务列表,并初始化元数据列表和任务列表。 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void initGTaskList() throws NetworkFailureException { - // 检查是否已经取消同步 - if (mCancelled) - return; - // 获取 GTaskClient 实例 - GTaskClient client = GTaskClient.getInstance(); - try { - // 从 Google Task 获取任务列表 - JSONArray jsTaskLists = client.getTaskLists(); - - // init meta list first - // 首先初始化元数据列表 - mMetaList = null; //初始化元数据列表,将其设置为 null。 - for (int i = 0; i < jsTaskLists.length(); i++) { - //遍历任务列表,逐个处理每个任务列表。 - JSONObject object = jsTaskLists.getJSONObject(i); - //获取当前任务列表的 JSONObject - String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); - //获取当前任务列表的 Google Task ID - //获取当前任务列表的名称。 - String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); - // 检查是否是元数据列表 - //如果是,则初始化元数据列表并加载元数据。 - if (name - .equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { - mMetaList = new TaskList(); - //创建一个新的 TaskList 对象作为元数据列表。 - mMetaList.setContentByRemoteJSON(object); - //使用远程 JSON 数据设置元数据列表的内容。 - - // load meta data - // 加载元数据 - JSONArray jsMetas = client.getTaskList(gid); - //获取元数据列表中的元数据,返回一个 JSONArray。 - for (int j = 0; j < jsMetas.length(); j++) { - //遍历元数据列表,逐个处理每个元数据。 - object = (JSONObject) jsMetas.getJSONObject(j); - MetaData metaData = new MetaData(); - //创建一个新的 MetaData 对象 - metaData.setContentByRemoteJSON(object); - //使用远程 JSON 数据设置元数据的内容 - if (metaData.isWorthSaving()) { - //检查元数据是否值得保存。如果值得保存,则将其添加到元数据列表中,并更新 mMetaHashMap - mMetaList.addChildTask(metaData); - if (metaData.getGid() != null) { - //检查元数据的 Google Task ID 是否存在。如果存在,则将其添加到 mMetaHashMap 中 - mMetaHashMap.put(metaData.getRelatedGid(), metaData); - } - } - } - } - } - - // create meta list if not existed - // 如果元数据列表不存在,则创建一个新的元数据列表 - if (mMetaList == null) { - //检查元数据列表是否为空。如果为空,则创建一个新的元数据列表并将其添加到 Google Task 中。 - mMetaList = new TaskList(); - mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_META); - //设置元数据列表的名称 - GTaskClient.getInstance().createTaskList(mMetaList); - //将元数据列表添加到 Google Task 中 - } - - // init task list - // 初始化任务列表 - for (int i = 0; i < jsTaskLists.length(); i++) { - //再次遍历任务列表,逐个处理每个任务列表 - JSONObject object = jsTaskLists.getJSONObject(i); - String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); - String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); - // 检查是否是 MIUI 文件夹前缀的任务列表 - if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) - && !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_META)) { - //检查当前任务列表是否是 MIUI 文件夹前缀的任务列表,并且不是元数据列表。如果是,则初始化任务列表并加载任务 - TaskList tasklist = new TaskList(); - tasklist.setContentByRemoteJSON(object); - mGTaskListHashMap.put(gid, tasklist); - mGTaskHashMap.put(gid, tasklist); - - // load tasks - // 加载任务 - JSONArray jsTasks = client.getTaskList(gid); - for (int j = 0; j < jsTasks.length(); j++) { - //遍历任务列表,逐个处理每个任务。 - object = (JSONObject) jsTasks.getJSONObject(j); - gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); - Task task = new Task(); - task.setContentByRemoteJSON(object); - if (task.isWorthSaving()) { - //检查任务是否值得保存。如果值得保存,则将其添加到任务列表中,并更新 mGTaskHashMap。 - task.setMetaInfo(mMetaHashMap.get(gid)); - tasklist.addChildTask(task); - mGTaskHashMap.put(gid, task); - } - } - } - } - } catch (JSONException e) { - // 处理 JSON 解析异常 - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("initGTaskList: handing JSONObject failed"); - } - } -/* - * 同步内容。 - * 该方法负责同步本地数据库中的笔记与 Google Tasks 中的任务。 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void syncContent() throws NetworkFailureException { - int syncType; - Cursor c = null; - String gid; - Node node; - // 清空本地删除的笔记 ID 集合 - mLocalDeleteIdMap.clear(); - // 检查是否已经取消同步。如果 mCancelled 为 true,则直接返回,不执行后续操作。 - if (mCancelled) { - return; - } - - // for local deleted note - // 处理本地删除的笔记 - //使用 try-finally 结构确保在查询结束后关闭游标。 - try { - c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type<>? AND parent_id=?)", new String[] { - String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER) - }, null); - //查询本地删除的笔记。查询条件为 type 不等于 Notes.TYPE_SYSTEM 且 parent_id 等于 Notes.ID_TRASH_FOLER。 - if (c != null) { - //检查查询结果是否为空。如果不为空,则遍历查询结果。 - while (c.moveToNext()) { - //遍历查询结果,逐个处理每个笔记。 - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - //获取当前笔记的 Google Task ID。 - node = mGTaskHashMap.get(gid); - //从 mGTaskHashMap 中获取对应的节点。 - if (node != null) { - //检查节点是否存在。如果存在,则从 mGTaskHashMap 中移除该节点,并执行远程删除操作。 - mGTaskHashMap.remove(gid); - doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c); - //执行远程删除操作。 - } - - mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); - //将当前笔记的本地 ID 添加到 mLocalDeleteIdMap 中。 - } - } else { - Log.w(TAG, "failed to query trash folder"); - } - } finally { - if (c != null) { - c.close(); - c = null; - } - } - - // sync folder first - syncFolder(); - - // for note existing in database - // 处理数据库中存在的笔记 - try { - c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type=? AND parent_id<>?)", new String[] { - String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.ID_TRASH_FOLER) - }, NoteColumns.TYPE + " DESC"); - //查询数据库中存在的笔记。查询条件为 type 等于 Notes.TYPE_NOTE 且 parent_id 不等于 Notes.ID_TRASH_FOLER。 - if (c != null) { - //检查查询结果是否为空。如果不为空,则遍历查询结果。 - while (c.moveToNext()) { - //遍历查询结果,逐个处理每个笔记。 - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - //获取当前笔记的 Google Task ID。 - node = mGTaskHashMap.get(gid); - //从 mGTaskHashMap 中获取对应的节点。 - if (node != null) { - //检查节点是否存在。如果存在,则从 mGTaskHashMap 中移除该节点,并更新 mGidToNid 和 mNidToGid 映射,然后获取同步操作类型。 - mGTaskHashMap.remove(gid); - mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); - //更新 Google Task ID 到本地笔记 ID 的映射。 - mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); - //更新本地笔记 ID 到 Google Task ID 的映射。 - syncType = node.getSyncAction(c); - //获取当前笔记的同步操作类型。 - } else { - //如果节点不存在,则根据 Google Task ID 是否为空来确定同步操作类型。 - if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // local add - // 本地添加 - //检查 Google Task ID 是否为空。如果为空,则表示本地添加操作。 - syncType = Node.SYNC_ACTION_ADD_REMOTE; - //设置同步操作类型为远程添加。 - } else { - // remote delete - // 远程删除 - syncType = Node.SYNC_ACTION_DEL_LOCAL; - } - } - doContentSync(syncType, node, c);//执行同步操作。 - } - } else { - Log.w(TAG, "failed to query existing note in database"); - } - - } finally { - if (c != null) { - c.close(); - c = null; - } - } - - // go through remaining items - // 处理剩余的项目 - Iterator> iter = mGTaskHashMap.entrySet().iterator(); - //获取 mGTaskHashMap 的迭代器。 - while (iter.hasNext()) { - //遍历 mGTaskHashMap,逐个处理剩余的项目。 - Map.Entry entry = iter.next(); - //获取当前的键值对。 - node = entry.getValue(); - doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); - //执行本地添加操作 - } - - // mCancelled can be set by another thread, so we neet to check one by - // one - // clear local delete table - // 检查是否已经取消同步 - if (!mCancelled) { - // 批量删除本地删除的笔记 - if (!DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) { - throw new ActionFailureException("failed to batch-delete local deleted notes"); - } - //批量删除本地删除的笔记。如果删除失败,则抛出 ActionFailureException。 - } - - // refresh local sync id - // 刷新本地同步 ID - if (!mCancelled) { - GTaskClient.getInstance().commitUpdate(); - refreshLocalSyncId(); - } - - } -/* - * 同步文件夹。 - * 该方法负责同步本地数据库中的文件夹与 Google Tasks 中的任务列表。 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void syncFolder() throws NetworkFailureException { - Cursor c = null; - String gid; - Node node; - int syncType; - //检查是否已经取消同步。如果 mCancelled 为 true,则直接返回,不执行后续操作。 - if (mCancelled) { - return; - } - - // for root folder - //处理根文件夹。 - try { - c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, - Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null); - //查询根文件夹。查询条件为 _id 等于 Notes.ID_ROOT_FOLDER。 - if (c != null) { - //检查查询结果是否为空。如果不为空,则处理查询结果。 - c.moveToNext(); - //移动游标到下一行。 - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - //获取当前文件夹的 Google Task ID。 - node = mGTaskHashMap.get(gid); - //从 mGTaskHashMap 中获取对应的节点。 - if (node != null) { - //检查节点是否存在。如果存在,则从 mGTaskHashMap 中移除该节点,并更新 mGidToNid 和 mNidToGid 映射。 - mGTaskHashMap.remove(gid); - mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER); - //更新 Google Task ID 到本地笔记 ID 的映射。 - mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid); - // for system folder, only update remote name if necessary - //更新本地笔记 ID 到 Google Task ID 的映射。 - if (!node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) - doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); - //检查节点名称是否需要更新。如果需要更新,则执行远程更新操作。 - } else { - doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);//执行远程更新操作。 - } - } else { - Log.w(TAG, "failed to query root folder"); - } - } finally { - if (c != null) { - c.close(); - c = null; - } - } - - // for call-note folder - //处理通话记录文件夹。 - try { - c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)", - new String[] { - String.valueOf(Notes.ID_CALL_RECORD_FOLDER) - }, null); - //查询通话记录文件夹。查询条件为 _id 等于 Notes.ID_CALL_RECORD_FOLDER。 - if (c != null) { - //检查查询结果是否为空。如果不为空,则处理查询结果。 - if (c.moveToNext()) { - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - node = mGTaskHashMap.get(gid); - if (node != null) { - //检查节点是否存在。如果存在,则从 mGTaskHashMap 中移除该节点,并更新 mGidToNid 和 mNidToGid 映射。 - mGTaskHashMap.remove(gid); - mGidToNid.put(gid, (long) Notes.ID_CALL_RECORD_FOLDER); - mNidToGid.put((long) Notes.ID_CALL_RECORD_FOLDER, gid); - // for system folder, only update remote name if - // necessary - if (!node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_CALL_NOTE)) - doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); - //检查节点名称是否需要更新。如果需要更新,则执行远程更新操作。 - } else { - //如果节点不存在,则执行远程添加操作。 - doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); - } - } - } else { - Log.w(TAG, "failed to query call note folder"); - } - } finally { - if (c != null) { - c.close(); - c = null; - } - } - - // for local existing folders - //处理本地存在的文件夹。 - try { - c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type=? AND parent_id<>?)", new String[] { - String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER) - }, NoteColumns.TYPE + " DESC"); - //查询本地存在的文件夹。查询条件为 type 等于 Notes.TYPE_FOLDER 且 parent_id 不等于 Notes.ID_TRASH_FOLER。 - if (c != null) { - //检查查询结果是否为空。如果不为空,则遍历查询结果。 - while (c.moveToNext()) { - //遍历查询结果,逐个处理每个文件夹。 - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - node = mGTaskHashMap.get(gid); - if (node != null) { - //检查节点是否存在。如果存在,则从 mGTaskHashMap 中移除该节点,并更新 mGidToNid 和 mNidToGid 映射,然后获取同步操作类型。 - mGTaskHashMap.remove(gid); - mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); - mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); - syncType = node.getSyncAction(c); - } else { - //如果节点不存在,则根据 Google Task ID 是否为空来确定同步操作类型。 - if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // local add - //检查 Google Task ID 是否为空。如果为空,则表示本地添加操作 - syncType = Node.SYNC_ACTION_ADD_REMOTE; - } else { - //如果 Google Task ID 不为空,则表示远程删除操作。 - // remote delete - syncType = Node.SYNC_ACTION_DEL_LOCAL; - } - } - doContentSync(syncType, node, c); - } - } else { - Log.w(TAG, "failed to query existing folder"); - } - } finally { - if (c != null) { - c.close(); - c = null; - } - } - - // for remote add folders - Iterator> iter = mGTaskListHashMap.entrySet().iterator(); - //获取 mGTaskListHashMap 的迭代器。 - while (iter.hasNext()) { - //遍历 mGTaskListHashMap,逐个处理远程添加的文件夹。 - Map.Entry entry = iter.next(); - //获取当前的键值对 - gid = entry.getKey(); - node = entry.getValue(); - if (mGTaskHashMap.containsKey(gid)) { - //检查 mGTaskHashMap 中是否包含该节点。如果包含,则从 mGTaskHashMap 中移除该节点,并执行本地添加操作。 - mGTaskHashMap.remove(gid); - doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); - } - } - - if (!mCancelled) //检查是否已经取消同步。如果没有取消,则提交更新。 - GTaskClient.getInstance().commitUpdate(); - } -/* - * 执行内容同步操作。 - * 该方法根据同步类型执行相应的同步操作。 - * @param syncType 同步类型 - * @param node 节点对象 - * @param c 游标对象 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { - // 检查是否已经取消同步 - if (mCancelled) { - return; - } - - MetaData meta; - //根据同步类型执行相应的同步操作。 - switch (syncType) { - case Node.SYNC_ACTION_ADD_LOCAL: - // 本地添加操作 - addLocalNode(node); - break; - case Node.SYNC_ACTION_ADD_REMOTE: - // 远程添加操作 - addRemoteNode(node, c); - break; - case Node.SYNC_ACTION_DEL_LOCAL: - // 本地删除操作。从 mMetaHashMap 中获取元数据。如果元数据存在,则调用 GTaskClient.getInstance().deleteNode(meta) 方法删除元数据。将本地笔记 ID 添加到 mLocalDeleteIdMap 中。 - meta = mMetaHashMap.get(c.getString(SqlNote.GTASK_ID_COLUMN)); - if (meta != null) { - GTaskClient.getInstance().deleteNode(meta); - } - mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); - break; - case Node.SYNC_ACTION_DEL_REMOTE: - // 远程删除操作。从 mMetaHashMap 中获取元数据。如果元数据存在,则调用 GTaskClient.getInstance().deleteNode(meta) 方法删除元数据。调用 GTaskClient.getInstance().deleteNode(node) 方法删除节点。 - meta = mMetaHashMap.get(node.getGid()); - if (meta != null) { - GTaskClient.getInstance().deleteNode(meta); - } - GTaskClient.getInstance().deleteNode(node); - break; - case Node.SYNC_ACTION_UPDATE_LOCAL: - // 本地更新操作 - updateLocalNode(node, c); - break; - case Node.SYNC_ACTION_UPDATE_REMOTE: - // 远程更新操作 - updateRemoteNode(node, c); - break; - case Node.SYNC_ACTION_UPDATE_CONFLICT: - // merging both modifications maybe a good idea - // right now just use local update simply - // 更新冲突操作 - // 合并两个修改可能是一个好主意 - // 现在只是简单地使用本地更新 - updateRemoteNode(node, c); - break; - case Node.SYNC_ACTION_NONE: - // 无操作 - break; - case Node.SYNC_ACTION_ERROR: - default: - // 未知同步操作类型 - throw new ActionFailureException("unkown sync action type"); - } - } -/* - * 添加本地节点。 - * 该方法负责将远程节点添加到本地数据库中。 - * @param node 远程节点对象 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void addLocalNode(Node node) throws NetworkFailureException { - if (mCancelled) { - //检查是否已经取消同步。如果 mCancelled 为 true,则直接返回,不执行后续操作。 - return; - } - - SqlNote sqlNote;//声明一个 SqlNote 变量,用于存储本地笔记。 - if (node instanceof TaskList) { - //检查节点是否是任务列表。如果是任务列表,则根据节点的名称创建相应的本地笔记。 - if (node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) { - //检查节点名称是否是根文件夹。如果是根文件夹,则创建根文件夹的本地笔记。 - sqlNote = new SqlNote(mContext, Notes.ID_ROOT_FOLDER); - } else if (node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) { - //检查节点名称是否是通话记录文件夹。如果是通话记录文件夹,则创建通话记录文件夹的本地笔记。 - sqlNote = new SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER); - } else { - //其他文件夹。创建新的本地笔记,并设置内容和父节点 ID。 - sqlNote = new SqlNote(mContext); - sqlNote.setContent(node.getLocalJSONFromContent()); - sqlNote.setParentId(Notes.ID_ROOT_FOLDER); - } - } else { - //如果是任务。创建新的本地笔记,并设置内容和父节点 ID。 - sqlNote = new SqlNote(mContext); - JSONObject js = node.getLocalJSONFromContent(); - try { - //处理 JSON 解析异常。 - if (js.has(GTaskStringUtils.META_HEAD_NOTE)) { - //检查是否包含笔记信息。如果包含笔记信息,则检查笔记 ID 是否可用。 - JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - if (note.has(NoteColumns.ID)) { - //检查笔记信息是否包含 ID。如果包含 ID,则检查 ID 是否可用。 - long id = note.getLong(NoteColumns.ID); - if (DataUtils.existInNoteDatabase(mContentResolver, id)) { - // the id is not available, have to create a new one - //检查笔记 ID 是否存在于本地数据库中。如果存在,则移除笔记 ID。 - note.remove(NoteColumns.ID); - } - } - } - - if (js.has(GTaskStringUtils.META_HEAD_DATA)) { - //检查是否包含数据信息。如果包含数据信息,则检查数据 ID 是否可用。 - JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); - for (int i = 0; i < dataArray.length(); i++) { - //遍历数据信息,逐个处理每个数据。 - JSONObject data = dataArray.getJSONObject(i); - //获取当前数据信息。 - if (data.has(DataColumns.ID)) { - //检查数据信息是否包含 ID。如果包含 ID,则检查 ID 是否可用。 - long dataId = data.getLong(DataColumns.ID); - if (DataUtils.existInDataDatabase(mContentResolver, dataId)) { - // the data id is not available, have to create - // a new one - //检查数据 ID 是否存在于本地数据库中。如果存在,则移除数据 ID。 - data.remove(DataColumns.ID); - } - } - } - - } - } catch (JSONException e) { - Log.w(TAG, e.toString()); - e.printStackTrace(); - } - sqlNote.setContent(js);//设置本地笔记的内容。 - - Long parentId = mGidToNid.get(((Task) node).getParent().getGid()); - //获取父节点的本地 ID。 - if (parentId == null) { - //检查父节点的本地 ID 是否存在。如果不存在,则抛出 ActionFailureException 异常。 - Log.e(TAG, "cannot find task's parent id locally"); - throw new ActionFailureException("cannot add local node"); - } - sqlNote.setParentId(parentId.longValue()); - } - - // create the local node - sqlNote.setGtaskId(node.getGid());//更新 Google Task ID 到本地笔记 ID 的映射。 - sqlNote.commit(false); - - // update gid-nid mapping - mGidToNid.put(node.getGid(), sqlNote.getId());//更新本地笔记 ID 到 Google Task ID 的映射。 - mNidToGid.put(sqlNote.getId(), node.getGid()); - - // update meta - updateRemoteMeta(node.getGid(), sqlNote);//更新元数据。 - } -/* - * 更新本地节点。 - * 该方法负责将远程节点的更新同步到本地数据库中。 - * @param node 远程节点对象 - * @param c 游标对象 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { - if (mCancelled) { - //检查是否已经取消同步。如果 mCancelled 为 true,则直接返回,不执行后续操作。 - return; - } - - SqlNote sqlNote; - // update the note locally - //声明一个 SqlNote 变量,用于存储本地笔记。 - sqlNote = new SqlNote(mContext, c); - //创建一个新的 SqlNote 对象,并使用游标 c 初始化。 - sqlNote.setContent(node.getLocalJSONFromContent()); - //设置本地笔记的内容为远程节点的本地 JSON 内容。 - Long parentId = (node instanceof Task) ? mGidToNid.get(((Task) node).getParent().getGid()) - : new Long(Notes.ID_ROOT_FOLDER); - //获取父节点的本地 ID。如果节点是任务,则从 mGidToNid 映射中获取父节点的本地 ID。如果节点不是任务,则将父节点 ID 设置为根文件夹的 ID。 - if (parentId == null) { - //检查父节点的本地 ID 是否存在。如果不存在,则记录错误日志并抛出 ActionFailureException 异常。 - Log.e(TAG, "cannot find task's parent id locally"); - throw new ActionFailureException("cannot update local node"); - } - sqlNote.setParentId(parentId.longValue());//设置本地笔记的父节点 ID。 - sqlNote.commit(true);//提交本地笔记的更新。 - - // update meta info - //更新元数据信息。 - updateRemoteMeta(node.getGid(), sqlNote); - } -/* - * 添加远程节点。 - * 该方法负责将本地笔记添加到 Google Tasks 中。 - * @param node 远程节点对象 - * @param c 游标对象 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException { - if (mCancelled) { - //检查是否已经取消同步。如果 mCancelled 为 true,则直接返回,不执行后续操作。 - return; - } - - SqlNote sqlNote = new SqlNote(mContext, c); - //创建一个新的 SqlNote 对象,并使用游标 c 初始化。 - Node n; - //声明一个 Node 变量,用于存储远程节点 - - // update remotely - if (sqlNote.isNoteType()) { - //检查本地笔记是否是笔记类型。如果是笔记类型,则创建一个新的 Task 对象,并设置内容。 - Task task = new Task(); - task.setContentByLocalJSON(sqlNote.getContent()); - - String parentGid = mNidToGid.get(sqlNote.getParentId()); - if (parentGid == null) { - //检查父任务列表的 Google Task ID 是否存在。如果不存在,则记录错误日志并抛出 ActionFailureException 异常。 - Log.e(TAG, "cannot find task's parent tasklist"); - throw new ActionFailureException("cannot add remote task"); - } - mGTaskListHashMap.get(parentGid).addChildTask(task); - //将任务添加到父任务列表中。 - - GTaskClient.getInstance().createTask(task); - //创建远程任务。 - n = (Node) task; - //将 Task 对象赋值给 Node 变量。 - - // add meta - //添加元数据。 - updateRemoteMeta(task.getGid(), sqlNote); - } else { - //如果是文件夹类型。创建一个新的 TaskList 对象,并设置内容。 - TaskList tasklist = null; - - // we need to skip folder if it has already existed - String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX;//初始化文件夹名称 - if (sqlNote.getId() == Notes.ID_ROOT_FOLDER) - //检查本地笔记的 ID 是否是根文件夹的 ID。如果是根文件夹,则设置文件夹名称为默认文件夹名称。 - folderName += GTaskStringUtils.FOLDER_DEFAULT; - else if (sqlNote.getId() == Notes.ID_CALL_RECORD_FOLDER) - //检查本地笔记的 ID 是否是通话记录文件夹的 ID。如果是通话记录文件夹,则设置文件夹名称为通话记录文件夹名称。 - folderName += GTaskStringUtils.FOLDER_CALL_NOTE; - else - //其他文件夹。设置文件夹名称为本地笔记的片段。 - folderName += sqlNote.getSnippet(); - - Iterator> iter = mGTaskListHashMap.entrySet().iterator(); - while (iter.hasNext()) { - //遍历 mGTaskListHashMap,查找匹配的文件夹。 - Map.Entry entry = iter.next(); - String gid = entry.getKey(); - TaskList list = entry.getValue(); - - if (list.getName().equals(folderName)) { - //检查任务列表的名称是否与文件夹名称匹配。如果匹配,则将任务列表赋值给 tasklist 变量,并从 mGTaskHashMap 中移除该节点。 - tasklist = list; - if (mGTaskHashMap.containsKey(gid)) { - //检查 mGTaskHashMap 中是否包含该节点。如果包含,则从 mGTaskHashMap 中移除该节点。 - mGTaskHashMap.remove(gid); - } - break; - } - } - - // no match we can add now - if (tasklist == null) { - //如果没有匹配的文件夹,则可以添加。创建一个新的 TaskList 对象,并设置内容。 - tasklist = new TaskList(); - tasklist.setContentByLocalJSON(sqlNote.getContent()); - GTaskClient.getInstance().createTaskList(tasklist); - mGTaskListHashMap.put(tasklist.getGid(), tasklist); - } - n = (Node) tasklist;//将 TaskList 对象赋值给 Node 变量。 - } - - // update local note - sqlNote.setGtaskId(n.getGid());//设置本地笔记的 Google Task ID - sqlNote.commit(false);//提交本地笔记的更新。 - sqlNote.resetLocalModified();//重置本地笔记的修改标志。 - sqlNote.commit(true);//重置本地笔记的修改标志。 - - // gid-id mapping - mGidToNid.put(n.getGid(), sqlNote.getId());//更新 Google Task ID 到本地笔记 ID 的映射。 - mNidToGid.put(sqlNote.getId(), n.getGid());//更新本地笔记 ID 到 Google Task ID 的映射。 - } -/* - * 更新远程节点。 - * 该方法负责将本地笔记的更新同步到 Google Tasks 中。 - * @param node 远程节点对象 - * @param c 游标对象 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { - if (mCancelled) { - //检查是否已经取消同步。如果 mCancelled 为 true,则直接返回,不执行后续操作。 - return; - } - - SqlNote sqlNote = new SqlNote(mContext, c);//创建一个新的 SqlNote 对象,并使用游标 c 初始化。 - - // update remotely - //使用本地笔记的内容更新远程节点的内容。 - node.setContentByLocalJSON(sqlNote.getContent()); - GTaskClient.getInstance().addUpdateNode(node); - //将更新后的节点添加到 GTaskClient 的更新列表中。 - - // update meta - //更新元数据。 - updateRemoteMeta(node.getGid(), sqlNote); - - // move task if necessary - if (sqlNote.isNoteType()) { - //检查本地笔记是否是笔记类型。如果是笔记类型,则处理任务的移动 - Task task = (Task) node; - TaskList preParentList = task.getParent(); - - String curParentGid = mNidToGid.get(sqlNote.getParentId()); - if (curParentGid == null) { - //检查父任务列表的 Google Task ID 是否存在。如果不存在,则记录错误日志并抛出 ActionFailureException 异常。 - Log.e(TAG, "cannot find task's parent tasklist"); - throw new ActionFailureException("cannot update remote task"); - } - TaskList curParentList = mGTaskListHashMap.get(curParentGid); - //获取当前父任务列表。 - if (preParentList != curParentList) { - //检查任务的当前父任务列表是否与当前父任务列表不同。如果不同,则从当前父任务列表中移除任务,并将其添加到新的父任务列表中。 - preParentList.removeChildTask(task); - curParentList.addChildTask(task); - GTaskClient.getInstance().moveTask(task, preParentList, curParentList); - } - } - - // clear local modified flag - sqlNote.resetLocalModified();//清除本地笔记的修改标志。 - sqlNote.commit(true);//提交本地笔记的更新。 - } -/* - * 更新远程元数据。 - * 该方法负责将本地笔记的元数据同步到 Google Tasks 中。 - * @param gid Google Task ID - * @param sqlNote 本地笔记对象 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { - // 检查本地笔记是否为空且是笔记类型 - if (sqlNote != null && sqlNote.isNoteType()) { - // 从元数据哈希表中获取元数据 - MetaData metaData = mMetaHashMap.get(gid); - if (metaData != null) { - // 如果元数据存在,则更新元数据 - metaData.setMeta(gid, sqlNote.getContent()); - GTaskClient.getInstance().addUpdateNode(metaData); - } else { - // 如果元数据不存在,则创建新的元数据 - metaData = new MetaData(); - metaData.setMeta(gid, sqlNote.getContent()); - mMetaList.addChildTask(metaData); - mMetaHashMap.put(gid, metaData); - GTaskClient.getInstance().createTask(metaData); - } - } - } -/* - * 刷新本地同步 ID。 - * 该方法负责刷新本地笔记的同步 ID,确保本地笔记的同步 ID 与 Google Tasks 中的最新数据一致。 - * @throws NetworkFailureException 如果网络操作失败 - */ - private void refreshLocalSyncId() throws NetworkFailureException { - // 检查是否已经取消同步。如果 mCancelled 为 true,则直接返回,不执行后续操作。 - if (mCancelled) { - return; - } - - // get the latest gtask list - mGTaskHashMap.clear();//清空 mGTaskHashMap - mGTaskListHashMap.clear();//清空 mGTaskListHashMap。 - mMetaHashMap.clear();//清空 mMetaHashMap。 - initGTaskList();//初始化 Google Task 列表。 - - Cursor c = null;//声明一个游标变量 c,用于存储查询结果。 - try { - c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type<>? AND parent_id<>?)", new String[] { - //查询本地笔记。查询条件为 type 不等于 Notes.TYPE_SYSTEM 且 parent_id 不等于 Notes.ID_TRASH_FOLER。 - String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER) - }, NoteColumns.TYPE + " DESC"); - if (c != null) { - //检查查询结果是否为空。如果不为空,则遍历查询结果。 - while (c.moveToNext()) { - //遍历查询结果,逐个处理每个笔记。 - String gid = c.getString(SqlNote.GTASK_ID_COLUMN); - Node node = mGTaskHashMap.get(gid); - if (node != null) { - //检查节点是否存在。如果存在,则从 mGTaskHashMap 中移除该节点,并更新本地笔记的同步 ID。 - mGTaskHashMap.remove(gid); - ContentValues values = new ContentValues(); - values.put(NoteColumns.SYNC_ID, node.getLastModified()); - mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, - c.getLong(SqlNote.ID_COLUMN)), values, null, null); - } else { - //如果节点不存在,则记录错误日志并抛出 ActionFailureException 异常。 - Log.e(TAG, "something is missed"); - throw new ActionFailureException( - "some local items don't have gid after sync"); - } - } - } else { - Log.w(TAG, "failed to query local note to refresh sync id"); - } - } finally { - if (c != null) { - //检查游标是否为空。如果不为空,则关闭游标。 - c.close(); - c = null; - } - } - } -/* - * 获取同步账户名称。 - * 该方法返回当前用于同步的 Google 账户名称。 - * @return 同步账户名称 - */ - public String getSyncAccount() { - // 获取 GTaskClient 的单例实例,并返回同步账户的名称 - return GTaskClient.getInstance().getSyncAccount().name; - } -/* - * 取消同步。 - * 该方法用于设置取消同步标志,以便在同步过程中停止同步操作。 - */ - public void cancelSync() { - // 设置取消同步标志为 true - mCancelled = true; - } -}