You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
note/GTaskClient.java

665 lines
32 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 声明包名这是Java项目中的一个约定用于组织类
package net.micode.notes.gtask.remote;
// 导入所需的Android和其他Java库
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; // 设置界面的Activity
// 导入Apache HttpClient库中的类用于发送HTTP请求
import org.apache.http.HttpEntity; // 表示HTTP消息的实体部分
import org.apache.http.HttpResponse; // 表示HTTP响应
import org.apache.http.client.ClientProtocolException; // 表示HTTP协议错误的异常
import org.apache.http.client.entity.UrlEncodedFormEntity; // 表示表单数据的实体
import org.apache.http.client.methods.HttpGet; // 表示HTTP GET请求的类
import org.apache.http.client.methods.HttpPost; // 表示HTTP POST请求的类
import org.apache.http.cookie.Cookie; // 表示HTTP cookie的类
import org.apache.http.impl.client.BasicCookieStore; // 用于存储HTTP cookies的类
import org.apache.http.impl.client.DefaultHttpClient; // 默认的HTTP客户端实现
import org.apache.http.message.BasicNameValuePair; // 表示表单中名称-值对的类
// 导入HTTP参数设置相关的类
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协议参数的类
// 导入JSON处理相关的类
import org.json.JSONArray; // 表示JSON数组的类
import org.json.JSONException; // 表示JSON格式错误的异常
import org.json.JSONObject; // 表示JSON对象的类
// 导入Java标准库中的类
import java.io.BufferedReader; // 用于读取文本(字符)输入流并缓冲字符,以便提供字符、数组和行的高效读取
import java.io.IOException; // 表示I/O操作失败的异常
import java.io.InputStream; // 表示字节输入流的抽象类
import java.io.InputStreamReader; // 是桥接字节流和字符流的输入流
import java.util.LinkedList; // 实现了List接口的双向链表
import java.util.List; // List接口是Collection接口的子接口
import java.util.zip.GZIPInputStream; // 用于读取GZIP格式压缩文件的输入流
import java.util.zip.Inflater; // 用于解压缩数据流的类
import java.util.zip.InflaterInputStream; // 使用Inflater解压缩输入流的类
// 声明GTaskClient类这是一个用于与Google Tasks API交互的客户端类
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;
// 定义GET请求的URL
private String mGetUrl;
// 定义POST请求的URL
private String mPostUrl;
// 定义客户端版本变量
private long mClientVersion;
// 定义登录状态变量
private boolean mLoggedin;
// 定义最后登录时间变量
private long mLastLoginTime;
// 定义操作ID变量
private int mActionId;
// 定义帐户变量
private Account mAccount;
// 定义更新数据的JSON数组变量
private JSONArray mUpdateArray;
// 私有构造函数,用于实现单例模式
private GTaskClient() {
// 初始化变量
mHttpClient = null;
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
mClientVersion = -1;
mLoggedin = false;
mLastLoginTime = 0;
mActionId = 1;
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;
}
// 如果已经登录则记录日志并返回true
if (mLoggedin) {
Log.d(TAG, "already logged in");
return true;
}
// 更新上次登录时间为当前系统时间
mLastLoginTime = System.currentTimeMillis();
// 尝试登录Google账户
String authToken = loginGoogleAccount(activity, false);
// 如果获取到的authToken为空则记录错误日志并返回false
if (authToken == null) {
Log.e(TAG, "login google account failed");
return false;
}
// 如果账户不是gmail.com或googlemail.com则使用自定义域名登录
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";
// 尝试使用自定义域名登录Google Tasks
if (tryToLoginGtask(activity, authToken)) {
mLoggedin = true;
}
}
// 如果还未登录则尝试使用Google官方URL登录
if (!mLoggedin) {
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
// 如果登录失败则返回false
if (!tryToLoginGtask(activity, authToken)) {
return false;
}
}
// 标记为已登录并返回true
mLoggedin = true;
return true;
}
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
String authToken;
// 获取AccountManager实例
AccountManager accountManager = AccountManager.get(activity);
// 获取所有Google类型的账户
Account[] accounts = accountManager.getAccountsByType("com.google");
// 如果没有可用的Google账户则记录错误日志并返回null
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;
}
}
// 如果找到了匹配的账户则更新mAccount
if (account != null) {
mAccount = account;
} else {
// 如果未找到匹配的账户则记录错误日志并返回null
Log.e(TAG, "unable to get an account with the same name in the settings");
return 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) {
// 如果获取令牌失败则记录错误日志并将authToken设为null
Log.e(TAG, "get auth token failed");
authToken = null;
}
// 返回认证令牌
return authToken;
}
// 尝试使用提供的authToken登录Google Tasks如果失败则尝试重新登录Google账户并再次尝试
private boolean tryToLoginGtask(Activity activity, String authToken) {
// 首先尝试使用提供的authToken登录Google Tasks
if (!loginGtask(authToken)) {
// 如果登录失败可能是因为authToken已过期现在我们尝试使登录Google账户来无效化旧令牌并获取新令牌
authToken = loginGoogleAccount(activity, true); // 尝试重新登录Google账户true可能表示强制刷新令牌
if (authToken == null) {
// 如果重新登录失败,记录错误日志
Log.e(TAG, "login google account failed");
return false; // 返回登录失败
}
// 使用新获取的authToken再次尝试登录Google Tasks
if (!loginGtask(authToken)) {
// 如果仍然登录失败,记录错误日志
Log.e(TAG, "login gtask failed");
return false; // 返回登录失败
}
}
// 如果任何一次登录成功,返回登录成功
return true;
}
// 使用提供的authToken登录Google Tasks
private boolean loginGtask(String authToken) {
// 设置HTTP连接和套接字超时时间
int timeoutConnection = 10000; // 连接超时时间10秒
int timeoutSocket = 15000; // 套接字超时时间15秒
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); // 设置HTTP客户端的Cookie存储
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false); // 禁用HTTP/1.1的Expect-Continue机制
// 尝试登录Google Tasks
try {
// 构建登录URL将authToken作为查询参数附加
String loginUrl = mGetUrl + "?auth=" + authToken;
HttpGet httpGet = new HttpGet(loginUrl); // 创建HTTP GET请求
HttpResponse response = null; // 初始化HTTP响应对象
response = mHttpClient.execute(httpGet); // 执行HTTP GET请求
// 从响应中获取Cookie
List<Cookie> cookies = mHttpClient.getCookieStore().getCookies(); // 获取所有Cookie
boolean hasAuthCookie = false; // 初始化认证Cookie存在标志
for (Cookie cookie : cookies) { // 遍历所有Cookie
if (cookie.getName().contains("GTL")) { // 如果Cookie名称包含"GTL"则认为是认证Cookie
hasAuthCookie = true; // 设置认证Cookie存在标志为true
}
}
if (!hasAuthCookie) { // 如果没有找到认证Cookie
Log.w(TAG, "it seems that there is no auth cookie"); // 记录警告日志
}
// 从响应中提取客户端版本信息
String resString = getResponseContent(response.getEntity()); // 获取响应内容
String jsBegin = "_setup("; // JavaScript响应开始的标记
String jsEnd = ")}</script>"; // JavaScript响应结束的标记
int begin = resString.indexOf(jsBegin); // 查找JavaScript开始的索引
int end = resString.lastIndexOf(jsEnd); // 查找JavaScript结束的索引
String jsString = null; // 初始化JavaScript字符串
if (begin != -1 && end != -1 && begin < end) { // 如果找到了JavaScript的开始和结束标记
jsString = resString.substring(begin + jsBegin.length(), end); // 提取JavaScript字符串
}
JSONObject js = new JSONObject(jsString); // 将JavaScript字符串转换为JSONObject
mClientVersion = js.getLong("v"); // 从JSONObject中获取客户端版本信息
} catch (JSONException e) { // 如果解析JSON时发生异常
Log.e(TAG, e.toString()); // 记录错误日志
e.printStackTrace(); // 打印异常堆栈信息
return false; // 返回登录失败
} catch (Exception e) { // 如果发生其他异常
// 简单地捕获所有异常
Log.e(TAG, "httpget gtask_url failed"); // 记录错误日志
return false; // 返回登录失败
}
// 如果没有发生异常,返回登录成功
return true;
}
// 生成一个唯一的动作ID每次调用时ID递增
private int getActionId() {
return mActionId++; // 返回当前ID并递增ID
}
// 创建一个用于发送HTTP POST请求的HttpPost对象
private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl); // 创建HttpPost对象指向mPostUrl
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); // 设置请求头,指定内容类型和字符集
httpPost.setHeader("AT", "1"); // 设置请求头,可能用于认证或其他目的
return httpPost; // 返回HttpPost对象
}
// 定义一个方法用于从HttpEntity中获取响应内容
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(); // 获取输入流
// 如果内容编码是gzip则使用GZIPInputStream进行解压
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {
input = new GZIPInputStream(entity.getContent());
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {
// 如果内容编码是deflate则使用InflaterInputStream进行解压
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(); // 无论是否发生异常,都关闭输入流
}
}
// 定义一个方法用于发送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(); // 创建HttpPost对象方法未在代码中给出
try {
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>(); // 创建键值对列表
list.add(new BasicNameValuePair("r", js.toString())); // 将JSON对象转换为字符串并添加到列表中
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); // 创建表单实体
httpPost.setEntity(entity); // 设置HttpPost的实体
// 执行POST请求
HttpResponse response = mHttpClient.execute(httpPost);
String jsString = getResponseContent(response.getEntity()); // 获取响应内容
return new JSONObject(jsString); // 将响应内容转换为JSONObject
} 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 NetworkFailureException("postRequest failed"); // 抛出网络失败异常
} catch (JSONException e) {
Log.e(TAG, e.toString()); // 打印异常信息
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对象用于POST请求
JSONArray actionList = new JSONArray(); // 创建JSON数组用于存储动作列表
// 向动作列表中添加任务创建动作
actionList.put(task.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将动作列表添加到JSON对象中
// 添加客户端版本信息
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)); // 设置任务的GID
} catch (JSONException e) {
Log.e(TAG, e.toString()); // 打印异常信息
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(); // 创建一个JSON数组用于存放动作列表
// 将创建任务的动作添加到动作列表中
actionList.put(tasklist.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将动作列表添加到请求JSON中
// 添加客户端版本信息到请求JSON中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// 发送请求并接收响应
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()); // 记录异常
e.printStackTrace(); // 打印异常堆栈
throw new ActionFailureException("create tasklist: handing jsonobject failed"); // 抛出动作失败异常
}
}
// 提交更新到服务器
public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) {
try {
JSONObject jsPost = new JSONObject(); // 创建一个JSON对象用于发送请求
// 将更新动作列表添加到请求JSON中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray);
// 添加客户端版本信息到请求JSON中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost); // 发送请求
mUpdateArray = null; // 清空更新数组
} catch (JSONException e) {
Log.e(TAG, e.toString()); // 记录异常
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(); // 创建一个JSON数组用于存放动作列表
JSONObject action = new JSONObject(); // 创建一个JSON对象用于存放动作信息
// 设置动作类型为移动并添加其他必要信息到动作JSON中
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) {
// 如果在同一个任务列表中移动且不是第一个任务则添加前一个兄弟任务的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); // 将动作列表添加到请求JSON中
// 添加客户端版本信息到请求JSON中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost); // 发送请求
} catch (JSONException e) {
Log.e(TAG, e.toString()); // 记录异常
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(); // 创建一个JSON数组用于存放动作列表
// 标记节点为已删除,并将删除动作添加到动作列表中
node.setDeleted(true);
actionList.put(node.getUpdateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将动作列表添加到请求JSON中
// 添加客户端版本信息到请求JSON中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost); // 发送请求
mUpdateArray = null; // 清空更新数组
} catch (JSONException e) {
Log.e(TAG, e.toString()); // 记录异常
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 {
// 创建一个HTTP GET请求
HttpGet httpGet = new HttpGet(mGetUrl);
// 初始化HTTP响应对象为null
HttpResponse response = null;
// 执行HTTP GET请求
response = mHttpClient.execute(httpGet);
// 从响应中获取任务列表的字符串内容
String resString = getResponseContent(response.getEntity());
// 定义JSON字符串的开始和结束标记
String jsBegin = "_setup(";
String jsEnd = ")}</script>";
// 在响应字符串中查找开始和结束标记的位置
int begin = resString.indexOf(jsBegin);
int end = resString.lastIndexOf(jsEnd);
// 初始化JSON字符串为null
String jsString = null;
// 如果找到了开始和结束标记,并且开始位置在结束位置之前
if (begin != -1 && end != -1 && begin < end) {
// 提取JSON字符串
jsString = resString.substring(begin + jsBegin.length(), end);
}
// 将提取的JSON字符串转换为JSONObject
JSONObject js = new JSONObject(jsString);
// 从JSONObject中获取名为"t"的对象然后从中获取名为GTASK_JSON_LISTS的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) {
// 如果捕获到IO异常记录错误日志并抛出网络失败异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new NetworkFailureException("gettasklists: httpget failed");
} catch (JSONException e) {
// 如果捕获到JSON解析异常记录错误日志并抛出动作失败异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("get task lists: handing jasonobject failed");
}
}
// 定义一个方法,用于获取特定任务列表的内容,可能会抛出网络失败异常
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
// 提交更新(可能用于同步或更新状态)
commitUpdate();
try {
// 创建用于POST请求的JSONObject
JSONObject jsPost = new JSONObject();
// 创建一个JSONArray用于存放动作列表
JSONArray actionList = new JSONArray();
// 创建一个JSONObject用于存放单个动作
JSONObject action = new JSONObject();
// 设置动作列表中的动作类型、动作ID、列表ID和是否获取已删除项
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid);
action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false);
// 将动作添加到动作列表中
actionList.put(action);
// 将动作列表添加到POST请求的JSONObject中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// 设置客户端版本
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// 发送POST请求并获取响应
JSONObject jsResponse = postRequest(jsPost);
// 从响应中获取任务列表的JSONArray
return jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_TASKS);
} catch (JSONException e) {
// 如果捕获到JSON解析异常记录错误日志并抛出动作失败异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("get task list: handing jsonobject failed");
}
}
// 定义一个方法,用于获取同步账户信息
public Account getSyncAccount() {
// 返回账户信息
return mAccount;
}
// 定义一个方法,用于重置更新数组
public void resetUpdateArray() {
// 将更新数组设置为null
mUpdateArray = null;
}
}