diff --git a/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java b/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java index c67dfdf..8aea56c 100644 --- a/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java +++ b/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java @@ -61,35 +61,30 @@ import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; +// GTask客户端类,负责与Google Tasks服务通信 public class GTaskClient { private static final String TAG = GTaskClient.class.getSimpleName(); + // GTask服务的基本URL private static final String GTASK_URL = "https://mail.google.com/tasks/"; - private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig"; - private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig"; + // 单例实例 private static GTaskClient mInstance = null; + // HTTP客户端和请求相关变量 private DefaultHttpClient mHttpClient; - private String mGetUrl; - private String mPostUrl; - private long mClientVersion; - private boolean mLoggedin; - private long mLastLoginTime; - private int mActionId; - private Account mAccount; - private JSONArray mUpdateArray; + // 私有构造方法,实现单例模式 private GTaskClient() { mHttpClient = null; mGetUrl = GTASK_GET_URL; @@ -102,6 +97,7 @@ public class GTaskClient { mUpdateArray = null; } + // 获取单例实例的方法 public static synchronized GTaskClient getInstance() { if (mInstance == null) { mInstance = new GTaskClient(); @@ -109,18 +105,17 @@ public class GTaskClient { return mInstance; } + // 登录Google账户并获取GTask访问权限 public boolean login(Activity activity) { - // we suppose that the cookie would expire after 5 minutes - // then we need to re-login + // 设定登录有效期为5分钟 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))) { + // 账户切换后需要重新登录 + if (mLoggedin && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity + .getSyncAccountName(activity))) { mLoggedin = false; } @@ -136,7 +131,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 +146,7 @@ public class GTaskClient { } } - // try to login with google official url + // 尝试使用Google官方URL登录 if (!mLoggedin) { mGetUrl = GTASK_GET_URL; mPostUrl = GTASK_POST_URL; @@ -164,6 +159,7 @@ public class GTaskClient { return true; } + // 登录Google账户获取认证令牌 private String loginGoogleAccount(Activity activity, boolean invalidateToken) { String authToken; AccountManager accountManager = AccountManager.get(activity); @@ -174,6 +170,7 @@ public class GTaskClient { return null; } + // 获取设置中的同步账户 String accountName = NotesPreferenceActivity.getSyncAccountName(activity); Account account = null; for (Account a : accounts) { @@ -189,7 +186,7 @@ public class GTaskClient { return null; } - // get the token now + // 获取认证令牌 AccountManagerFuture accountManagerFuture = accountManager.getAuthToken(account, "goanna_mobile", null, activity, null, null); try { @@ -207,10 +204,10 @@ public class GTaskClient { return authToken; } + // 尝试登录GTask服务 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 +222,7 @@ public class GTaskClient { return true; } + // 使用认证令牌登录GTask private boolean loginGtask(String authToken) { int timeoutConnection = 10000; int timeoutSocket = 15000; @@ -236,14 +234,14 @@ public class GTaskClient { mHttpClient.setCookieStore(localBasicCookieStore); HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false); - // login gtask try { + // 构造登录URL 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 +253,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 +270,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 +277,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 +290,7 @@ public class GTaskClient { return httpPost; } + // 从HTTP响应中获取内容 private String getResponseContent(HttpEntity entity) throws IOException { String contentEncoding = null; if (entity.getContentEncoding() != null) { @@ -298,6 +298,7 @@ public class GTaskClient { Log.d(TAG, "encoding: " + contentEncoding); } + // 处理压缩的响应内容 InputStream input = entity.getContent(); if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) { input = new GZIPInputStream(entity.getContent()); @@ -311,6 +312,7 @@ public class GTaskClient { BufferedReader br = new BufferedReader(isr); StringBuilder sb = new StringBuilder(); + // 读取响应内容 while (true) { String buff = br.readLine(); if (buff == null) { @@ -323,6 +325,7 @@ public class GTaskClient { } } + // 发送POST请求并获取JSON响应 private JSONObject postRequest(JSONObject js) throws NetworkFailureException { if (!mLoggedin) { Log.e(TAG, "please login first"); @@ -331,12 +334,13 @@ public class GTaskClient { HttpPost httpPost = createHttpPost(); try { + // 构造请求参数 LinkedList list = new LinkedList(); list.add(new BasicNameValuePair("r", js.toString())); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); httpPost.setEntity(entity); - // execute the post + // 执行POST请求并处理响应 HttpResponse response = mHttpClient.execute(httpPost); String jsString = getResponseContent(response.getEntity()); return new JSONObject(jsString); @@ -360,20 +364,21 @@ public class GTaskClient { } } + // 创建新任务并发送到GTask服务 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 +391,21 @@ public class GTaskClient { } } + // 创建新任务列表并发送到GTask服务 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 +418,16 @@ public class GTaskClient { } } + // 提交更新操作到GTask服务 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 +440,10 @@ 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 + // 限制更新队列大小为10个项目 if (mUpdateArray != null && mUpdateArray.length() > 10) { commitUpdate(); } @@ -447,6 +454,7 @@ public class GTaskClient { } } + // 移动任务到不同的任务列表 public void moveTask(Task task, TaskList preParent, TaskList curParent) throws NetworkFailureException { commitUpdate(); @@ -455,26 +463,28 @@ 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()); + + // 根据情况设置前一个兄弟任务ID 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 +496,19 @@ 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 +520,7 @@ public class GTaskClient { } } + // 获取所有任务列表 public JSONArray getTaskLists() throws NetworkFailureException { if (!mLoggedin) { Log.e(TAG, "please login first"); @@ -516,11 +528,12 @@ public class GTaskClient { } try { + // 发送GET请求获取任务列表 HttpGet httpGet = new HttpGet(mGetUrl); HttpResponse response = null; response = mHttpClient.execute(httpGet); - // get the task list + // 解析响应获取任务列表数据 String resString = getResponseContent(response.getEntity()); String jsBegin = "_setup("; String jsEnd = ")}"; @@ -547,6 +560,7 @@ public class GTaskClient { } } + // 获取指定任务列表中的所有任务 public JSONArray getTaskList(String listGid) throws NetworkFailureException { commitUpdate(); try { @@ -554,7 +568,7 @@ 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 +577,7 @@ 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 +589,13 @@ public class GTaskClient { } } + // 获取当前同步账户 public Account getSyncAccount() { return mAccount; } + // 重置更新数组 public void resetUpdateArray() { mUpdateArray = null; } -} +} \ No newline at end of file