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.
software/GTaskClient.txt

808 lines
34 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.

/*
* 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任务服务进行交互的客户端类。
* 该类提供了登录、创建任务、创建任务列表、更新任务、移动任务、删除任务等功能。
*/
public class GTaskClient {
private static final String TAG = GTaskClient.class.getSimpleName();
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;
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; // 初始化HttpClient为null
mGetUrl = GTASK_GET_URL; // 初始化GET和POST请求的URL
mPostUrl = GTASK_POST_URL;
mClientVersion = -1; // 初始化客户端版本号为-1
mLoggedin = false; // 初始化登录状态为false
mLastLoginTime = 0; // 初始化最后一次登录时间为0
mActionId = 1; // 初始化操作ID为1
mAccount = null; // 初始化账户为null
mUpdateArray = null; // 初始化更新数组为null
}
/*
* 获取GTaskClient的单例实例。
* @return GTaskClient的单例实例
*/
public static synchronized GTaskClient getInstance() {
// 如果mInstance为null创建一个新的GTaskClient实例
if (mInstance == null) {
mInstance = new GTaskClient();
}
// 返回GTaskClient的单例实例
return mInstance;
}
/*
* 登录Google任务服务。
* @param activity 当前活动
* @return 是否登录成功
*/
public boolean login(Activity activity) {
// we suppose that the cookie would expire after 5 minutes
// 假设cookie在5分钟后过期需要重新登录
// 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))) {
mLoggedin = false;
}
// 如果已经登录直接返回true
if (mLoggedin) {
Log.d(TAG, "already logged in");
return true;
}
// 更新最后一次登录时间
mLastLoginTime = System.currentTimeMillis();
// 登录Google账户
String authToken = loginGoogleAccount(activity, false);
if (authToken == null) {
Log.e(TAG, "login google account failed");
return false;
}
// login with custom domain if necessary
// 如果账户不是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";
if (tryToLoginGtask(activity, authToken)) {
mLoggedin = true;
}
}
// try to login with google official url
// 尝试使用Google官方URL登录
if (!mLoggedin) {
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
if (!tryToLoginGtask(activity, authToken)) {
return false;
}
}
// 登录成功
mLoggedin = true;
return true;
}
/*
* 登录Google账户并获取授权令牌。
* @param activity 当前活动
* @param invalidateToken 是否使授权令牌失效
* @return 授权令牌如果登录失败则返回null
*/
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;
// 遍历所有Google账户查找与设置中同步账户名称匹配的账户
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;
}
// get the token now
// 获取授权令牌
AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null);
try {
// 获取授权令牌的Bundle
Bundle authTokenBundle = accountManagerFuture.getResult();
// 从Bundle中获取授权令牌
authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN);
// 如果需要使授权令牌失效,使令牌失效并重新获取
if (invalidateToken) {
accountManager.invalidateAuthToken("com.google", authToken);
loginGoogleAccount(activity, false);
}
} catch (Exception e) {
// 如果获取授权令牌失败记录错误日志并返回null
Log.e(TAG, "get auth token failed");
authToken = null;
}
return authToken; // 返回授权令牌
}
/*
* 尝试登录Google任务服务。
* @param activity 当前活动
* @param authToken 授权令牌
* @return 是否登录成功
*/
private boolean tryToLoginGtask(Activity activity, String authToken) {
// 尝试使用当前授权令牌登录Google任务服务
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");
return false;
}
// 使用新的授权令牌再次尝试登录Google任务服务
if (!loginGtask(authToken)) {
Log.e(TAG, "login gtask failed");
return false;
}
}
return true;
}
/*
* 使用授权令牌登录Google任务服务。
* @param authToken 授权令牌
* @return 是否登录成功
*/
private boolean loginGtask(String authToken) {
// 设置连接超时和套接字超时
int timeoutConnection = 10000;
int timeoutSocket = 15000;
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
// 创建DefaultHttpClient实例
mHttpClient = new DefaultHttpClient(httpParameters);
// 创建BasicCookieStore实例并设置到HttpClient中
BasicCookieStore localBasicCookieStore = new BasicCookieStore();
mHttpClient.setCookieStore(localBasicCookieStore);
// 设置HttpClient不使用Expect-Continue
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false);
// login gtask
// 登录Google任务服务
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<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");
}
// get the client version
// 获取客户端版本
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) {
// simply catch all exceptions
// 捕获所有异常
Log.e(TAG, "httpget gtask_url failed");
return false;
}
return true;
}
/*
* 获取操作ID并递增。
* @return 当前操作ID
*/
private int getActionId() {
// 返回当前操作ID并递增
return mActionId++;
}
/*
* 创建HttpPost请求。
* @return 创建的HttpPost请求
*/
private HttpPost createHttpPost() {
// 创建HttpPost请求设置请求URL
HttpPost httpPost = new HttpPost(mPostUrl);
// 设置请求头指定Content-Type为application/x-www-form-urlencoded字符集为UTF-8
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
httpPost.setHeader("AT", "1");
// 设置请求头指定AT为1
return httpPost;
// 返回创建的HttpPost请求
}
/*
* 从HttpEntity中获取响应内容并返回字符串形式。
* 支持处理gzip和deflate压缩编码。
* @param entity HTTP响应实体
* @return 响应内容的字符串形式
* @throws IOException 如果读取输入流时发生错误
*/
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
// 检查HttpEntity是否包含Content-Encoding头部
if (entity.getContentEncoding() != null) {
// 获取Content-Encoding的值
contentEncoding = entity.getContentEncoding().getValue();
// 记录日志显示当前的Content-Encoding
Log.d(TAG, "encoding: " + contentEncoding);
}
// 获取HttpEntity的原始输入流
InputStream input = entity.getContent();
// 如果Content-Encoding是gzip则使用GZIPInputStream解压缩
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {
input = new GZIPInputStream(entity.getContent());
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {
// 如果Content-Encoding是deflate则使用InflaterInputStream解压缩
Inflater inflater = new Inflater(true);
input = new InflaterInputStream(entity.getContent(), inflater);
}
try {
// 创建InputStreamReader用于将字节流转换为字符流
InputStreamReader isr = new InputStreamReader(input);
// 创建BufferedReader用于逐行读取字符流
BufferedReader br = new BufferedReader(isr);
// 创建StringBuilder用于存储读取到的内容
StringBuilder sb = new StringBuilder();
// 循环读取输入流中的每一行
while (true) {
String buff = br.readLine();
// 如果读取到null表示已经到达流的末尾返回StringBuilder中的内容
if (buff == null) {
return sb.toString();
}
// 将读取到的行追加到StringBuilder中
sb = sb.append(buff);
}
} finally {
// 确保输入流在方法结束时被关闭
input.close();
}
}
/*
* 发送POST请求并返回响应的JSONObject。
* @param js 要发送的请求数据以JSONObject形式表示
* @return 服务器响应的JSONObject
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如未登录或响应内容无法转换为JSONObject
*/
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
// 检查用户是否已登录,如果未登录则抛出异常
if (!mLoggedin) {
Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in");
}
// 创建HttpPost对象
HttpPost httpPost = createHttpPost();
try {
// 创建一个LinkedList来存储请求参数
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
// 将请求数据JSONObject转换为字符串并添加到请求参数列表中
list.add(new BasicNameValuePair("r", js.toString()));
// 创建UrlEncodedFormEntity对象用于将请求参数编码为表单格式
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
// 将请求实体设置到HttpPost对象中
httpPost.setEntity(entity);
// execute the post
// 执行POST请求
HttpResponse response = mHttpClient.execute(httpPost);
// 获取响应内容并转换为字符串
String jsString = getResponseContent(response.getEntity());
// 将响应内容字符串转换为JSONObject并返回
return new JSONObject(jsString);
} catch (ClientProtocolException e) {
// 捕获并记录HTTP协议异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new NetworkFailureException("postRequest failed");
} catch (IOException e) {
// 捕获并记录IO异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new NetworkFailureException("postRequest failed");
} catch (JSONException e) {
// 捕获并记录JSON解析异常
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");
}
}
/*
* 创建一个新的任务,并将其上传到服务器。
* @param task 要创建的任务对象
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如JSON处理失败
*/
public void createTask(Task task) throws NetworkFailureException {
// 提交更新操作
commitUpdate();
try {
// 创建一个新的JSONObject用于存储POST请求的数据
JSONObject jsPost = new JSONObject();
// 创建一个JSONArray用于存储任务的创建操作
JSONArray actionList = new JSONArray();
// action_list
// 将任务的创建操作添加到actionList中
actionList.put(task.getCreateAction(getActionId()));
// 将actionList添加到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
// 添加客户端版本信息到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// post
// 发送POST请求并将响应内容转换为JSONObject
JSONObject jsResponse = postRequest(jsPost);
// 从响应中获取结果数组,并获取第一个结果
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
// 从结果中获取新创建任务的ID并设置到任务对象中
task.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
} catch (JSONException e) {、
// 捕获并记录JSON解析异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("create task: handing jsonobject failed");
}
}
/*
* 创建一个新的任务列表,并将其上传到服务器。
* @param tasklist 要创建的任务列表对象
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如JSON处理失败
*/
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
// 提交更新操作
commitUpdate();
try {
// 创建一个新的JSONObject用于存储POST请求的数据
JSONObject jsPost = new JSONObject();
// 创建一个JSONArray用于存储任务列表的创建操作
JSONArray actionList = new JSONArray();
// action_list
// 将任务列表的创建操作添加到actionList中
actionList.put(tasklist.getCreateAction(getActionId()));
// 将actionList添加到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client version
// 添加客户端版本信息到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// post
// 发送POST请求并将响应内容转换为JSONObject
JSONObject jsResponse = postRequest(jsPost);
// 从响应中获取结果数组,并获取第一个结果
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
// 从结果中获取新创建任务列表的ID并设置到任务列表对象中
tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
} catch (JSONException e) {
// 捕获并记录JSON解析异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("create tasklist: handing jsonobject failed");
}
}
/*
* 提交所有未完成的更新操作到服务器。
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如JSON处理失败
*/
public void commitUpdate() throws NetworkFailureException {
// 检查是否有未完成的更新操作
if (mUpdateArray != null) {
try {
// 创建一个新的JSONObject用于存储POST请求的数据
JSONObject jsPost = new JSONObject();
// action_list
// 将未完成的更新操作数组添加到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray);
// client_version
// 添加客户端版本信息到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// 发送POST请求
postRequest(jsPost);
// 提交成功后,清空更新操作数组
mUpdateArray = null;
} catch (JSONException e) {
// 捕获并记录JSON解析异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("commit update: handing jsonobject failed");
}
}
}
/*
* 将一个节点添加到更新操作数组中,并在必要时提交更新操作。
* @param node 要添加的节点对象
* @throws NetworkFailureException 如果网络请求失败
*/
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();
}
// 如果更新操作数组为空则创建一个新的JSONArray
if (mUpdateArray == null)
mUpdateArray = new JSONArray();
// 将节点的更新操作添加到更新操作数组中
mUpdateArray.put(node.getUpdateAction(getActionId()));
}
}
/*
* 将任务从一个任务列表移动到另一个任务列表。
* @param task 要移动的任务对象
* @param preParent 任务的原始父任务列表
* @param curParent 任务的新父任务列表
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如JSON处理失败
*/
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
// 提交更新操作
commitUpdate();
try {
// 创建一个新的JSONObject用于存储POST请求的数据
JSONObject jsPost = new JSONObject();
// 创建一个JSONArray用于存储任务的移动操作
JSONArray actionList = new JSONArray();
// 创建一个JSONObject用于存储具体的移动操作
JSONObject action = new JSONObject();
// action_list
// 设置移动操作的类型为"move"
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE);
// 设置移动操作的ID
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
// 设置要移动的任务的ID
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());
}
// 设置任务的原始父任务列表的ID
action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid());
// 设置任务的新父任务列表的ID
action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid());
// 如果任务在不同的任务列表之间移动则设置目标任务列表的ID
if (preParent != curParent) {
// put the dest_list only if moving between tasklists
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());
}
// 将移动操作添加到actionList中
actionList.put(action);
// 将actionList添加到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
// 添加客户端版本信息到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// 发送POST请求
postRequest(jsPost);
} catch (JSONException e) {
// 捕获并记录JSON解析异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("move task: handing jsonobject failed");
}
}
/*
* 删除一个节点,并将其标记为已删除状态。
* @param node 要删除的节点对象
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如JSON处理失败
*/
public void deleteNode(Node node) throws NetworkFailureException {
// 提交更新操作
commitUpdate();
try {
// 创建一个新的JSONObject用于存储POST请求的数据
JSONObject jsPost = new JSONObject();
// 创建一个JSONArray用于存储节点的删除操作
JSONArray actionList = new JSONArray();
// action_list
// 将节点标记为已删除
node.setDeleted(true);
// 获取节点的更新操作并将其添加到actionList中
actionList.put(node.getUpdateAction(getActionId()));
// 将actionList添加到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
// 添加客户端版本信息到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// 发送POST请求
postRequest(jsPost);
// 提交成功后,清空更新操作数组
mUpdateArray = null;
} catch (JSONException e) {
// 捕获并记录JSON解析异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("delete node: handing jsonobject failed");
}
}
/*
* 获取所有任务列表并返回一个包含任务列表的JSONArray。
* @return 包含任务列表的JSONArray
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如未登录或JSON处理失败
*/
public JSONArray getTaskLists() throws NetworkFailureException {
// 检查用户是否已登录,如果未登录则抛出异常
if (!mLoggedin) {
Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in");
}
try {
// 创建一个HttpGet对象用于发送GET请求
HttpGet httpGet = new HttpGet(mGetUrl);
HttpResponse response = null;
// 执行GET请求并获取响应
response = mHttpClient.execute(httpGet);
// get the task list
// 获取响应内容并转换为字符串
String resString = getResponseContent(response.getEntity());
// 从响应内容中提取包含任务列表的JSON字符串
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);
}
// 将提取的JSON字符串转换为JSONObject
JSONObject js = new JSONObject(jsString);
// 从JSONObject中获取任务列表的JSONArray并返回
return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS);
} catch (ClientProtocolException e) {
// 捕获并记录HTTP协议异常
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");
}
}
/*
* 获取指定任务列表中的所有任务并返回一个包含任务的JSONArray。
* @param listGid 任务列表的ID
* @return 包含任务的JSONArray
* @throws NetworkFailureException 如果网络请求失败
* @throws ActionFailureException 如果操作失败例如JSON处理失败
*/
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
// 提交更新操作
commitUpdate();
try {
// 创建一个新的JSONObject用于存储POST请求的数据
JSONObject jsPost = new JSONObject();
// 创建一个JSONArray用于存储获取任务列表的操作
JSONArray actionList = new JSONArray();
// 创建一个JSONObject用于存储具体的获取操作
JSONObject action = new JSONObject();
// action_list
// 设置获取操作的类型为"getall"
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
// 设置获取操作的ID
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
// 设置要获取的任务列表的ID
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid);
// 设置是否获取已删除的任务这里设置为false
action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false);
// 将获取操作添加到actionList中
actionList.put(action);
// 将actionList添加到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
// 添加客户端版本信息到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// 发送POST请求并将响应内容转换为JSONObject
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");
}
}
/*
* 获取当前同步的账户。
* @return 当前同步的账户对象
*/
public Account getSyncAccount() {
return mAccount;
}
/*
* 重置更新操作数组。
*/
public void resetUpdateArray() {
mUpdateArray = null;
}
}