|
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// 声明包名,这是Java中组织类的一种方式,确保类的唯一性
|
|
|
|
|
|
|
|
|
|
package net.micode.notes.gtask.remote;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 导入Android框架和其他Java库中的类
|
|
|
|
|
|
|
|
|
|
import android.app.Activity; // 导入Activity类,它是Android应用中用户界面的一个基本组件
|
|
|
|
|
|
|
|
|
|
import android.content.ContentResolver; // 导入ContentResolver类,用于访问Android内容提供者提供的数据
|
|
|
|
|
|
|
|
|
|
import android.content.ContentUris; // 导入ContentUris类,提供用于操作URI的工具方法
|
|
|
|
|
|
|
|
|
|
import android.content.ContentValues; // 导入ContentValues类,用于存储一组值,这些值通常用于插入或更新数据库
|
|
|
|
|
|
|
|
|
|
import android.content.Context; // 导入Context类,它提供了关于应用环境和其资源的全局信息
|
|
|
|
|
|
|
|
|
|
import android.database.Cursor; // 导入Cursor类,用于遍历查询结果集
|
|
|
|
|
|
|
|
|
|
import android.util.Log; // 导入Log类,用于记录日志信息
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 导入项目内部的其他类
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.R; // 导入R类,它包含了项目中所有资源的引用,如布局、字符串等
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.data.Notes; // 导入Notes类,可能是一个用于管理笔记数据的数据库帮助类
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.data.Notes.DataColumns; // 导入DataColumns接口或类,它定义了Notes数据库中数据表的列名
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.data.Notes.NoteColumns; // 导入NoteColumns接口或类,它定义了Notes数据库中笔记数据表的列名
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.gtask.data.MetaData; // 导入MetaData类,可能用于存储与Google任务相关的元数据
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.gtask.data.Node; // 导入Node类,可能表示Google任务中的节点或任务项
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.gtask.data.SqlNote; // 导入SqlNote类,可能是一个表示笔记的实体类,与数据库交互
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.gtask.data.Task; // 导入Task类,表示Google任务中的一个任务项
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.gtask.data.TaskList; // 导入TaskList类,表示Google任务中的一个任务列表
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.gtask.exception.ActionFailureException; // 导入ActionFailureException类,表示执行动作失败时抛出的异常
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.gtask.exception.NetworkFailureException; // 导入NetworkFailureException类,表示网络请求失败时抛出的异常
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.tool.DataUtils; // 导入DataUtils类,可能包含了一些用于数据处理的工具方法
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.tool.GTaskStringUtils; // 导入GTaskStringUtils类,可能包含了一些用于处理Google任务相关字符串的工具方法
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 导入Java标准库中的类
|
|
|
|
|
|
|
|
|
|
import org.json.JSONArray; // 导入JSONArray类,用于表示JSON数组
|
|
|
|
|
|
|
|
|
|
import org.json.JSONException; // 导入JSONException类,表示在解析JSON时发生的异常
|
|
|
|
|
|
|
|
|
|
import org.json.JSONObject; // 导入JSONObject类,用于表示JSON对象
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.HashMap; // 导入HashMap类,用于存储键值对
|
|
|
|
|
|
|
|
|
|
import java.util.HashSet; // 导入HashSet类,它是一个不包含重复元素的集合
|
|
|
|
|
|
|
|
|
|
import java.util.Iterator; // 导入Iterator接口,用于遍历集合中的元素
|
|
|
|
|
|
|
|
|
|
import java.util.Map; // 导入Map接口,它是存储键值对的数据结构的基础接口
|
|
|
|
|
//1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 声明GTaskManager类,这是一个管理Google任务(GTasks)的类
|
|
|
|
|
|
|
|
|
|
public class GTaskManager {
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量TAG,用于日志记录时标识此类的名称
|
|
|
|
|
|
|
|
|
|
private static final String TAG = GTaskManager.class.getSimpleName();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义几个静态常量,用于表示不同的状态码
|
|
|
|
|
|
|
|
|
|
// 0表示操作成功
|
|
|
|
|
|
|
|
|
|
public static final int STATE_SUCCESS = 0;
|
|
|
|
|
|
|
|
|
|
// 1表示网络错误
|
|
|
|
|
|
|
|
|
|
public static final int STATE_NETWORK_ERROR = 1;
|
|
|
|
|
|
|
|
|
|
// 2表示内部错误
|
|
|
|
|
|
|
|
|
|
public static final int STATE_INTERNAL_ERROR = 2;
|
|
|
|
|
|
|
|
|
|
// 3表示同步正在进行中
|
|
|
|
|
|
|
|
|
|
public static final int STATE_SYNC_IN_PROGRESS = 3;
|
|
|
|
|
|
|
|
|
|
// 4表示同步被取消
|
|
|
|
|
|
|
|
|
|
public static final int STATE_SYNC_CANCELLED = 4;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个私有的静态实例变量mInstance,用于实现单例模式
|
|
|
|
|
|
|
|
|
|
private static GTaskManager mInstance = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义私有成员变量,用于存储Activity的引用
|
|
|
|
|
|
|
|
|
|
private Activity mActivity;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义私有成员变量,用于存储Context的引用
|
|
|
|
|
|
|
|
|
|
private Context mContext;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义私有成员变量,用于访问Android内容提供者提供的数据
|
|
|
|
|
|
|
|
|
|
private ContentResolver mContentResolver;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义私有成员变量,表示当前是否正在同步
|
|
|
|
|
|
|
|
|
|
private boolean mSyncing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义私有成员变量,表示同步是否被取消
|
|
|
|
|
|
|
|
|
|
private boolean mCancelled;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个HashMap,用于存储Google任务列表(TaskList)的映射关系,键是任务列表的字符串标识,值是TaskList对象
|
|
|
|
|
|
|
|
|
|
private HashMap<String, TaskList> mGTaskListHashMap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个HashMap,用于存储Google任务节点(Node)的映射关系,键是节点的字符串标识,值是Node对象
|
|
|
|
|
|
|
|
|
|
private HashMap<String, Node> mGTaskHashMap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个HashMap,用于存储元数据(MetaData)的映射关系,键是元数据的字符串标识,值是MetaData对象
|
|
|
|
|
|
|
|
|
|
private HashMap<String, MetaData> mMetaHashMap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个TaskList对象,可能用于存储元数据列表
|
|
|
|
|
|
|
|
|
|
private TaskList mMetaList;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个HashSet,用于存储本地删除的ID集合,可能用于标记那些已经在本地删除但尚未同步到云端的任务ID
|
|
|
|
|
|
|
|
|
|
private HashSet<Long> mLocalDeleteIdMap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个HashMap,用于存储Google任务ID(Gid)到本地任务ID(Nid)的映射关系
|
|
|
|
|
|
|
|
|
|
private HashMap<String, Long> mGidToNid;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个HashMap,用于存储本地任务ID(Nid)到Google任务ID(Gid)的映射关系
|
|
|
|
|
|
|
|
|
|
private HashMap<Long, String> mNidToGid;
|
|
|
|
|
//2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 私有构造函数,用于初始化GTaskManager类的实例变量
|
|
|
|
|
|
|
|
|
|
private GTaskManager() {
|
|
|
|
|
|
|
|
|
|
mSyncing = false; // 初始化同步状态为false
|
|
|
|
|
|
|
|
|
|
mCancelled = false; // 初始化取消状态为false
|
|
|
|
|
|
|
|
|
|
mGTaskListHashMap = new HashMap<String, TaskList>(); // 初始化任务列表的HashMap
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap = new HashMap<String, Node>(); // 初始化任务节点的HashMap
|
|
|
|
|
|
|
|
|
|
mMetaHashMap = new HashMap<String, MetaData>(); // 初始化元数据的HashMap
|
|
|
|
|
|
|
|
|
|
mMetaList = null; // 初始化元数据列表为null
|
|
|
|
|
|
|
|
|
|
mLocalDeleteIdMap = new HashSet<Long>(); // 初始化本地删除ID的HashSet
|
|
|
|
|
|
|
|
|
|
mGidToNid = new HashMap<String, Long>(); // 初始化GID到NID的映射
|
|
|
|
|
|
|
|
|
|
mNidToGid = new HashMap<Long, String>(); // 初始化NID到GID的映射
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取GTaskManager类的单例实例
|
|
|
|
|
|
|
|
|
|
public static synchronized GTaskManager getInstance() {
|
|
|
|
|
|
|
|
|
|
if (mInstance == null) { // 如果实例尚未创建
|
|
|
|
|
|
|
|
|
|
mInstance = new GTaskManager(); // 创建新实例
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mInstance; // 返回单例实例
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置Activity上下文,用于获取认证令牌
|
|
|
|
|
|
|
|
|
|
public synchronized void setActivityContext(Activity activity) {
|
|
|
|
|
|
|
|
|
|
mActivity = activity; // 保存Activity上下文
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 同步Google Tasks数据
|
|
|
|
|
|
|
|
|
|
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; // 设置同步状态为true
|
|
|
|
|
|
|
|
|
|
mCancelled = false; // 重置取消状态为false
|
|
|
|
|
|
|
|
|
|
// 清空所有HashMap和HashSet
|
|
|
|
|
|
|
|
|
|
mGTaskListHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mMetaHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mLocalDeleteIdMap.clear();
|
|
|
|
|
|
|
|
|
|
mGidToNid.clear();
|
|
|
|
|
|
|
|
|
|
mNidToGid.clear();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
GTaskClient client = GTaskClient.getInstance(); // 获取GTaskClient实例
|
|
|
|
|
|
|
|
|
|
client.resetUpdateArray(); // 重置更新数组
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 登录Google Tasks
|
|
|
|
|
|
|
|
|
|
if (!mCancelled) {
|
|
|
|
|
|
|
|
|
|
if (!client.login(mActivity)) { // 如果登录失败
|
|
|
|
|
|
|
|
|
|
throw new NetworkFailureException("login google task failed"); // 抛出网络失败异常
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 从Google获取任务列表
|
|
|
|
|
|
|
|
|
|
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list)); // 发布进度
|
|
|
|
|
|
|
|
|
|
initGTaskList(); // 初始化任务列表
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 执行内容同步
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
|
|
// 清空所有HashMap和HashSet
|
|
|
|
|
|
|
|
|
|
mGTaskListHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mMetaHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mLocalDeleteIdMap.clear();
|
|
|
|
|
|
|
|
|
|
mGidToNid.clear();
|
|
|
|
|
|
|
|
|
|
mNidToGid.clear();
|
|
|
|
|
|
|
|
|
|
mSyncing = false; // 设置同步状态为false
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; // 根据取消状态返回相应结果
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化Google Tasks列表
|
|
|
|
|
|
|
|
|
|
private void initGTaskList() throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
if (mCancelled) return; // 如果已取消,则直接返回
|
|
|
|
|
|
|
|
|
|
GTaskClient client = GTaskClient.getInstance(); // 获取GTaskClient实例
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
JSONArray jsTaskLists = client.getTaskLists(); // 获取任务列表的JSON数组
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 首先初始化元数据列表
|
|
|
|
|
|
|
|
|
|
mMetaList = null; // 重置元数据列表为null
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < jsTaskLists.length(); i++) { // 遍历任务列表
|
|
|
|
|
|
|
|
|
|
JSONObject object = jsTaskLists.getJSONObject(i); // 获取任务对象
|
|
|
|
|
|
|
|
|
|
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); // 获取GID
|
|
|
|
|
|
|
|
|
|
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); // 获取名称
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否为元数据文件夹
|
|
|
|
|
|
|
|
|
|
if (name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {
|
|
|
|
|
|
|
|
|
|
mMetaList = new TaskList(); // 创建元数据列表
|
|
|
|
|
|
|
|
|
|
mMetaList.setContentByRemoteJSON(object); // 设置内容
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 加载元数据
|
|
|
|
|
|
|
|
|
|
JSONArray jsMetas = client.getTaskList(gid); // 获取元数据列表的JSON数组
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < jsMetas.length(); j++) { // 遍历元数据
|
|
|
|
|
|
|
|
|
|
object = jsMetas.getJSONObject(j); // 获取元数据对象
|
|
|
|
|
|
|
|
|
|
MetaData metaData = new MetaData(); // 创建元数据实例
|
|
|
|
|
|
|
|
|
|
metaData.setContentByRemoteJSON(object); // 设置内容
|
|
|
|
|
|
|
|
|
|
if (metaData.isWorthSaving()) { // 如果值得保存
|
|
|
|
|
|
|
|
|
|
mMetaList.addChildTask(metaData); // 添加到元数据列表
|
|
|
|
|
|
|
|
|
|
if (metaData.getGid() != null) { // 如果有GID
|
|
|
|
|
|
|
|
|
|
mMetaHashMap.put(metaData.getRelatedGid(), metaData); // 添加到元数据HashMap
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果元数据列表不存在,则创建
|
|
|
|
|
|
|
|
|
|
if (mMetaList == null) {
|
|
|
|
|
|
|
|
|
|
mMetaList = new TaskList(); // 创建元数据列表
|
|
|
|
|
|
|
|
|
|
mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META); // 设置名称
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().createTaskList(mMetaList); // 创建任务列表
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化任务列表
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < jsTaskLists.length(); i++) { // 遍历任务列表
|
|
|
|
|
|
|
|
|
|
JSONObject object = jsTaskLists.getJSONObject(i); // 获取任务对象
|
|
|
|
|
|
|
|
|
|
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); // 获取GID
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
|
|
|
|
|
TaskList tasklist = new TaskList(); // 创建任务列表
|
|
|
|
|
|
|
|
|
|
tasklist.setContentByRemoteJSON(object); // 设置内容
|
|
|
|
|
|
|
|
|
|
mGTaskListHashMap.put(gid, tasklist); // 添加到任务列表HashMap
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.put(gid, tasklist); // 添加到任务节点HashMap(这里可能有误,通常应该添加任务节点而非任务列表)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 加载任务
|
|
|
|
|
|
|
|
|
|
JSONArray jsTasks = client.getTaskList(gid); // 获取任务的JSON数组
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < jsTasks.length(); j++) { // 遍历任务
|
|
|
|
|
|
|
|
|
|
object = jsTasks.getJSONObject(j); // 获取任务对象
|
|
|
|
|
|
|
|
|
|
gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); // 获取GID(这里可能覆盖了之前的gid变量,应该是nid或其他变量)
|
|
|
|
|
|
|
|
|
|
Task task = new Task(); // 创建任务实例
|
|
|
|
|
|
|
|
|
|
task.setContentByRemoteJSON(object); // 设置内容
|
|
|
|
|
|
|
|
|
|
if (task.isWorthSaving()) { // 如果值得保存
|
|
|
|
|
|
|
|
|
|
task.setMetaInfo(mMetaHashMap.get(gid)); // 设置元数据(这里gid可能应该是任务的相关GID)
|
|
|
|
|
|
|
|
|
|
tasklist.addChildTask(task); // 添加到任务列表
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.put(gid, task); // 添加到任务节点HashMap(这里gid可能应该是任务的唯一ID)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (JSONException e) { // 捕获JSON异常
|
|
|
|
|
|
|
|
|
|
Log.e(TAG, e.toString()); // 记录错误日志
|
|
|
|
|
|
|
|
|
|
e.printStackTrace(); // 打印堆栈跟踪
|
|
|
|
|
|
|
|
|
|
throw new ActionFailureException("initGTaskList: handing JSONObject failed"); // 抛出操作失败异常
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个私有方法,用于同步内容,该方法可能会抛出NetworkFailureException异常
|
|
|
|
|
|
|
|
|
|
private void syncContent() throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
int syncType; // 定义一个整型变量,用于存储同步类型
|
|
|
|
|
|
|
|
|
|
Cursor c = null; // 定义一个Cursor对象,用于数据库查询,初始化为null
|
|
|
|
|
|
|
|
|
|
String gid; // 定义一个字符串变量,用于存储Google任务的ID
|
|
|
|
|
|
|
|
|
|
Node node; // 定义一个Node对象,用于表示一个任务节点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清空本地删除ID的映射表
|
|
|
|
|
|
|
|
|
|
mLocalDeleteIdMap.clear();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果同步已被取消,则直接返回
|
|
|
|
|
|
|
|
|
|
if (mCancelled) {
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 查询本地已删除的笔记(非系统笔记且不在回收站中的笔记)
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
// 如果查询结果不为空
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
while (c.moveToNext()) { // 遍历查询结果
|
|
|
|
|
|
|
|
|
|
gid = c.getString(SqlNote.GTASK_ID_COLUMN); // 获取Google任务的ID
|
|
|
|
|
|
|
|
|
|
node = mGTaskHashMap.get(gid); // 从哈希表中获取对应的Node对象
|
|
|
|
|
|
|
|
|
|
if (node != null) {
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.remove(gid); // 从哈希表中移除该节点
|
|
|
|
|
|
|
|
|
|
doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c); // 执行远程删除同步操作
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); // 将本地笔记ID添加到删除ID映射表中
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
Log.w(TAG, "failed to query trash folder"); // 如果查询失败,记录警告日志
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
c.close(); // 关闭Cursor对象
|
|
|
|
|
|
|
|
|
|
c = null; // 将Cursor对象置为null
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 先同步文件夹
|
|
|
|
|
|
|
|
|
|
syncFolder();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 查询数据库中存在的笔记(类型为笔记且不在回收站中的笔记)
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
while (c.moveToNext()) { // 遍历查询结果
|
|
|
|
|
|
|
|
|
|
gid = c.getString(SqlNote.GTASK_ID_COLUMN); // 获取Google任务的ID
|
|
|
|
|
|
|
|
|
|
node = mGTaskHashMap.get(gid); // 从哈希表中获取对应的Node对象
|
|
|
|
|
|
|
|
|
|
if (node != null) {
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.remove(gid); // 从哈希表中移除该节点
|
|
|
|
|
|
|
|
|
|
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); // 将Google任务ID和本地笔记ID添加到映射表中
|
|
|
|
|
|
|
|
|
|
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); // 将本地笔记ID和Google任务ID添加到映射表中
|
|
|
|
|
|
|
|
|
|
syncType = node.getSyncAction(c); // 获取同步类型
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
|
|
|
|
|
|
|
|
|
|
// 如果Google任务ID为空,则为本地新增
|
|
|
|
|
|
|
|
|
|
syncType = Node.SYNC_ACTION_ADD_REMOTE;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// 如果Google任务ID不为空但哈希表中无对应节点,则为远程删除
|
|
|
|
|
|
|
|
|
|
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(); // 关闭Cursor对象
|
|
|
|
|
|
|
|
|
|
c = null; // 将Cursor对象置为null
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 遍历哈希表中剩余的项目(即远程新增的项目)
|
|
|
|
|
|
|
|
|
|
Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator();
|
|
|
|
|
|
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
|
|
|
|
|
|
Map.Entry<String, Node> 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");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有被取消,则刷新本地同步ID
|
|
|
|
|
|
|
|
|
|
if (!mCancelled) {
|
|
|
|
|
|
|
|
|
|
// 提交更新到GTaskClient实例(可能是与服务器同步的客户端)
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().commitUpdate();
|
|
|
|
|
|
|
|
|
|
// 刷新本地同步ID
|
|
|
|
|
|
|
|
|
|
refreshLocalSyncId();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个私有方法,用于同步文件夹
|
|
|
|
|
|
|
|
|
|
private void syncFolder() throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
Cursor c = null; // 声明一个Cursor对象,用于数据库查询
|
|
|
|
|
|
|
|
|
|
String gid; // 声明一个字符串变量,用于存储Google任务的ID
|
|
|
|
|
|
|
|
|
|
Node node; // 声明一个Node对象,可能代表一个笔记或文件夹的节点
|
|
|
|
|
|
|
|
|
|
int syncType; // 声明一个整型变量,用于存储同步类型
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果操作被取消,则直接返回
|
|
|
|
|
|
|
|
|
|
if (mCancelled) {
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 查询根文件夹
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
// 使用ContentResolver查询根文件夹的信息
|
|
|
|
|
|
|
|
|
|
c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI,
|
|
|
|
|
|
|
|
|
|
Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null);
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
c.moveToNext(); // 移动到查询结果的下一行(实际上是第一行)
|
|
|
|
|
|
|
|
|
|
gid = c.getString(SqlNote.GTASK_ID_COLUMN); // 获取Google任务的ID
|
|
|
|
|
|
|
|
|
|
node = mGTaskHashMap.get(gid); // 从哈希表中获取对应的Node对象
|
|
|
|
|
|
|
|
|
|
if (node != null) {
|
|
|
|
|
|
|
|
|
|
// 如果Node对象存在,则进行一系列更新操作
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.remove(gid); // 从哈希表中移除该Node
|
|
|
|
|
|
|
|
|
|
mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER); // 更新全局ID到本地ID的映射
|
|
|
|
|
|
|
|
|
|
mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid); // 更新本地ID到全局ID的映射
|
|
|
|
|
|
|
|
|
|
// 如果根文件夹的名称不是默认的,则更新远程名称
|
|
|
|
|
|
|
|
|
|
if (!node.getName().equals(
|
|
|
|
|
|
|
|
|
|
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT))
|
|
|
|
|
|
|
|
|
|
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); // 执行内容同步
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// 如果Node对象不存在,则添加远程Node
|
|
|
|
|
|
|
|
|
|
doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// 如果查询失败,则记录警告日志
|
|
|
|
|
|
|
|
|
|
Log.w(TAG, "failed to query root folder");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
|
|
// 确保Cursor被关闭
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
c.close();
|
|
|
|
|
|
|
|
|
|
c = null;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 查询通话记录文件夹
|
|
|
|
|
|
|
|
|
|
// ...(这部分代码与上面的根文件夹查询逻辑类似,只是查询条件和处理的Node不同)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 查询本地存在的其他文件夹
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
while (c.moveToNext()) {
|
|
|
|
|
|
|
|
|
|
gid = c.getString(SqlNote.GTASK_ID_COLUMN); // 获取Google任务的ID
|
|
|
|
|
|
|
|
|
|
node = mGTaskHashMap.get(gid); // 从哈希表中获取对应的Node对象
|
|
|
|
|
|
|
|
|
|
if (node != null) {
|
|
|
|
|
|
|
|
|
|
// 如果Node对象存在,则进行一系列更新操作
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.remove(gid); // 从哈希表中移除该Node
|
|
|
|
|
|
|
|
|
|
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); // 更新全局ID到本地ID的映射
|
|
|
|
|
|
|
|
|
|
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); // 更新本地ID到全局ID的映射
|
|
|
|
|
|
|
|
|
|
syncType = node.getSyncAction(c); // 获取同步类型
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// 如果Node对象不存在,则根据条件判断是本地添加还是远程删除
|
|
|
|
|
|
|
|
|
|
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
|
|
|
|
|
|
|
|
|
|
syncType = Node.SYNC_ACTION_ADD_REMOTE; // 本地添加
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
syncType = Node.SYNC_ACTION_DEL_LOCAL; // 远程删除
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 执行内容同步
|
|
|
|
|
|
|
|
|
|
doContentSync(syncType, node, c);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// 如果查询失败,则记录警告日志
|
|
|
|
|
|
|
|
|
|
Log.w(TAG, "failed to query existing folder");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
|
|
// 确保Cursor被关闭
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
c.close();
|
|
|
|
|
|
|
|
|
|
c = null;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 遍历mGTaskListHashMap中的每个条目,用于远程添加文件夹
|
|
|
|
|
|
|
|
|
|
Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();
|
|
|
|
|
|
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
|
|
|
|
|
|
Map.Entry<String, TaskList> entry = iter.next();
|
|
|
|
|
|
|
|
|
|
gid = entry.getKey(); // 获取条目的键(可能是任务列表的全局唯一标识符)
|
|
|
|
|
|
|
|
|
|
node = entry.getValue(); // 获取条目的值(任务列表对象)
|
|
|
|
|
|
|
|
|
|
// 如果mGTaskHashMap中已存在此gid的条目,则移除它,并调用doContentSync方法添加本地节点
|
|
|
|
|
|
|
|
|
|
if (mGTaskHashMap.containsKey(gid)) {
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.remove(gid);
|
|
|
|
|
|
|
|
|
|
doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有取消操作,则提交更新到GTaskClient
|
|
|
|
|
|
|
|
|
|
if (!mCancelled)
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().commitUpdate();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据同步类型和节点执行相应的同步操作
|
|
|
|
|
|
|
|
|
|
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中根据cursor获取的gid获取MetaData对象,并删除节点
|
|
|
|
|
|
|
|
|
|
meta = mMetaHashMap.get(c.getString(SqlNote.GTASK_ID_COLUMN));
|
|
|
|
|
|
|
|
|
|
if (meta != null) {
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().deleteNode(meta);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); // 添加本地删除ID到集合
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Node.SYNC_ACTION_DEL_REMOTE:
|
|
|
|
|
|
|
|
|
|
// 从mMetaHashMap中根据节点的gid获取MetaData对象,并删除节点
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
// 冲突时,目前简单采用本地更新
|
|
|
|
|
|
|
|
|
|
updateRemoteNode(node, c);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Node.SYNC_ACTION_NONE:
|
|
|
|
|
|
|
|
|
|
break; // 无操作
|
|
|
|
|
|
|
|
|
|
case Node.SYNC_ACTION_ERROR:
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
|
|
throw new ActionFailureException("unkown sync action type"); // 抛出异常
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加本地节点的方法
|
|
|
|
|
|
|
|
|
|
private void addLocalNode(Node node) throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
if (mCancelled) {
|
|
|
|
|
|
|
|
|
|
return; // 如果已取消,则直接返回
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SqlNote sqlNote;
|
|
|
|
|
|
|
|
|
|
// 判断节点类型,如果是TaskList,则根据名称决定是否为特殊文件夹
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
|
|
sqlNote = new SqlNote(mContext);
|
|
|
|
|
|
|
|
|
|
sqlNote.setContent(node.getLocalJSONFromContent()); // 设置节点内容
|
|
|
|
|
|
|
|
|
|
sqlNote.setParentId(Notes.ID_ROOT_FOLDER); // 设置父节点为根文件夹
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else { // 如果不是TaskList,则处理为Task
|
|
|
|
|
|
|
|
|
|
sqlNote = new SqlNote(mContext);
|
|
|
|
|
|
|
|
|
|
JSONObject js = node.getLocalJSONFromContent();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
// 处理节点内容中的note和data部分,检查ID是否已存在
|
|
|
|
|
|
|
|
|
|
if (js.has(GTaskStringUtils.META_HEAD_NOTE)) {
|
|
|
|
|
|
|
|
|
|
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
|
|
|
|
|
|
|
|
|
|
if (note.has(NoteColumns.ID)) {
|
|
|
|
|
|
|
|
|
|
long id = note.getLong(NoteColumns.ID);
|
|
|
|
|
|
|
|
|
|
if (DataUtils.existInNoteDatabase(mContentResolver, id)) {
|
|
|
|
|
|
|
|
|
|
// 如果ID已存在,则移除ID
|
|
|
|
|
|
|
|
|
|
note.remove(NoteColumns.ID);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (js.has(GTaskStringUtils.META_HEAD_DATA)) {
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
|
|
|
|
|
long dataId = data.getLong(DataColumns.ID);
|
|
|
|
|
|
|
|
|
|
if (DataUtils.existInDataDatabase(mContentResolver, dataId)) {
|
|
|
|
|
|
|
|
|
|
// 如果数据ID已存在,则移除ID
|
|
|
|
|
|
|
|
|
|
data.remove(DataColumns.ID);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (JSONException e) {
|
|
|
|
|
|
|
|
|
|
Log.w(TAG, e.toString()); // 打印警告日志
|
|
|
|
|
|
|
|
|
|
e.printStackTrace(); // 打印异常堆栈
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sqlNote.setContent(js); // 设置节点内容
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取父节点的ID,并设置给当前节点
|
|
|
|
|
|
|
|
|
|
Long parentId = mGidToNid.get(((Task) node).getParent().getGid());
|
|
|
|
|
|
|
|
|
|
if (parentId == null) {
|
|
|
|
|
|
|
|
|
|
Log.e(TAG, "cannot find task's parent id locally"); // 打印错误日志
|
|
|
|
|
|
|
|
|
|
throw new ActionFailureException("cannot add local node"); // 抛出异常
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sqlNote.setParentId(parentId.longValue());
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建一个本地节点
|
|
|
|
|
|
|
|
|
|
sqlNote.setGtaskId(node.getGid()); // 为SqlNote对象设置全局ID(Gid),这个Gid来自传入的Node对象
|
|
|
|
|
|
|
|
|
|
sqlNote.commit(false); // 提交SqlNote对象到数据库,false表示不是一次更新操作
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新Gid到Nid的映射
|
|
|
|
|
|
|
|
|
|
mGidToNid.put(node.getGid(), sqlNote.getId()); // 将Node的全局ID(Gid)映射到SqlNote的本地ID(Nid)
|
|
|
|
|
|
|
|
|
|
mNidToGid.put(sqlNote.getId(), node.getGid()); // 同时,将SqlNote的本地ID(Nid)映射回全局ID(Gid)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新元数据
|
|
|
|
|
|
|
|
|
|
updateRemoteMeta(node.getGid(), sqlNote); // 调用函数更新远程元数据,传入Node的Gid和SqlNote对象
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新本地节点
|
|
|
|
|
|
|
|
|
|
private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
if (mCancelled) { // 检查操作是否被取消
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SqlNote sqlNote;
|
|
|
|
|
|
|
|
|
|
// 更新本地笔记
|
|
|
|
|
|
|
|
|
|
sqlNote = new SqlNote(mContext, c); // 使用上下文和游标创建SqlNote对象
|
|
|
|
|
|
|
|
|
|
sqlNote.setContent(node.getLocalJSONFromContent()); // 设置SqlNote的内容为Node的本地JSON内容
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取父节点的ID,如果是任务则通过Gid映射获取,否则默认为根文件夹ID
|
|
|
|
|
|
|
|
|
|
Long parentId = (node instanceof Task) ? mGidToNid.get(((Task) node).getParent().getGid())
|
|
|
|
|
|
|
|
|
|
: new Long(Notes.ID_ROOT_FOLDER);
|
|
|
|
|
|
|
|
|
|
if (parentId == null) { // 如果父ID为空
|
|
|
|
|
|
|
|
|
|
Log.e(TAG, "cannot find task's parent id locally"); // 打印错误日志
|
|
|
|
|
|
|
|
|
|
throw new ActionFailureException("cannot update local node"); // 抛出操作失败异常
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sqlNote.setParentId(parentId.longValue()); // 设置SqlNote的父ID
|
|
|
|
|
|
|
|
|
|
sqlNote.commit(true); // 提交更改到数据库,true表示是一次更新操作
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新元数据信息
|
|
|
|
|
|
|
|
|
|
updateRemoteMeta(node.getGid(), sqlNote); // 调用函数更新远程元数据
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 添加远程节点
|
|
|
|
|
|
|
|
|
|
private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
if (mCancelled) { // 检查操作是否被取消
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SqlNote sqlNote = new SqlNote(mContext, c); // 使用上下文和游标创建SqlNote对象
|
|
|
|
|
|
|
|
|
|
Node n;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据SqlNote的类型进行不同的处理
|
|
|
|
|
|
|
|
|
|
if (sqlNote.isNoteType()) { // 如果是笔记类型
|
|
|
|
|
|
|
|
|
|
Task task = new Task(); // 创建一个Task对象
|
|
|
|
|
|
|
|
|
|
task.setContentByLocalJSON(sqlNote.getContent()); // 设置Task的内容为SqlNote的内容
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String parentGid = mNidToGid.get(sqlNote.getParentId()); // 获取父节点的Gid
|
|
|
|
|
|
|
|
|
|
if (parentGid == null) { // 如果父节点的Gid为空
|
|
|
|
|
|
|
|
|
|
Log.e(TAG, "cannot find task's parent tasklist"); // 打印错误日志
|
|
|
|
|
|
|
|
|
|
throw new ActionFailureException("cannot add remote task"); // 抛出操作失败异常
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mGTaskListHashMap.get(parentGid).addChildTask(task); // 将Task添加到对应的TaskList中
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().createTask(task); // 调用GTaskClient的实例创建任务
|
|
|
|
|
|
|
|
|
|
n = (Node) task; // 将Task对象转换为Node对象
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新远程元数据
|
|
|
|
|
|
|
|
|
|
updateRemoteMeta(task.getGid(), sqlNote);
|
|
|
|
|
|
|
|
|
|
} else { // 如果不是笔记类型(假设是文件夹)
|
|
|
|
|
|
|
|
|
|
TaskList tasklist = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据SqlNote的ID和名称判断文件夹是否已存在
|
|
|
|
|
|
|
|
|
|
String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX; // 获取文件夹前缀
|
|
|
|
|
|
|
|
|
|
if (sqlNote.getId() == Notes.ID_ROOT_FOLDER)
|
|
|
|
|
|
|
|
|
|
folderName += GTaskStringUtils.FOLDER_DEFAULT; // 如果是根文件夹,添加默认后缀
|
|
|
|
|
|
|
|
|
|
else if (sqlNote.getId() == Notes.ID_CALL_RECORD_FOLDER)
|
|
|
|
|
|
|
|
|
|
folderName += GTaskStringUtils.FOLDER_CALL_NOTE; // 如果是通话记录文件夹,添加对应后缀
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
folderName += sqlNote.getSnippet(); // 否则,添加SqlNote的摘要作为后缀
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 遍历所有TaskList,查找是否存在同名文件夹
|
|
|
|
|
|
|
|
|
|
Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();
|
|
|
|
|
|
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
|
|
|
|
|
|
Map.Entry<String, TaskList> entry = iter.next();
|
|
|
|
|
|
|
|
|
|
String gid = entry.getKey();
|
|
|
|
|
|
|
|
|
|
TaskList list = entry.getValue();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (list.getName().equals(folderName)) { // 如果找到同名文件夹
|
|
|
|
|
|
|
|
|
|
tasklist = list; // 将找到的文件夹赋值给tasklist
|
|
|
|
|
|
|
|
|
|
if (mGTaskHashMap.containsKey(gid)) {
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.remove(gid); // 从另一个映射中移除该Gid,避免重复
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有找到同名文件夹,则创建一个新的
|
|
|
|
|
|
|
|
|
|
if (tasklist == null) {
|
|
|
|
|
|
|
|
|
|
tasklist = new TaskList(); // 创建新的TaskList对象
|
|
|
|
|
|
|
|
|
|
tasklist.setContentByLocalJSON(sqlNote.getContent()); // 设置内容
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().createTaskList(tasklist); // 调用GTaskClient的实例创建任务列表
|
|
|
|
|
|
|
|
|
|
mGTaskListHashMap.put(tasklist.getGid(), tasklist); // 将新创建的TaskList添加到映射中
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n = (Node) tasklist; // 将TaskList对象转换为Node对象
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新本地SqlNote的Gid和元数据
|
|
|
|
|
|
|
|
|
|
sqlNote.setGtaskId(n.getGid()); // 设置SqlNote的全局ID(Gid)
|
|
|
|
|
|
|
|
|
|
sqlNote.commit(false); // 提交更改到数据库,false表示不是更新操作
|
|
|
|
|
|
|
|
|
|
sqlNote.resetLocalModified(); // 重置SqlNote的本地修改标志
|
|
|
|
|
|
|
|
|
|
sqlNote.commit(true); // 再次提交更改,true表示是更新操作
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新Gid到Nid和Nid到Gid的映射
|
|
|
|
|
|
|
|
|
|
mGidToNid.put(n.getGid(), sqlNote.getId()); // 更新Gid到Nid的映射
|
|
|
|
|
|
|
|
|
|
mNidToGid.put(sqlNote.getId(), n.getGid()); // 更新Nid到Gid的映射
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新远程节点
|
|
|
|
|
|
|
|
|
|
private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
if (mCancelled) { // 检查操作是否被取消
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SqlNote sqlNote = new SqlNote(mContext, c); // 使用上下文和游标创建SqlNote对象
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新远程节点
|
|
|
|
|
|
|
|
|
|
node.setContentByLocalJSON(sqlNote.getContent()); // 更新Node的内容为SqlNote的内容
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().addUpdateNode(node); // 调用GTaskClient的实例更新节点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新元数据
|
|
|
|
|
|
|
|
|
|
updateRemoteMeta(node.getGid(), sqlNote); // 调用函数更新远程元数据
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果需要,移动任务
|
|
|
|
|
|
|
|
|
|
if (sqlNote.isNoteType()) { // 如果是笔记类型(任务)
|
|
|
|
|
|
|
|
|
|
Task task = (Task) node; // 将Node转换为Task对象
|
|
|
|
|
|
|
|
|
|
TaskList preParentList = task.getParent(); // 获取任务之前的父TaskList
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String curParentGid = mNidToGid.get(sqlNote.getParentId()); // 获取当前父节点的Gid
|
|
|
|
|
|
|
|
|
|
if (curParentGid == null) { // 如果当前父节点的Gid为空
|
|
|
|
|
|
|
|
|
|
Log.e(TAG, "cannot find task's parent tasklist"); // 打印错误日志
|
|
|
|
|
|
|
|
|
|
throw new ActionFailureException("cannot update remote task"); // 抛出操作失败异常
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TaskList curParentList = mGTaskListHashMap.get(curParentGid); // 获取当前的父TaskList
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果任务的父TaskList发生了变化,则进行移动操作
|
|
|
|
|
|
|
|
|
|
if (preParentList != curParentList) {
|
|
|
|
|
|
|
|
|
|
preParentList.removeChildTask(task); // 从之前的父TaskList中移除任务
|
|
|
|
|
|
|
|
|
|
curParentList.addChildTask(task); // 将任务添加到当前的父TaskList中
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().moveTask(task, preParentList, curParentList); // 调用GTaskClient的实例移动任务
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清除本地修改标志
|
|
|
|
|
|
|
|
|
|
sqlNote.resetLocalModified();
|
|
|
|
|
|
|
|
|
|
// 提交sqlNote的更改到数据库,true参数可能表示强制提交或某种特殊模式
|
|
|
|
|
|
|
|
|
|
sqlNote.commit(true);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新远程元数据的方法,传入笔记的全局唯一标识符(gid)和SqlNote对象
|
|
|
|
|
|
|
|
|
|
private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
// 检查sqlNote对象非空且为笔记类型
|
|
|
|
|
|
|
|
|
|
if (sqlNote != null && sqlNote.isNoteType()) {
|
|
|
|
|
|
|
|
|
|
// 从哈希映射中获取gid对应的MetaData对象
|
|
|
|
|
|
|
|
|
|
MetaData metaData = mMetaHashMap.get(gid);
|
|
|
|
|
|
|
|
|
|
if (metaData != null) {
|
|
|
|
|
|
|
|
|
|
// 如果MetaData对象已存在,更新其内容
|
|
|
|
|
|
|
|
|
|
metaData.setMeta(gid, sqlNote.getContent());
|
|
|
|
|
|
|
|
|
|
// 向GTaskClient实例添加更新节点的任务
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().addUpdateNode(metaData);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// 如果MetaData对象不存在,创建一个新的
|
|
|
|
|
|
|
|
|
|
metaData = new MetaData();
|
|
|
|
|
|
|
|
|
|
// 设置MetaData的内容
|
|
|
|
|
|
|
|
|
|
metaData.setMeta(gid, sqlNote.getContent());
|
|
|
|
|
|
|
|
|
|
// 向任务列表添加子任务
|
|
|
|
|
|
|
|
|
|
mMetaList.addChildTask(metaData);
|
|
|
|
|
|
|
|
|
|
// 将MetaData对象添加到哈希映射中
|
|
|
|
|
|
|
|
|
|
mMetaHashMap.put(gid, metaData);
|
|
|
|
|
|
|
|
|
|
// 向GTaskClient实例添加创建任务的任务
|
|
|
|
|
|
|
|
|
|
GTaskClient.getInstance().createTask(metaData);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 刷新本地同步ID的方法
|
|
|
|
|
|
|
|
|
|
private void refreshLocalSyncId() throws NetworkFailureException {
|
|
|
|
|
|
|
|
|
|
// 如果同步已取消,则直接返回
|
|
|
|
|
|
|
|
|
|
if (mCancelled) {
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清除哈希映射和任务列表,准备重新初始化
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mGTaskListHashMap.clear();
|
|
|
|
|
|
|
|
|
|
mMetaHashMap.clear();
|
|
|
|
|
|
|
|
|
|
// 初始化任务列表
|
|
|
|
|
|
|
|
|
|
initGTaskList();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化Cursor对象,用于查询数据库
|
|
|
|
|
|
|
|
|
|
Cursor c = null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
// 查询笔记内容URI,过滤掉系统类型和垃圾桶文件夹的笔记
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
}, NoteColumns.TYPE + " DESC");
|
|
|
|
|
|
|
|
|
|
// 如果Cursor不为空,遍历查询结果
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
while (c.moveToNext()) {
|
|
|
|
|
|
|
|
|
|
// 获取笔记的全局唯一标识符
|
|
|
|
|
|
|
|
|
|
String gid = c.getString(SqlNote.GTASK_ID_COLUMN);
|
|
|
|
|
|
|
|
|
|
// 从哈希映射中获取对应的Node对象
|
|
|
|
|
|
|
|
|
|
Node node = mGTaskHashMap.get(gid);
|
|
|
|
|
|
|
|
|
|
if (node != null) {
|
|
|
|
|
|
|
|
|
|
// 如果Node对象存在,从哈希映射中移除
|
|
|
|
|
|
|
|
|
|
mGTaskHashMap.remove(gid);
|
|
|
|
|
|
|
|
|
|
// 更新本地数据库中该笔记的同步ID为Node的最后修改时间
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
|
|
// 如果Node对象不存在,记录错误日志
|
|
|
|
|
|
|
|
|
|
Log.e(TAG, "something is missed");
|
|
|
|
|
|
|
|
|
|
// 抛出异常,表示一些本地项目在同步后没有gid
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
|
|
// 最后确保Cursor被关闭
|
|
|
|
|
|
|
|
|
|
if (c != null) {
|
|
|
|
|
|
|
|
|
|
c.close();
|
|
|
|
|
|
|
|
|
|
c = null;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 获取同步账户名称的方法
|
|
|
|
|
|
|
|
|
|
public String getSyncAccount() {
|
|
|
|
|
|
|
|
|
|
// 返回GTaskClient实例的同步账户名称
|
|
|
|
|
|
|
|
|
|
return GTaskClient.getInstance().getSyncAccount().name;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 取消同步的方法
|
|
|
|
|
|
|
|
|
|
public void cancelSync() {
|
|
|
|
|
|
|
|
|
|
// 设置取消标志为true
|
|
|
|
|
|
|
|
|
|
mCancelled = true;
|
|
|
|
|
|
|
|
|
|
}
|