From 3276d013fb309bc996bb908181ccf4aa112eb844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E4=BF=8A=E5=BD=A6?= <1101703918@qq.com> Date: Thu, 15 May 2025 14:23:41 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B3=A8=E9=87=8Aapp\src\main\java\net\mic?= =?UTF-8?q?ode\notes\gtask\exception=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notes/gtask/exception/ActionFailureException.java | 7 ++++++- .../notes/gtask/exception/NetworkFailureException.java | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java b/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java index 15504be..18e26af 100644 --- a/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java +++ b/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java @@ -16,18 +16,23 @@ package net.micode.notes.gtask.exception; +// ActionFailureException类用于表示任务操作失败的异常情况 public class ActionFailureException extends RuntimeException { + // 序列化ID,用于标识类的版本 private static final long serialVersionUID = 4425249765923293627L; + // 构造方法,无参数 public ActionFailureException() { super(); } + // 构造方法,带错误消息参数 public ActionFailureException(String paramString) { super(paramString); } + // 构造方法,带错误消息和异常原因参数 public ActionFailureException(String paramString, Throwable paramThrowable) { super(paramString, paramThrowable); } -} +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java b/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java index b08cfb1..73b8f84 100644 --- a/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java +++ b/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java @@ -16,18 +16,23 @@ package net.micode.notes.gtask.exception; +// NetworkFailureException类用于表示网络操作失败的异常情况 public class NetworkFailureException extends Exception { + // 序列化ID,用于标识类的版本 private static final long serialVersionUID = 2107610287180234136L; + // 构造方法,无参数 public NetworkFailureException() { super(); } + // 构造方法,带错误消息参数 public NetworkFailureException(String paramString) { super(paramString); } + // 构造方法,带错误消息和异常原因参数 public NetworkFailureException(String paramString, Throwable paramThrowable) { super(paramString, paramThrowable); } -} +} \ No newline at end of file From 2fda4731b59bd075174e0aec6eba3f9ebb54b233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E4=BF=8A=E5=BD=A6?= <1101703918@qq.com> Date: Thu, 15 May 2025 14:36:13 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B3=A8=E9=87=8Asrc/main/java/net/micode/?= =?UTF-8?q?notes/gtask/remote=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notes/gtask/remote/GTaskASyncTask.java | 40 +++--- .../notes/gtask/remote/GTaskClient.java | 80 ++++++------ .../notes/gtask/remote/GTaskManager.java | 115 ++++++++---------- .../notes/gtask/remote/GTaskSyncService.java | 22 +++- 4 files changed, 131 insertions(+), 126 deletions(-) diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java index 719f867..e393413 100644 --- a/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java +++ b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * @@ -28,23 +27,29 @@ import net.micode.notes.R; import net.micode.notes.ui.NotesListActivity; import net.micode.notes.ui.NotesPreferenceActivity; - public class GTaskASyncTask extends AsyncTask { + // 通知ID,用于同步任务的通知 private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; + // 定义任务完成后的回调接口 public interface OnCompleteListener { void onComplete(); } + // 上下文环境,用于访问应用程序资源 private Context mContext; + // 通知管理器,用于显示同步通知 private NotificationManager mNotifiManager; + // GTask管理器,用于处理任务同步 private GTaskManager mTaskManager; + // 任务完成后的回调监听器 private OnCompleteListener mOnCompleteListener; + // 构造方法,初始化任务所需的资源 public GTaskASyncTask(Context context, OnCompleteListener listener) { mContext = context; mOnCompleteListener = listener; @@ -53,35 +58,19 @@ public class GTaskASyncTask extends AsyncTask { mTaskManager = GTaskManager.getInstance(); } + // 取消同步操作 public void cancelSync() { mTaskManager.cancelSync(); } + // 发布进度信息 public void publishProgess(String message) { publishProgress(new String[] { - message + message }); } -// private void showNotification(int tickerId, String content) { -// Notification notification = new Notification(R.drawable.notification, mContext -// .getString(tickerId), System.currentTimeMillis()); -// notification.defaults = Notification.DEFAULT_LIGHTS; -// notification.flags = Notification.FLAG_AUTO_CANCEL; -// PendingIntent pendingIntent; -// if (tickerId != R.string.ticker_success) { -// pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, -// NotesPreferenceActivity.class), 0); -// -// } else { -// pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, -// NotesListActivity.class), 0); -// } -// notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content, -// pendingIntent); -// mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); -// } - + // 显示通知 private void showNotification(int tickerId, String content) { PendingIntent pendingIntent; if (tickerId != R.string.ticker_success) { @@ -98,10 +87,11 @@ public class GTaskASyncTask extends AsyncTask { .setContentIntent(pendingIntent) .setWhen(System.currentTimeMillis()) .setOngoing(true); - Notification notification=builder.getNotification(); + Notification notification = builder.getNotification(); mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); } + // 后台执行任务 @Override protected Integer doInBackground(Void... unused) { publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity @@ -109,6 +99,7 @@ public class GTaskASyncTask extends AsyncTask { return mTaskManager.sync(mContext, this); } + // 更新进度 @Override protected void onProgressUpdate(String... progress) { showNotification(R.string.ticker_syncing, progress[0]); @@ -117,6 +108,7 @@ public class GTaskASyncTask extends AsyncTask { } } + // 任务完成后执行的操作 @Override protected void onPostExecute(Integer result) { if (result == GTaskManager.STATE_SUCCESS) { @@ -140,4 +132,4 @@ public class GTaskASyncTask extends AsyncTask { }).start(); } } -} +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java b/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java index c67dfdf..d221cd6 100644 --- a/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java +++ b/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java @@ -44,7 +44,6 @@ import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; -import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.json.JSONArray; import org.json.JSONException; @@ -60,36 +59,50 @@ import java.util.zip.GZIPInputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; - public class GTaskClient { + // 日志标签,用于调试和日志记录 private static final String TAG = GTaskClient.class.getSimpleName(); + // Google Tasks 的基础URL private static final String GTASK_URL = "https://mail.google.com/tasks/"; + // Google Tasks 获取数据的URL private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig"; + // Google Tasks 提交数据的URL private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig"; + // 单例实例 private static GTaskClient mInstance = null; + // HTTP客户端,用于网络请求 private DefaultHttpClient mHttpClient; + // 获取数据的URL private String mGetUrl; + // 提交数据的URL private String mPostUrl; + // 客户端版本号 private long mClientVersion; + // 登录状态 private boolean mLoggedin; + // 最后登录时间 private long mLastLoginTime; + // 操作ID private int mActionId; + // 当前账户 private Account mAccount; + // 更新数组 private JSONArray mUpdateArray; + // 私有构造方法,用于单例模式 private GTaskClient() { mHttpClient = null; mGetUrl = GTASK_GET_URL; @@ -102,6 +115,7 @@ public class GTaskClient { mUpdateArray = null; } + // 获取单例实例 public static synchronized GTaskClient getInstance() { if (mInstance == null) { mInstance = new GTaskClient(); @@ -109,18 +123,18 @@ public class GTaskClient { return mInstance; } + // 登录Google账户 public boolean login(Activity activity) { - // we suppose that the cookie would expire after 5 minutes - // then we need to re-login + // 检查是否需要重新登录 final long interval = 1000 * 60 * 5; if (mLastLoginTime + interval < System.currentTimeMillis()) { mLoggedin = false; } - // need to re-login after account switch + // 检查账户是否切换 if (mLoggedin && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity - .getSyncAccountName(activity))) { + .getSyncAccountName(activity))) { mLoggedin = false; } @@ -136,7 +150,7 @@ public class GTaskClient { return false; } - // login with custom domain if necessary + // 登录自定义域名 if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase() .endsWith("googlemail.com"))) { StringBuilder url = new StringBuilder(GTASK_URL).append("a/"); @@ -151,7 +165,7 @@ public class GTaskClient { } } - // try to login with google official url + // 登录官方URL if (!mLoggedin) { mGetUrl = GTASK_GET_URL; mPostUrl = GTASK_POST_URL; @@ -164,6 +178,7 @@ public class GTaskClient { return true; } + // 登录Google账户并获取认证令牌 private String loginGoogleAccount(Activity activity, boolean invalidateToken) { String authToken; AccountManager accountManager = AccountManager.get(activity); @@ -189,7 +204,6 @@ public class GTaskClient { return null; } - // get the token now AccountManagerFuture accountManagerFuture = accountManager.getAuthToken(account, "goanna_mobile", null, activity, null, null); try { @@ -207,10 +221,10 @@ public class GTaskClient { return authToken; } + // 尝试登录Google Tasks private boolean tryToLoginGtask(Activity activity, String authToken) { if (!loginGtask(authToken)) { - // maybe the auth token is out of date, now let's invalidate the - // token and try again + // 如果认证令牌过期,重新获取并再次尝试登录 authToken = loginGoogleAccount(activity, true); if (authToken == null) { Log.e(TAG, "login google account failed"); @@ -225,6 +239,7 @@ public class GTaskClient { return true; } + // 登录Google Tasks private boolean loginGtask(String authToken) { int timeoutConnection = 10000; int timeoutSocket = 15000; @@ -236,14 +251,13 @@ public class GTaskClient { mHttpClient.setCookieStore(localBasicCookieStore); HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false); - // login gtask try { String loginUrl = mGetUrl + "?auth=" + authToken; HttpGet httpGet = new HttpGet(loginUrl); HttpResponse response = null; response = mHttpClient.execute(httpGet); - // get the cookie now + // 获取登录后的Cookie List cookies = mHttpClient.getCookieStore().getCookies(); boolean hasAuthCookie = false; for (Cookie cookie : cookies) { @@ -255,7 +269,7 @@ public class GTaskClient { Log.w(TAG, "it seems that there is no auth cookie"); } - // get the client version + // 获取客户端版本号 String resString = getResponseContent(response.getEntity()); String jsBegin = "_setup("; String jsEnd = ")}"; @@ -272,7 +286,6 @@ public class GTaskClient { e.printStackTrace(); return false; } catch (Exception e) { - // simply catch all exceptions Log.e(TAG, "httpget gtask_url failed"); return false; } @@ -280,10 +293,12 @@ public class GTaskClient { return true; } + // 获取操作ID private int getActionId() { return mActionId++; } + // 创建HTTP POST请求 private HttpPost createHttpPost() { HttpPost httpPost = new HttpPost(mPostUrl); httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); @@ -291,6 +306,7 @@ public class GTaskClient { return httpPost; } + // 获取HTTP响应内容 private String getResponseContent(HttpEntity entity) throws IOException { String contentEncoding = null; if (entity.getContentEncoding() != null) { @@ -323,6 +339,7 @@ public class GTaskClient { } } + // 发送POST请求 private JSONObject postRequest(JSONObject js) throws NetworkFailureException { if (!mLoggedin) { Log.e(TAG, "please login first"); @@ -336,7 +353,6 @@ public class GTaskClient { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); httpPost.setEntity(entity); - // execute the post HttpResponse response = mHttpClient.execute(httpPost); String jsString = getResponseContent(response.getEntity()); return new JSONObject(jsString); @@ -360,20 +376,18 @@ public class GTaskClient { } } + // 创建任务 public void createTask(Task task) throws NetworkFailureException { commitUpdate(); try { JSONObject jsPost = new JSONObject(); JSONArray actionList = new JSONArray(); - // action_list actionList.put(task.getCreateAction(getActionId())); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); - // client_version jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); - // post JSONObject jsResponse = postRequest(jsPost); JSONObject jsResult = (JSONObject) jsResponse.getJSONArray( GTaskStringUtils.GTASK_JSON_RESULTS).get(0); @@ -386,20 +400,18 @@ public class GTaskClient { } } + // 创建任务列表 public void createTaskList(TaskList tasklist) throws NetworkFailureException { commitUpdate(); try { JSONObject jsPost = new JSONObject(); JSONArray actionList = new JSONArray(); - // action_list actionList.put(tasklist.getCreateAction(getActionId())); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); - // client version jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); - // post JSONObject jsResponse = postRequest(jsPost); JSONObject jsResult = (JSONObject) jsResponse.getJSONArray( GTaskStringUtils.GTASK_JSON_RESULTS).get(0); @@ -412,15 +424,14 @@ public class GTaskClient { } } + // 提交更新 public void commitUpdate() throws NetworkFailureException { if (mUpdateArray != null) { try { JSONObject jsPost = new JSONObject(); - // action_list jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray); - // client_version jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); postRequest(jsPost); @@ -433,10 +444,9 @@ public class GTaskClient { } } + // 添加更新节点 public void addUpdateNode(Node node) throws NetworkFailureException { if (node != null) { - // too many update items may result in an error - // set max to 10 items if (mUpdateArray != null && mUpdateArray.length() > 10) { commitUpdate(); } @@ -447,6 +457,7 @@ public class GTaskClient { } } + // 移动任务 public void moveTask(Task task, TaskList preParent, TaskList curParent) throws NetworkFailureException { commitUpdate(); @@ -455,26 +466,21 @@ public class GTaskClient { JSONArray actionList = new JSONArray(); JSONObject action = new JSONObject(); - // action_list action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE); action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid()); if (preParent == curParent && task.getPriorSibling() != null) { - // put prioring_sibing_id only if moving within the tasklist and - // it is not the first one action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling()); } action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid()); action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); if (preParent != curParent) { - // put the dest_list only if moving between tasklists action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid()); } actionList.put(action); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); - // client_version jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); postRequest(jsPost); @@ -486,18 +492,17 @@ public class GTaskClient { } } + // 删除节点 public void deleteNode(Node node) throws NetworkFailureException { commitUpdate(); try { JSONObject jsPost = new JSONObject(); JSONArray actionList = new JSONArray(); - // action_list node.setDeleted(true); actionList.put(node.getUpdateAction(getActionId())); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); - // client_version jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); postRequest(jsPost); @@ -509,6 +514,7 @@ public class GTaskClient { } } + // 获取任务列表 public JSONArray getTaskLists() throws NetworkFailureException { if (!mLoggedin) { Log.e(TAG, "please login first"); @@ -520,7 +526,6 @@ public class GTaskClient { HttpResponse response = null; response = mHttpClient.execute(httpGet); - // get the task list String resString = getResponseContent(response.getEntity()); String jsBegin = "_setup("; String jsEnd = ")}"; @@ -547,6 +552,7 @@ public class GTaskClient { } } + // 获取任务列表中的任务 public JSONArray getTaskList(String listGid) throws NetworkFailureException { commitUpdate(); try { @@ -554,7 +560,6 @@ public class GTaskClient { JSONArray actionList = new JSONArray(); JSONObject action = new JSONObject(); - // action_list action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL); action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); @@ -563,7 +568,6 @@ public class GTaskClient { actionList.put(action); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); - // client_version jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); JSONObject jsResponse = postRequest(jsPost); @@ -575,11 +579,13 @@ public class GTaskClient { } } + // 获取同步账户 public Account getSyncAccount() { return mAccount; } + // 重置更新数组 public void resetUpdateArray() { mUpdateArray = null; } -} +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java b/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java index d2b4082..01410aa 100644 --- a/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java +++ b/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java @@ -47,46 +47,57 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; - 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; + // 当前活动的Activity private Activity mActivity; + // 上下文环境 private Context mContext; + // 内容解析器 private ContentResolver mContentResolver; + // 同步状态 private boolean mSyncing; + // 是否取消同步 private boolean mCancelled; + // GTask列表映射 private HashMap mGTaskListHashMap; + // GTask映射 private HashMap mGTaskHashMap; + // 元数据映射 private HashMap mMetaHashMap; + // 元数据列表 private TaskList mMetaList; + // 本地删除ID集合 private HashSet mLocalDeleteIdMap; + // GID到NID的映射 private HashMap mGidToNid; + // NID到GID的映射 private HashMap mNidToGid; + // 私有构造方法,用于单例模式 private GTaskManager() { mSyncing = false; mCancelled = false; @@ -99,6 +110,7 @@ public class GTaskManager { mNidToGid = new HashMap(); } + // 获取单例实例 public static synchronized GTaskManager getInstance() { if (mInstance == null) { mInstance = new GTaskManager(); @@ -106,11 +118,12 @@ public class GTaskManager { return mInstance; } + // 设置活动的Activity public synchronized void setActivityContext(Activity activity) { - // used for getting authtoken mActivity = activity; } + // 执行同步操作 public int sync(Context context, GTaskASyncTask asyncTask) { if (mSyncing) { Log.d(TAG, "Sync is in progress"); @@ -131,18 +144,18 @@ public class GTaskManager { GTaskClient client = GTaskClient.getInstance(); client.resetUpdateArray(); - // login google task + // 登录Google Tasks if (!mCancelled) { if (!client.login(mActivity)) { throw new NetworkFailureException("login google task failed"); } } - // get the task list from google + // 初始化GTask列表 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) { @@ -168,6 +181,7 @@ public class GTaskManager { return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; } + // 初始化GTask列表 private void initGTaskList() throws NetworkFailureException { if (mCancelled) return; @@ -175,7 +189,7 @@ public class GTaskManager { try { JSONArray jsTaskLists = client.getTaskLists(); - // init meta list first + // 初始化元数据列表 mMetaList = null; for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); @@ -187,7 +201,7 @@ public class GTaskManager { mMetaList = new TaskList(); mMetaList.setContentByRemoteJSON(object); - // load meta data + // 加载元数据 JSONArray jsMetas = client.getTaskList(gid); for (int j = 0; j < jsMetas.length(); j++) { object = (JSONObject) jsMetas.getJSONObject(j); @@ -203,7 +217,7 @@ public class GTaskManager { } } - // create meta list if not existed + // 创建元数据列表(如果不存在) if (mMetaList == null) { mMetaList = new TaskList(); mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX @@ -211,7 +225,7 @@ public class GTaskManager { GTaskClient.getInstance().createTaskList(mMetaList); } - // init task list + // 初始化任务列表 for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); @@ -219,13 +233,13 @@ public class GTaskManager { if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) && !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_META)) { + + GTaskStringUtils.FOLDERMETA)) { 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); @@ -247,6 +261,7 @@ public class GTaskManager { } } + // 执行内容同步 private void syncContent() throws NetworkFailureException { int syncType; Cursor c = null; @@ -259,7 +274,7 @@ public class GTaskManager { return; } - // for local deleted note + // 同步本地删除的便签 try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type<>? AND parent_id=?)", new String[] { @@ -286,10 +301,10 @@ public class GTaskManager { } } - // 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[] { @@ -306,10 +321,8 @@ public class GTaskManager { syncType = node.getSyncAction(c); } else { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // local add syncType = Node.SYNC_ACTION_ADD_REMOTE; } else { - // remote delete syncType = Node.SYNC_ACTION_DEL_LOCAL; } } @@ -326,7 +339,7 @@ public class GTaskManager { } } - // go through remaining items + // 同步剩余项目 Iterator> iter = mGTaskHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -334,23 +347,21 @@ public class GTaskManager { 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"); } } - // refresh local sync id + // 刷新本地同步ID if (!mCancelled) { GTaskClient.getInstance().commitUpdate(); refreshLocalSyncId(); } - } + // 同步文件夹 private void syncFolder() throws NetworkFailureException { Cursor c = null; String gid; @@ -361,7 +372,7 @@ public class GTaskManager { return; } - // for root folder + // 同步根文件夹 try { c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null); @@ -373,7 +384,6 @@ public class GTaskManager { mGTaskHashMap.remove(gid); mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER); mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid); - // for system folder, only update remote name if necessary if (!node.getName().equals( GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); @@ -390,11 +400,11 @@ public class GTaskManager { } } - // 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) + String.valueOf(Notes.ID_CALL_RECORD_FOLDER) }, null); if (c != null) { if (c.moveToNext()) { @@ -404,8 +414,6 @@ public class GTaskManager { 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)) @@ -424,7 +432,7 @@ public class GTaskManager { } } - // for local existing folders + // 同步本地现有文件夹 try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type=? AND parent_id<>?)", new String[] { @@ -441,10 +449,8 @@ public class GTaskManager { syncType = node.getSyncAction(c); } else { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // local add syncType = Node.SYNC_ACTION_ADD_REMOTE; } else { - // remote delete syncType = Node.SYNC_ACTION_DEL_LOCAL; } } @@ -460,7 +466,7 @@ public class GTaskManager { } } - // for remote add folders + // 同步远程添加的文件夹 Iterator> iter = mGTaskListHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -476,6 +482,7 @@ public class GTaskManager { GTaskClient.getInstance().commitUpdate(); } + // 执行内容同步操作 private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -510,18 +517,17 @@ public class GTaskManager { 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"); + throw new ActionFailureException("unknown sync action type"); } } + // 添加本地节点 private void addLocalNode(Node node) throws NetworkFailureException { if (mCancelled) { return; @@ -549,7 +555,6 @@ public class GTaskManager { if (note.has(NoteColumns.ID)) { long id = note.getLong(NoteColumns.ID); if (DataUtils.existInNoteDatabase(mContentResolver, id)) { - // the id is not available, have to create a new one note.remove(NoteColumns.ID); } } @@ -562,8 +567,6 @@ public class GTaskManager { if (data.has(DataColumns.ID)) { long dataId = data.getLong(DataColumns.ID); if (DataUtils.existInDataDatabase(mContentResolver, dataId)) { - // the data id is not available, have to create - // a new one data.remove(DataColumns.ID); } } @@ -584,26 +587,22 @@ public class GTaskManager { sqlNote.setParentId(parentId.longValue()); } - // create the local node sqlNote.setGtaskId(node.getGid()); sqlNote.commit(false); - // update gid-nid mapping mGidToNid.put(node.getGid(), sqlNote.getId()); mNidToGid.put(sqlNote.getId(), node.getGid()); - // update meta updateRemoteMeta(node.getGid(), sqlNote); } + // 更新本地节点 private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; } - SqlNote sqlNote; - // update the note locally - sqlNote = new SqlNote(mContext, c); + SqlNote sqlNote = new SqlNote(mContext, c); sqlNote.setContent(node.getLocalJSONFromContent()); Long parentId = (node instanceof Task) ? mGidToNid.get(((Task) node).getParent().getGid()) @@ -615,10 +614,10 @@ public class GTaskManager { sqlNote.setParentId(parentId.longValue()); sqlNote.commit(true); - // update meta info updateRemoteMeta(node.getGid(), sqlNote); } + // 添加远程节点 private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -627,7 +626,6 @@ public class GTaskManager { SqlNote sqlNote = new SqlNote(mContext, c); Node n; - // update remotely if (sqlNote.isNoteType()) { Task task = new Task(); task.setContentByLocalJSON(sqlNote.getContent()); @@ -642,12 +640,10 @@ public class GTaskManager { GTaskClient.getInstance().createTask(task); n = (Node) task; - // add meta updateRemoteMeta(task.getGid(), sqlNote); } else { 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) folderName += GTaskStringUtils.FOLDER_DEFAULT; @@ -671,7 +667,6 @@ public class GTaskManager { } } - // no match we can add now if (tasklist == null) { tasklist = new TaskList(); tasklist.setContentByLocalJSON(sqlNote.getContent()); @@ -681,17 +676,16 @@ public class GTaskManager { n = (Node) tasklist; } - // update local note sqlNote.setGtaskId(n.getGid()); sqlNote.commit(false); sqlNote.resetLocalModified(); sqlNote.commit(true); - // gid-id mapping mGidToNid.put(n.getGid(), sqlNote.getId()); mNidToGid.put(sqlNote.getId(), n.getGid()); } + // 更新远程节点 private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -699,14 +693,11 @@ public class GTaskManager { SqlNote sqlNote = new SqlNote(mContext, c); - // update remotely node.setContentByLocalJSON(sqlNote.getContent()); GTaskClient.getInstance().addUpdateNode(node); - // update meta updateRemoteMeta(node.getGid(), sqlNote); - // move task if necessary if (sqlNote.isNoteType()) { Task task = (Task) node; TaskList preParentList = task.getParent(); @@ -725,11 +716,11 @@ public class GTaskManager { } } - // clear local modified flag sqlNote.resetLocalModified(); sqlNote.commit(true); } + // 更新远程元数据 private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { if (sqlNote != null && sqlNote.isNoteType()) { MetaData metaData = mMetaHashMap.get(gid); @@ -746,12 +737,12 @@ public class GTaskManager { } } + // 刷新本地同步ID private void refreshLocalSyncId() throws NetworkFailureException { if (mCancelled) { return; } - // get the latest gtask list mGTaskHashMap.clear(); mGTaskListHashMap.clear(); mMetaHashMap.clear(); @@ -790,11 +781,13 @@ public class GTaskManager { } } + // 获取同步账户名称 public String getSyncAccount() { return GTaskClient.getInstance().getSyncAccount().name; } + // 取消同步 public void cancelSync() { mCancelled = true; } -} +} \ No newline at end of file diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java b/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java index cca36f7..673c290 100644 --- a/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java +++ b/src/main/java/net/micode/notes/gtask/remote/GTaskSyncService.java @@ -24,24 +24,28 @@ import android.os.Bundle; import android.os.IBinder; public class GTaskSyncService extends Service { + // 广播操作类型 public final static String ACTION_STRING_NAME = "sync_action_type"; + // 同步操作类型常量 public final static int ACTION_START_SYNC = 0; - public final static int ACTION_CANCEL_SYNC = 1; - 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_IS_SYNCING = "isSyncing"; - public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg"; + // 同步任务实例 private static GTaskASyncTask mSyncTask = null; + // 同步进度信息 private static String mSyncProgress = ""; + // 开始同步 private void startSync() { if (mSyncTask == null) { mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() { @@ -56,17 +60,20 @@ public class GTaskSyncService extends Service { } } + // 取消同步 private void cancelSync() { if (mSyncTask != null) { mSyncTask.cancelSync(); } } + // 服务创建时调用 @Override public void onCreate() { mSyncTask = null; } + // 处理启动命令 @Override public int onStartCommand(Intent intent, int flags, int startId) { Bundle bundle = intent.getExtras(); @@ -86,6 +93,7 @@ public class GTaskSyncService extends Service { return super.onStartCommand(intent, flags, startId); } + // 低内存时调用 @Override public void onLowMemory() { if (mSyncTask != null) { @@ -93,10 +101,12 @@ public class GTaskSyncService extends Service { } } + // 返回绑定的IBinder对象 public IBinder onBind(Intent intent) { return null; } + // 发送广播 public void sendBroadcast(String msg) { mSyncProgress = msg; Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); @@ -105,6 +115,7 @@ public class GTaskSyncService extends Service { sendBroadcast(intent); } + // 静态方法,用于启动同步 public static void startSync(Activity activity) { GTaskManager.getInstance().setActivityContext(activity); Intent intent = new Intent(activity, GTaskSyncService.class); @@ -112,17 +123,20 @@ public class GTaskSyncService extends Service { activity.startService(intent); } + // 静态方法,用于取消同步 public static void cancelSync(Context context) { Intent intent = new Intent(context, GTaskSyncService.class); intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC); context.startService(intent); } + // 静态方法,用于检查是否正在同步 public static boolean isSyncing() { return mSyncTask != null; } + // 静态方法,用于获取同步进度信息 public static String getProgressString() { return mSyncProgress; } -} +} \ No newline at end of file