diff --git a/src/net/micode/notes/tool/BackupUtils.java b/src/net/micode/notes/tool/BackupUtils.java index d76fff2..f98343e 100644 --- a/src/net/micode/notes/tool/BackupUtils.java +++ b/src/net/micode/notes/tool/BackupUtils.java @@ -243,4 +243,576 @@ public class BackupUtils { } String folderId = folderCursor.getString(NOTE_COLUMN_ID); exportFolderToText(folderId +package net.micode.notes.gtask.remote; // 定义当前类所在的包 + +import android.accounts.Account; // 引入账户类,表示一个用户账户 +import android.accounts.AccountManager; // 导入账户管理类,用于管理账户及其相关操作 +import android.accounts.AccountManagerFuture; // 导入异步获取账户的类 +import android.app.Activity; // 引入Activity类,代表应用的一个界面 +import android.os.Bundle; // 引入Bundle类,用于存储数据的容器 +import android.text.TextUtils; // 导入工具类,主要用于判断字符串是否为空 +import android.util.Log; // 导入Log类,用于记录日志 + +import net.micode.notes.gtask.data.Node; // 引入任务节点类 +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.GTaskStringUtils; // 引入字符串工具类,提供字符串相关的方法 +import net.micode.notes.ui.NotesPreferenceActivity; // 引入笔记偏好设置活动类 + +import org.apache.http.HttpEntity; // 引入HTTP实体类,表示请求或响应的消息体 +import org.apache.http.HttpResponse; // 引入HTTP响应类,表示HTTP请求的响应 +import org.apache.http.client.ClientProtocolException; // 引入客户端协议异常类 +import org.apache.http.client.entity.UrlEncodedFormEntity; // 引入URL编码的表单实体类 +import org.apache.http.client.methods.HttpGet; // 引入HTTP GET请求类 +import org.apache.http.client.methods.HttpPost; // 引入HTTP POST请求类 +import org.apache.http.cookie.Cookie; // 引入Cookie类,表示HTTP Cookie +import org.apache.http.impl.client.BasicCookieStore; // 引入基本的Cookie存储类 +import org.apache.http.impl.client.DefaultHttpClient; // 引入默认的HTTP客户端类 +import org.apache.http.message.BasicNameValuePair; // 引入基本名称值对类,用于表单参数 +import org.apache.http.params.BasicHttpParams; // 引入基本HTTP参数类 +import org.apache.http.params.HttpConnectionParams; // 引入HTTP连接参数类 +import org.apache.http.params.HttpParams; // 引入HTTP参数类 +import org.apache.http.params.HttpProtocolParams; // 引入HTTP协议参数类 +import org.json.JSONArray; // 引入JSON数组类 +import org.json.JSONException; // 引入JSON异常类 +import org.json.JSONObject; // 引入JSON对象类 + +import java.io.BufferedReader; // 引入缓冲读取器类 +import java.io.IOException; // 引入IO异常类 +import java.io.InputStream; // 引入输入流类 +import java.io.InputStreamReader; // 引入输入流阅读器类 +import java.util.LinkedList; // 引入链表类 +import java.util.List; // 引入列表接口 +import java.util.zip.GZIPInputStream; // 引入GZIP输入流类 +import java.util.zip.Inflater; // 引入解压缩类 +import java.util.zip.InflaterInputStream; // 引入解压缩输入流类 + +// GTaskClient类,负责与Google任务系统的网络交互 +public class GTaskClient { + private static final String TAG = GTaskClient.class.getSimpleName(); // 日志标记,用于日志记录 + + // Google任务相关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; // 单例实例 + + private DefaultHttpClient mHttpClient; // 默认HTTP客户端 + private String mGetUrl; // GET请求URL + private String mPostUrl; // POST请求URL + private long mClientVersion; // 客户端版本号 + private boolean mLoggedin; // 登录状态 + private long mLastLoginTime; // 上次登录时间 + private int mActionId; // 动作ID + private Account mAccount; // 当前账户信息 + private JSONArray mUpdateArray; // 更新操作数组 + + // 私有构造函数,初始化GTaskClient实例 + private GTaskClient() { + mHttpClient = null; + mGetUrl = GTASK_GET_URL; // 初始化GET请求URL + mPostUrl = GTASK_POST_URL; // 初始化POST请求URL + mClientVersion = -1; // 初始化客户端版本 + mLoggedin = false; // 初始化未登录状态 + mLastLoginTime = 0; // 初始化上次登录时间 + mActionId = 1; // 初始化动作ID + mAccount = null; // 初始化账户信息 + mUpdateArray = null; // 初始化更新数组 + } + + // 获取GTaskClient单例实例 + public static synchronized GTaskClient getInstance() { + if (mInstance == null) { + mInstance = new GTaskClient(); // 创建新实例 + } + return mInstance; // 返回单例实例 + } + + // 登录方法 + public boolean login(Activity activity) { + // 假设cookie在5分钟后过期,需要重新登录 + final long interval = 1000 * 60 * 5; + if (mLastLoginTime + interval < System.currentTimeMillis()) { + mLoggedin = false; // 登录过期 + } + + // 当账户切换时需要重新登录 + if (mLoggedin && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity.getSyncAccountName(activity))) { + mLoggedin = false; // 切换账户后未登录 + } + + if (mLoggedin) { + Log.d(TAG, "already logged in"); // 已经登录 + return true; // 返回登录成功 + } + + mLastLoginTime = System.currentTimeMillis(); // 更新最后登录时间 + String authToken = loginGoogleAccount(activity, false); // 登录Google账户 + if (authToken == null) { + Log.e(TAG, "login google account failed"); // 登录失败 + return false; // 返回登录失败 + } + + // 登录自定义域名 + if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase().endsWith("googlemail.com"))) { + // 构建URL + StringBuilder url = new StringBuilder(GTASK_URL).append("a/"); + int index = mAccount.name.indexOf('@') + 1; + String suffix = mAccount.name.substring(index); + url.append(suffix + "/"); + mGetUrl = url.toString() + "ig"; // 更新GET请求URL + mPostUrl = url.toString() + "r/ig"; // 更新POST请求URL + + // 尝试以自定义域名登录 + if (tryToLoginGtask(activity, authToken)) { + mLoggedin = true; // 登录成功 + } + } + + // 尝试使用Google官方URL登录 + if (!mLoggedin) { + mGetUrl = GTASK_GET_URL; // 恢复默认GET请求URL + mPostUrl = GTASK_POST_URL; // 恢复默认POST请求URL + if (!tryToLoginGtask(activity, authToken)) { // 尝试登录 + return false; // 登录失败 + } + } + + mLoggedin = true; // 登录状态更新 + return true; // 返回登录成功 + } + + // 登录Google账户 + private String loginGoogleAccount(Activity activity, boolean invalidateToken) { + String authToken; // 认证令牌 + AccountManager accountManager = AccountManager.get(activity); // 获取账户管理器 + Account[] accounts = accountManager.getAccountsByType("com.google"); // 获取Google账户 + + if (accounts.length == 0) { + Log.e(TAG, "there is no available google account"); // 没有可用的Google账户 + return null; // 返回null + } + + String accountName = NotesPreferenceActivity.getSyncAccountName(activity); // 获取预设的账户名 + Account account = null; + for (Account a : accounts) { + if (a.name.equals(accountName)) { // 查找匹配的账户 + account = a; + break; + } + } + if (account != null) { + mAccount = account; // 设置当前账户 + } else { + Log.e(TAG, "unable to get an account with the same name in the settings"); // 未找到匹配的账户 + return null; // 返回null + } + + // 现在获取token + AccountManagerFuture accountManagerFuture = accountManager.getAuthToken(account, "goanna_mobile", null, activity, null, null); // 获取账户的认证令牌 + try { + Bundle authTokenBundle = accountManagerFuture.getResult(); // 获取结果 + authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN); // 提取认证令牌 + if (invalidateToken) { + accountManager.invalidateAuthToken("com.google", authToken); // 使令牌失效 + loginGoogleAccount(activity, false); // 重新登录 + } + } catch (Exception e) { + Log.e(TAG, "get auth token failed"); // 获取令牌失败 + authToken = null; // 令牌为null + } + + return authToken; // 返回认证令牌 + } + + // 尝试登录GTask + private boolean tryToLoginGtask(Activity activity, String authToken) { + if (!loginGtask(authToken)) { // 登录GTask + // 可能认证令牌过期,令牌失效后重试 + authToken = loginGoogleAccount(activity, true); // 重新获取令牌 + if (authToken == null) { + Log.e(TAG, "login google account failed"); // 登录失败 + return false; // 返回失败 + } + + if (!loginGtask(authToken)) { // 重试登录GTask + Log.e(TAG, "login gtask failed"); // 登录GTask失败 + return false; // 返回失败 + } + } + return true; // 登录成功 + } + + // 登录GTask + private boolean loginGtask(String authToken) { + int timeoutConnection = 10000; // 连接超时设置 + int timeoutSocket = 15000; // 套接字超时设置 + HttpParams httpParameters = new BasicHttpParams(); // 创建HTTP参数 + HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); // 设置连接超时 + HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); // 设置套接字超时 + mHttpClient = new DefaultHttpClient(httpParameters); // 初始化HTTP客户端 + BasicCookieStore localBasicCookieStore = new BasicCookieStore(); // 初始化Cookie存储 + mHttpClient.setCookieStore(localBasicCookieStore); // 设置Cookie存储 + HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false); // 禁用ExpectContinue + + // 登录GTask + try { + String loginUrl = mGetUrl + "?auth=" + authToken; // 构建登录URL + HttpGet httpGet = new HttpGet(loginUrl); // 创建GET请求 + HttpResponse response = null; + response = mHttpClient.execute(httpGet); // 执行GET请求 + + // 获取Cookie + List cookies = mHttpClient.getCookieStore().getCookies(); // 获取当前Cookie + boolean hasAuthCookie = false; + for (Cookie cookie : cookies) { + if (cookie.getName().contains("GTL")) { // 检查是否存在授权Cookie + hasAuthCookie = true; + } + } + if (!hasAuthCookie) { + Log.w(TAG, "it seems that there is no auth cookie"); // 授权Cookie不存在 + } + + // 获取客户端版本 + String resString = getResponseContent(response.getEntity()); // 获取响应内容 + String jsBegin = "_setup("; // JavaScript开始标识 + String jsEnd = ")}"; // JavaScript结束标识 + int begin = resString.indexOf(jsBegin); // 查找开始索引 + int end = resString.lastIndexOf(jsEnd); // 查找结束索引 + String jsString = null; + if (begin != -1 && end != -1 && begin < end) { // 提取JavaScript内容 + jsString = resString.substring(begin + jsBegin.length(), end); + } + JSONObject js = new JSONObject(jsString); // 创建JSON对象 + mClientVersion = js.getLong("v"); // 获取客户端版本 + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON解析异常 + e.printStackTrace(); // 打印异常堆栈 + return false; // 返回失败 + } catch (Exception e) { + // 捕获所有异常 + Log.e(TAG, "httpget gtask_url failed"); // GET请求失败 + return false; // 返回失败 + } + + return true; // 登录成功 + } + + // 获取下一个动作ID + private int getActionId() { + return mActionId++; // 返回并自增动作ID + } + + // 创建HTTP POST请求 + private HttpPost createHttpPost() { + HttpPost httpPost = new HttpPost(mPostUrl); // 创建POST请求 + httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); // 设置请求头 + httpPost.setHeader("AT", "1"); // 设置自定义请求头 + return httpPost; // 返回POST请求 + } + + // 获取响应内容 + private String getResponseContent(HttpEntity entity) throws IOException { + String contentEncoding = null; // 内容编码 + if (entity.getContentEncoding() != null) { + contentEncoding = entity.getContentEncoding().getValue(); // 获取编码类型 + Log.d(TAG, "encoding: " + contentEncoding); // 记录编码类型 + } + + InputStream input = entity.getContent(); // 获取输入流 + if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) { + input = new GZIPInputStream(entity.getContent()); // 解压GZIP流 + } else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) { + Inflater inflater = new Inflater(true); // 创建Inflater对象 + input = new InflaterInputStream(entity.getContent(), inflater); // 解压DEFLATE流 + } + + try { + InputStreamReader isr = new InputStreamReader(input); // 创建输入流阅读器 + BufferedReader br = new BufferedReader(isr); // 创建缓冲读取器 + StringBuilder sb = new StringBuilder(); // 创建字符串构建器 + + while (true) { + String buff = br.readLine(); // 逐行读取 + if (buff == null) { + return sb.toString(); // 返回读取的内容 + } + sb = sb.append(buff); // 将内容添加到构建器 + } + } finally { + input.close(); // 关闭输入流 + } + } + + // POST请求方法 + private JSONObject postRequest(JSONObject js) throws NetworkFailureException { + if (!mLoggedin) { + Log.e(TAG, "please login first"); // 未登录 + throw new ActionFailureException("not logged in"); // 抛出异常 + } + + HttpPost httpPost = createHttpPost(); // 创建POST请求 + try { + LinkedList list = new LinkedList(); // 创建参数列表 + list.add(new BasicNameValuePair("r", js.toString())); // 添加请求参数 + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); // 创建表单实体 + httpPost.setEntity(entity); // 设置POST实体 + + // 执行POST请求 + HttpResponse response = mHttpClient.execute(httpPost); + String jsString = getResponseContent(response.getEntity()); // 获取响应内容 + return new JSONObject(jsString); // 返回JSON对象 + + } catch (ClientProtocolException e) { + Log.e(TAG, e.toString()); // 记录协议异常 + e.printStackTrace(); // 打印异常堆栈 + throw new NetworkFailureException("postRequest failed"); // 抛出网络失败异常 + } catch (IOException e) { + Log.e(TAG, e.toString()); // 记录IO异常 + e.printStackTrace(); // 打印异常堆栈 + throw new NetworkFailureException("postRequest failed"); // 抛出网络失败异常 + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("unable to convert response content to jsonobject"); // 抛出操作失败异常 + } catch (Exception e) { + Log.e(TAG, e.toString()); // 记录其他异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("error occurs when posting request"); // 抛出操作失败异常 + } + } + + // 创建任务方法 + public void createTask(Task task) throws NetworkFailureException { + commitUpdate(); // 提交更新 + try { + JSONObject jsPost = new JSONObject(); // 创建JSON对象 + JSONArray actionList = new JSONArray(); // 创建动作列表数组 + + // 添加创建动作到动作列表 + actionList.put(task.getCreateAction(getActionId())); // 获取创建动作并添加 + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 设置动作列表 + + // 设置客户端版本 + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + // 执行POST请求 + JSONObject jsResponse = postRequest(jsPost); + JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_RESULTS).get(0); // 获取结果 + task.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID)); // 设置任务ID + + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("create task: handing jsonobject failed"); // 抛出操作失败异常 + } + } + + // 创建任务列表方法 + public void createTaskList(TaskList tasklist) throws NetworkFailureException { + commitUpdate(); // 提交更新 + try { + JSONObject jsPost = new JSONObject(); // 创建JSON对象 + JSONArray actionList = new JSONArray(); // 创建动作列表数组 + + // 添加创建动作到动作列表 + actionList.put(tasklist.getCreateAction(getActionId())); // 获取创建动作并添加 + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 设置动作列表 + + // 设置客户端版本 + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + // 执行POST请求 + JSONObject jsResponse = postRequest(jsPost); + JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_RESULTS).get(0); // 获取结果 + tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID)); // 设置任务列表ID + + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("create tasklist: handing jsonobject failed"); // 抛出操作失败异常 + } + } + + // 提交更新方法 + public void commitUpdate() throws NetworkFailureException { + if (mUpdateArray != null) { // 如果有更新数组 + try { + JSONObject jsPost = new JSONObject(); // 创建JSON对象 + + // 设置动作列表 + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray); + + // 设置客户端版本 + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + postRequest(jsPost); // 执行POST请求 + mUpdateArray = null; // 清空更新数组 + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("commit update: handing jsonobject failed"); // 抛出操作失败异常 + } + } + } + + // 添加更新节点方法 + public void addUpdateNode(Node node) throws NetworkFailureException { + if (node != null) { // 如果节点不为空 + // 更新项目数量过多可能会导致错误,设置最大为10个 + if (mUpdateArray != null && mUpdateArray.length() > 10) { + commitUpdate(); // 提交更新 + } + + if (mUpdateArray == null) // 如果更新数组为空 + mUpdateArray = new JSONArray(); // 初始化更新数组 + mUpdateArray.put(node.getUpdateAction(getActionId())); // 添加更新操作到数组 + } + } + + // 移动任务方法 + public void moveTask(Task task, TaskList preParent, TaskList curParent) throws NetworkFailureException { + commitUpdate(); // 提交更新 + try { + JSONObject jsPost = new JSONObject(); // 创建JSON对象 + JSONArray actionList = new JSONArray(); // 创建动作列表 + JSONObject action = new JSONObject(); // 创建动作对象 + + // 设置移动任务的动作 + action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE); + action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); // 设置动作ID + action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid()); // 设置任务ID + if (preParent == curParent && task.getPriorSibling() != null) { + // 仅当在任务列表内移动且不是第一个时,设置前一个兄弟节点ID + action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling()); + } + action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid()); // 设置源列表ID + action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); // 设置目标父任务列表ID + if (preParent != curParent) { + // 仅当在不同任务列表间移动时,设置目标列表ID + action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid()); + } + actionList.put(action); // 将动作添加到动作列表 + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 设置动作列表 + + // 设置客户端版本 + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + postRequest(jsPost); // 执行POST请求 + + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("move task: handing jsonobject failed"); // 抛出操作失败异常 + } + } + + // 删除节点方法 + public void deleteNode(Node node) throws NetworkFailureException { + commitUpdate(); // 提交更新 + try { + JSONObject jsPost = new JSONObject(); // 创建JSON对象 + JSONArray actionList = new JSONArray(); // 创建动作列表 + + // 删除节点 + node.setDeleted(true); // 设置节点为已删除 + actionList.put(node.getUpdateAction(getActionId())); // 添加更新动作到列表 + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 设置动作列表 + + // 设置客户端版本 + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + postRequest(jsPost); // 执行POST请求 + mUpdateArray = null; // 清空更新数组 + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("delete node: handing jsonobject failed"); // 抛出操作失败异常 + } + } + + + // 获取任务列表的方法 + public JSONArray getTaskLists() throws NetworkFailureException { + // 检查是否已登录 + if (!mLoggedin) { + Log.e(TAG, "please login first"); // 记录错误日志 + throw new ActionFailureException("not logged in"); // 抛出未登录异常 + } + + try { + HttpGet httpGet = new HttpGet(mGetUrl); // 创建GET请求 + HttpResponse response = null; // 声明响应对象 + response = mHttpClient.execute(httpGet); // 执行GET请求并获取响应 + + // 获取任务列表 + String resString = getResponseContent(response.getEntity()); // 读取响应内容 + String jsBegin = "_setup("; // JS数据开始标识 + String jsEnd = ")}"; // JS数据结束标识 + int begin = resString.indexOf(jsBegin); // 查找开始索引 + int end = resString.lastIndexOf(jsEnd); // 查找结束索引 + String jsString = null; // 存储提取的JS字符串 + if (begin != -1 && end != -1 && begin < end) { // 检查索引有效性 + jsString = resString.substring(begin + jsBegin.length(), end); // 提取JS字符串 + } + JSONObject js = new JSONObject(jsString); // 创建JSON对象 + // 返回任务列表的JSONArray + return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS); + } catch (ClientProtocolException e) { + Log.e(TAG, e.toString()); // 记录协议异常 + e.printStackTrace(); // 打印异常堆栈 + throw new NetworkFailureException("gettasklists: httpget failed"); // 抛出网络失败异常 + } catch (IOException e) { + Log.e(TAG, e.toString()); // 记录IO异常 + e.printStackTrace(); // 打印异常堆栈 + throw new NetworkFailureException("gettasklists: httpget failed"); // 抛出网络失败异常 + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("get task lists: handing jasonobject failed"); // 抛出操作失败异常 + } + } + + // 获取指定任务列表的任务方法 + public JSONArray getTaskList(String listGid) throws NetworkFailureException { + commitUpdate(); // 提交更新操作 + try { + JSONObject jsPost = new JSONObject(); // 创建JSON对象 + JSONArray actionList = new JSONArray(); // 创建动作列表 + JSONObject action = new JSONObject(); // 创建单个动作对象 + + // 设置动作列表 + action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL); // 动作类型为获取所有任务 + action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); // 设置动作ID + action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid); // 设置任务列表ID + action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false); // 不获取已删除的任务 + actionList.put(action); // 将动作添加到动作列表 + jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 设置动作列表到JSON对象 + + // 设置客户端版本 + jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); + + JSONObject jsResponse = postRequest(jsPost); // 执行POST请求并获取响应 + return jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_TASKS); // 返回任务数组 + } catch (JSONException e) { + Log.e(TAG, e.toString()); // 记录JSON异常 + e.printStackTrace(); // 打印异常堆栈 + throw new ActionFailureException("get task list: handing jsonobject failed"); // 抛出操作失败异常 + } + } + + // 获取当前同步账户的方法 + public Account getSyncAccount() { + return mAccount; // 返回当前账户信息 + } + + // 重置更新数组的方法 + public void resetUpdateArray() { + mUpdateArray = null; // 将更新数组设置为null + } +}