|
|
/*
|
|
|
* 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.
|
|
|
*/
|
|
|
|
|
|
package net.micode.notes.gtask.remote;
|
|
|
|
|
|
import android.accounts.Account;
|
|
|
import android.accounts.AccountManager;
|
|
|
import android.accounts.AccountManagerFuture;
|
|
|
import android.app.Activity;
|
|
|
import android.os.Bundle;
|
|
|
import android.text.TextUtils;
|
|
|
import android.util.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;
|
|
|
import org.apache.http.HttpResponse;
|
|
|
import org.apache.http.client.ClientProtocolException;
|
|
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
|
|
import org.apache.http.client.methods.HttpGet;
|
|
|
import org.apache.http.client.methods.HttpPost;
|
|
|
import org.apache.http.cookie.Cookie;
|
|
|
import org.apache.http.impl.client.BasicCookieStore;
|
|
|
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;
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.util.LinkedList;
|
|
|
import java.util.List;
|
|
|
import java.util.zip.GZIPInputStream;
|
|
|
import java.util.zip.Inflater;
|
|
|
import java.util.zip.InflaterInputStream;
|
|
|
|
|
|
// GTaskClient类用于与Google Tasks服务进行交互,实现诸如登录、创建任务、创建任务列表、更新操作、获取任务列表等功能,
|
|
|
// 内部通过HttpClient等相关类来发送HTTP请求与服务端通信,并且处理了诸如网络异常、JSON解析异常等多种情况,同时还管理登录状态、客户端版本等信息。
|
|
|
public class GTaskClient {
|
|
|
// 用于在日志输出中标识该类的标签,取类的简单名称,方便在日志里区分该类相关的记录
|
|
|
private static final String TAG = GTaskClient.class.getSimpleName();
|
|
|
// Google Tasks服务的基础URL,用于后续构建具体的请求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";
|
|
|
|
|
|
// 单例模式下的唯一实例对象,初始化为null,通过静态方法getInstance获取实例,确保整个应用中只有一个GTaskClient实例在运行。
|
|
|
private static GTaskClient mInstance = null;
|
|
|
// 用于发送HTTP请求的HttpClient对象,负责实际的网络通信,初始化为null,在需要进行网络请求时进行初始化和相关配置。
|
|
|
private DefaultHttpClient mHttpClient;
|
|
|
// 用于获取数据的具体URL,初始化为GTASK_GET_URL,可根据不同情况(如登录自定义域名等)进行修改,指向实际获取数据的地址。
|
|
|
private String mGetUrl;
|
|
|
// 用于提交数据的具体URL,初始化为GTASK_POST_URL,可根据情况调整,指向实际提交数据的地址。
|
|
|
private String mPostUrl;
|
|
|
// 记录客户端的版本号,初始化为 -1,在登录成功等操作后从服务端获取并更新,用于与服务端交互时标识客户端版本情况。
|
|
|
private long mClientVersion;
|
|
|
// 标记当前是否已登录到Google Tasks服务,初始化为false,在登录成功后设置为true,后续操作根据此标记判断是否需要先登录。
|
|
|
private boolean mLoggedin;
|
|
|
// 记录上次登录的时间戳,初始化为0,用于判断是否需要重新登录(例如根据设定的时间间隔判断),单位通常为毫秒。
|
|
|
private long mLastLoginTime;
|
|
|
// 用于为每个操作生成唯一的动作标识符,每次获取后自增1,确保不同操作有不同的标识,方便服务端区分和处理。
|
|
|
private int mActionId;
|
|
|
// 存储当前登录的账户信息(Account类型),代表与Google Tasks服务交互所使用的账号,在登录过程中进行赋值。
|
|
|
private Account mAccount;
|
|
|
// 用于暂存需要更新的节点(Node类型)相关操作的JSON数组,比如任务、任务列表的更新操作等,批量处理更新时使用,初始化为null。
|
|
|
private JSONArray mUpdateArray;
|
|
|
|
|
|
// 私有构造函数,用于初始化GTaskClient对象的各个成员变量,按照默认值进行初始化,保证单例模式下实例的初始化状态统一。
|
|
|
private GTaskClient() {
|
|
|
mHttpClient = null;
|
|
|
mGetUrl = GTASK_GET_URL;
|
|
|
mPostUrl = GTASK_POST_URL;
|
|
|
mClientVersion = -1;
|
|
|
mLoggedin = false;
|
|
|
mLastLoginTime = 0;
|
|
|
mActionId = 1;
|
|
|
mAccount = null;
|
|
|
mUpdateArray = null;
|
|
|
}
|
|
|
|
|
|
// 静态方法,采用双重检查锁定(Double-Checked Locking)的方式实现单例模式,确保多线程环境下能正确获取唯一的GTaskClient实例。
|
|
|
public static synchronized GTaskClient getInstance() {
|
|
|
if (mInstance == null) {
|
|
|
mInstance = new GTaskClient();
|
|
|
}
|
|
|
return mInstance;
|
|
|
}
|
|
|
|
|
|
// 登录到Google Tasks服务的方法,根据一定的条件判断是否需要重新登录(如时间间隔超过设定值、账号切换等),
|
|
|
// 如果已登录则直接返回true,否则尝试进行登录操作,包括获取Google账户认证令牌、根据账户域名情况尝试不同的登录URL等步骤,登录成功返回true,失败返回false。
|
|
|
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();
|
|
|
// 尝试获取Google账户的认证令牌,用于后续登录Google Tasks服务,如果获取失败则返回false
|
|
|
String authToken = loginGoogleAccount(activity, false);
|
|
|
if (authToken == null) {
|
|
|
Log.e(TAG, "login google account failed");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// 如果账户名不是以"gmail.com"或"googlemail.com"结尾,说明可能是自定义域名账户,需要构建自定义域名的登录URL
|
|
|
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
|
|
|
.endsWith("googlemail.com"))) {
|
|
|
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";
|
|
|
mPostUrl = url.toString() + "r/ig";
|
|
|
|
|
|
// 使用自定义域名的URL尝试登录Google Tasks服务,如果成功则标记为已登录
|
|
|
if (tryToLoginGtask(activity, authToken)) {
|
|
|
mLoggedin = true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 如果使用自定义域名登录失败或者本身就是普通账户,使用默认的Google官方URL再次尝试登录
|
|
|
if (!mLoggedin) {
|
|
|
mGetUrl = GTASK_GET_URL;
|
|
|
mPostUrl = GTASK_POST_URL;
|
|
|
if (!tryToLoginGtask(activity, authToken)) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
mLoggedin = true;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 从Android系统账户管理器中获取Google账户的认证令牌的方法,首先获取所有的Google类型账户,
|
|
|
// 然后根据设置中指定的同步账户名称找到对应的账户,再通过账户管理器获取认证令牌,如果获取过程出现异常则返回null。
|
|
|
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
|
|
|
String authToken;
|
|
|
AccountManager accountManager = AccountManager.get(activity);
|
|
|
Account[] accounts = accountManager.getAccountsByType("com.google");
|
|
|
|
|
|
if (accounts.length == 0) {
|
|
|
Log.e(TAG, "there is no available google account");
|
|
|
return 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
|
|
|
AccountManagerFuture<Bundle> 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;
|
|
|
}
|
|
|
|
|
|
return authToken;
|
|
|
}
|
|
|
|
|
|
// 尝试使用给定的认证令牌登录Google Tasks服务的方法,如果登录失败,可能是令牌过期,会尝试先使令牌失效再重新获取并登录,
|
|
|
// 只有两次尝试都失败才返回false,表示登录Google Tasks服务最终失败。
|
|
|
private boolean tryToLoginGtask(Activity activity, String authToken) {
|
|
|
if (!loginGtask(authToken)) {
|
|
|
// 可能认证令牌已过期,先使令牌失效,然后重新获取令牌并再次尝试登录
|
|
|
authToken = loginGoogleAccount(activity, true);
|
|
|
if (authToken == null) {
|
|
|
Log.e(TAG, "login google account failed");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
if (!loginGtask(authToken)) {
|
|
|
Log.e(TAG, "login gtask failed");
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 使用给定的认证令牌实际登录Google Tasks服务的方法,配置HttpClient的连接超时、读取超时等参数,设置Cookie存储等,
|
|
|
// 发送HTTP GET请求到登录URL,获取登录后的Cookie和客户端版本号等信息,如果过程中出现JSON解析异常、网络请求异常等情况则返回false,表示登录失败。
|
|
|
private boolean loginGtask(String authToken) {
|
|
|
int timeoutConnection = 10000;
|
|
|
int timeoutSocket = 15000;
|
|
|
HttpParams httpParameters = new BasicHttpParams();
|
|
|
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
|
|
|
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
|
|
|
mHttpClient = new DefaultHttpClient(httpParameters);
|
|
|
BasicCookieStore localBasicCookieStore = new BasicCookieStore();
|
|
|
mHttpClient.setCookieStore(localBasicCookieStore);
|
|
|
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false);
|
|
|
|
|
|
// 构建登录的URL,带上认证令牌参数
|
|
|
try {
|
|
|
String loginUrl = mGetUrl + "?auth=" + authToken;
|
|
|
HttpGet httpGet = new HttpGet(loginUrl);
|
|
|
HttpResponse response = null;
|
|
|
response = mHttpClient.execute(httpGet);
|
|
|
|
|
|
// 获取登录后的Cookie信息,检查是否包含特定的认证Cookie(以"GTL"命名的Cookie)
|
|
|
List<Cookie> cookies = mHttpClient.getCookieStore().getCookies();
|
|
|
boolean hasAuthCookie = false;
|
|
|
for (Cookie cookie : cookies) {
|
|
|
if (cookie.getName().contains("GTL")) {
|
|
|
hasAuthCookie = true;
|
|
|
}
|
|
|
}
|
|
|
if (!hasAuthCookie) {
|
|
|
Log.w(TAG, "it seems that there is no auth cookie");
|
|
|
}
|
|
|
|
|
|
// 从登录响应内容中提取客户端版本号信息,通过解析特定格式的JSON字符串来获取版本号,如果JSON解析出现异常则返回false
|
|
|
String resString = getResponseContent(response.getEntity());
|
|
|
String jsBegin = "_setup(";
|
|
|
String jsEnd = ")}</script>";
|
|
|
int begin = resString.indexOf(jsBegin);
|
|
|
int end = resString.lastIndexOf(jsEnd);
|
|
|
String jsString = null;
|
|
|
if (begin!= -1 && end!= -1 && begin < end) {
|
|
|
jsString = resString.substring(begin + jsBegin.length(), end);
|
|
|
}
|
|
|
JSONObject js = new JSONObject(jsString);
|
|
|
mClientVersion = js.getLong("v");
|
|
|
} catch (JSONException e) {
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
return false;
|
|
|
} catch (Exception e) {
|
|
|
// 简单地捕获所有其他异常情况,记录日志并返回false,表示登录失败
|
|
|
Log.e(TAG, "httpget gtask_url failed");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// 获取下一个操作的唯一标识符的方法,每次调用该方法会使内部的操作标识符(mActionId)自增1,并返回当前的标识符值,用于区分不同的操作请求。
|
|
|
private int getActionId() {
|
|
|
return mActionId++;
|
|
|
}
|
|
|
|
|
|
// 创建一个用于HTTP POST请求的HttpPost对象的方法,设置请求头的Content-Type为"application/x-www-form-urlencoded;charset=utf-8"以及其他自定义的请求头信息(如"AT"设为"1"),返回配置好的HttpPost对象。
|
|
|
private HttpPost createHttpPost() {
|
|
|
HttpPost httpPost = new HttpPost(mPostUrl);
|
|
|
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
|
|
|
httpPost.setHeader("AT", "1");
|
|
|
return httpPost;
|
|
|
}
|
|
|
|
|
|
// 从给定的HTTP实体(通常是HTTP响应的内容实体)中获取响应内容的方法,根据内容的编码格式(如gzip、deflate等)进行相应的解压处理,
|
|
|
// 然后逐行读取内容并拼接成字符串返回,如果出现IO异常则在方法执行完毕后关闭输入流,并向上抛出异常。
|
|
|
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());
|
|
|
} else if (contentEncoding!= null && contentEncoding.equalsIgnoreCase("deflate")) {
|
|
|
Inflater inflater = new Inflater(true);
|
|
|
input = new InflaterInputStream(entity.getContent(), inflater);
|
|
|
}
|
|
|
|
|
|
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();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 向Google Tasks服务发送POST请求的方法,首先检查是否已登录,未登录则抛出异常,然后构建包含请求数据的HttpPost对象,
|
|
|
// 设置请求实体(将JSON数据转换为URL编码的表单实体),发送请求并获取响应,将响应内容解析为JSONObject后返回,
|
|
|
// 如果在请求过程中出现客户端协议异常、IO异常、JSON解析异常等各种情况,则分别抛出对应的异常(NetworkFailureException或ActionFailureException)。
|
|
|
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
|
|
|
if (!mLoggedin) {
|
|
|
Log.e(TAG, "please login first");
|
|
|
throw new ActionFailureException("not logged in");
|
|
|
}
|
|
|
|
|
|
HttpPost httpPost = createHttpPost();
|
|
|
try {
|
|
|
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
|
|
|
list.add(new BasicNameValuePair("r", js.toString()));
|
|
|
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
|
|
|
httpPost.setEntity(entity);
|
|
|
|
|
|
// 执行POST请求,获取响应对象,并从响应中获取内容解析为JSONObject返回
|
|
|
HttpResponse response = mHttpClient.execute(httpPost);
|
|
|
String jsString = getResponseContent(response.getEntity());
|
|
|
return new JSONObject(jsString);
|
|
|
|
|
|
} catch (ClientProtocolException e) {
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
throw new NetworkFailureException("postRequest failed");
|
|
|
} catch (IOException e) {
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
throw new ActionFailureException("get task lists: handing jasonobject failed");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 用于获取指定任务列表(通过列表的唯一标识符listGid来指定)中所有任务信息的方法,以JSONArray形式返回任务列表对应的任务数据。
|
|
|
// 该方法会先提交之前暂存的更新操作(通过调用commitUpdate方法),然后构建请求数据发送到服务器,解析响应获取任务信息,若过程出现异常则向外抛出相应异常。
|
|
|
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
|
|
|
// 先提交之前暂存的更新操作,确保获取任务列表时之前的更新已经处理或者发送到服务器端,避免数据不一致等问题。
|
|
|
commitUpdate();
|
|
|
try {
|
|
|
JSONObject jsPost = new JSONObject();
|
|
|
JSONArray actionList = new JSONArray();
|
|
|
JSONObject action = new JSONObject();
|
|
|
|
|
|
// action_list
|
|
|
// 设置操作类型为获取全部(GETALL),对应的值从GTaskStringUtils中获取,表明此次请求是要获取指定任务列表下的所有任务信息。
|
|
|
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
|
|
|
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
|
|
|
// 为此次操作生成一个唯一的动作标识符,通过调用getActionId方法获取,用于服务器端区分不同的操作请求。
|
|
|
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
|
|
|
// 设置要获取任务的任务列表的唯一标识符,将传入的listGid参数放入对应的JSON字段中,告诉服务器要获取哪个任务列表下的任务。
|
|
|
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid);
|
|
|
// 设置不获取已删除的任务,将对应的JSON字段设置为false,只获取当前未删除状态的任务信息。
|
|
|
action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false);
|
|
|
// 将包含此次操作相关信息的action对象添加到actionList数组中,后续会将actionList作为请求数据的一部分发送给服务器。
|
|
|
actionList.put(action);
|
|
|
// 将actionList数组放入外层的jsPost对象中,对应键为GTaskStringUtils.GTASK_JSON_ACTION_LIST,构建出符合服务器要求格式的请求数据结构。
|
|
|
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
|
|
|
|
|
|
// client_version
|
|
|
// 将客户端当前的版本号放入请求数据中,对应键为GTaskStringUtils.GTASK_JSON_CLIENT_VERSION,服务器端可根据此版本号来判断兼容性等情况,进行相应处理。
|
|
|
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
|
|
|
|
|
|
// 发送POST请求,将构建好的jsPost请求数据发送到服务器,并获取服务器返回的响应数据,解析为JSONObject对象。
|
|
|
JSONObject jsResponse = postRequest(jsPost);
|
|
|
// 从服务器返回的响应数据(jsResponse)中提取任务列表对应的任务信息,以JSONArray形式返回,对应的键为GTaskStringUtils.GTASK_JSON_TASKS,这里假设服务器按约定格式返回了任务数据。
|
|
|
return jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_TASKS);
|
|
|
} catch (JSONException e) {
|
|
|
// 如果在构建请求数据、解析服务器响应数据等过程中出现JSON解析异常,记录错误日志,打印异常堆栈信息,并抛出表示获取任务列表操作中处理JSON对象失败的异常。
|
|
|
Log.e(TAG, e.toString());
|
|
|
e.printStackTrace();
|
|
|
throw new ActionFailureException("get task list: handing jsonobject failed");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 用于获取当前用于同步操作的账户信息(Account类型)的方法,直接返回成员变量mAccount,该变量在登录等相关操作中被赋值,代表与Google Tasks服务交互所使用的账号。
|
|
|
public Account getSyncAccount() {
|
|
|
return mAccount;
|
|
|
}
|
|
|
|
|
|
// 用于重置更新操作数组(mUpdateArray)的方法,将mUpdateArray设置为null,通常用于清空之前暂存的更新操作相关数据,例如在某些特定场景下重新开始积累更新操作时使用。
|
|
|
public void resetUpdateArray() {
|
|
|
mUpdateArray = null;
|
|
|
}
|