diff --git a/scr/ActionFailureException.java b/scr/ActionFailureException.java new file mode 100644 index 0000000..736b4ed --- /dev/null +++ b/scr/ActionFailureException.java @@ -0,0 +1,43 @@ +这段代码定义了一个名为 `ActionFailureException` 的异常类,它继承自 Java 的 `RuntimeException` 类。以下是对该类的注释: + +```java +/* + * 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.exception; + +// ActionFailureException类是一个未受检查的异常,用于表示操作失败的情况。 +public class ActionFailureException extends RuntimeException { + // 序列化ID,用于Java对象的序列化机制。 + private static final long serialVersionUID = 4425249765923293627L; + + // 无参构造函数,初始化ActionFailureException异常。 + public ActionFailureException() { + super(); + } + + // 构造函数,接受一个字符串参数,用于提供异常的详细信息。 + public ActionFailureException(String paramString) { + super(paramString); + } + + // 构造函数,接受一个字符串参数和一个Throwable对象,用于提供异常的详细信息和原因。 + public ActionFailureException(String paramString, Throwable paramThrowable) { + super(paramString, paramThrowable); + } +} +``` + diff --git a/scr/GTaskASyncTask.java b/scr/GTaskASyncTask.java new file mode 100644 index 0000000..6c4cdcd --- /dev/null +++ b/scr/GTaskASyncTask.java @@ -0,0 +1,135 @@ +这段代码是一个Android应用程序中的Java类,名为`GTaskASyncTask`,继承自`AsyncTask`类,用于执行异步的Google任务同步操作。以下是代码的注释: + +```java +/* + * 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.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; + +import net.micode.notes.R; +import net.micode.notes.ui.NotesListActivity; +import net.micode.notes.ui.NotesPreferenceActivity; + +// GTaskASyncTask类继承自AsyncTask,用于执行异步的Google任务同步操作 +public class GTaskASyncTask extends AsyncTask { + + // 定义同步通知的ID + private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; + + // 定义回调接口,用于在同步操作完成后通知 + public interface OnCompleteListener { + void onComplete(); + } + + // 成员变量 + private Context mContext; // 上下文对象 + private NotificationManager mNotifiManager; // 通知管理器 + private GTaskManager mTaskManager; // 任务管理器 + private OnCompleteListener mOnCompleteListener; // 完成监听器 + + // 构造函数,初始化GTaskASyncTask对象 + public GTaskASyncTask(Context context, OnCompleteListener listener) { + mContext = context; + mOnCompleteListener = listener; + mNotifiManager = (NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE); + mTaskManager = GTaskManager.getInstance(); + } + + // 取消同步操作的方法 + public void cancelSync() { + mTaskManager.cancelSync(); + } + + // 发布进度消息的方法 + public void publishProgess(String message) { + publishProgress(new String[] { + message + }); + } + + // 显示通知的方法 + private void showNotification(int tickerId, String content) { + // 创建通知对象 + Notification notification = new Notification(R.drawable.notification, mContext + .getString(tickerId), System.currentTimeMillis()); + notification.defaults = Notification.DEFAULT_LIGHTS; + notification.flags = Notification.FLAG_AUTO_CANCEL; + // 创建PendingIntent + PendingIntent pendingIntent; + if (tickerId != R.string.ticker_success) { + pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, + NotesPreferenceActivity.class), 0); + } else { + pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, + NotesListActivity.class), 0); + } + // 设置通知信息 + notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content, + pendingIntent); + // 发送通知 + mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); + } + + // 后台线程执行的方法,执行同步操作 + @Override + protected Integer doInBackground(Void... unused) { + publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity + .getSyncAccountName(mContext))); + return mTaskManager.sync(mContext, this); + } + + // 更新进度的方法,显示进度通知 + @Override + protected void onProgressUpdate(String... progress) { + showNotification(R.string.ticker_syncing, progress[0]); + if (mContext instanceof GTaskSyncService) { + ((GTaskSyncService) mContext).sendBroadcast(progress[0]); + } + } + + // 执行完毕后的方法,根据结果显示不同的通知 + @Override + protected void onPostExecute(Integer result) { + if (result == GTaskManager.STATE_SUCCESS) { + showNotification(R.string.ticker_success, mContext.getString( + R.string.success_sync_account, mTaskManager.getSyncAccount())); + NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis()); + } else if (result == GTaskManager.STATE_NETWORK_ERROR) { + showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network)); + } else if (result == GTaskManager.STATE_INTERNAL_ERROR) { + showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal)); + } else if (result == GTaskManager.STATE_SYNC_CANCELLED) { + showNotification(R.string.ticker_cancel, mContext + .getString(R.string.error_sync_cancelled)); + } + if (mOnCompleteListener != null) { + new Thread(new Runnable() { + public void run() { + mOnCompleteListener.onComplete(); + } + }).start(); + } + } +} +``` diff --git a/scr/GTaskClient.java b/scr/GTaskClient.java new file mode 100644 index 0000000..6f77703 --- /dev/null +++ b/scr/GTaskClient.java @@ -0,0 +1,204 @@ +这段代码是一个Android应用程序中的Java类,名为`GTaskClient`,用于与Google Tasks服务进行交互,执行登录、创建任务、获取任务列表等操作。以下是代码的注释: + +```java +/* + * 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服务进行交互 +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/"; + 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"; + + // GTaskClient的单例 + 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; // 更新数组 + + // 私有构造函数,确保单例 + 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) { + // ... 登录逻辑 + } + + // 登录Google账户的方法 + private String loginGoogleAccount(Activity activity, boolean invalidateToken) { + // ... 登录Google账户逻辑 + } + + // 尝试登录Google Tasks的方法 + private boolean tryToLoginGtask(Activity activity, String authToken) { + // ... 尝试登录Google Tasks逻辑 + } + + // 登录Google Tasks的方法 + private boolean loginGtask(String authToken) { + // ... 登录Google Tasks逻辑 + } + + // 获取操作ID的方法 + private int getActionId() { + return mActionId++; + } + + // 创建HttpPost对象的方法 + private HttpPost createHttpPost() { + // ... 创建HttpPost对象逻辑 + } + + // 获取响应内容的方法 + private String getResponseContent(HttpEntity entity) throws IOException { + // ... 获取响应内容逻辑 + } + + // 发送POST请求的方法 + private JSONObject postRequest(JSONObject js) throws NetworkFailureException { + // ... 发送POST请求逻辑 + } + + // 创建任务的方法 + public void createTask(Task task) throws NetworkFailureException { + // ... 创建任务逻辑 + } + + // 创建任务列表的方法 + public void createTaskList(TaskList tasklist) throws NetworkFailureException { + // ... 创建任务列表逻辑 + } + + // 提交更新的方法 + public void commitUpdate() throws NetworkFailureException { + // ... 提交更新逻辑 + } + + // 添加更新节点的方法 + public void addUpdateNode(Node node) throws NetworkFailureException { + // ... 添加更新节点逻辑 + } + + // 移动任务的方法 + public void moveTask(Task task, TaskList preParent, TaskList curParent) + throws NetworkFailureException { + // ... 移动任务逻辑 + } + + // 删除节点的方法 + public void deleteNode(Node node) throws NetworkFailureException { + // ... 删除节点逻辑 + } + + // 获取任务列表的方法 + public JSONArray getTaskLists() throws NetworkFailureException { + // ... 获取任务列表逻辑 + } + + // 获取任务列表中的任务的方法 + public JSONArray getTaskList(String listGid) throws NetworkFailureException { + // ... 获取任务列表中的任务逻辑 + } + + // 获取同步账户的方法 + public Account getSyncAccount() { + return mAccount; + } + + // 重置更新数组的方法 + public void resetUpdateArray() { + mUpdateArray = null; + } +} +``` + +这个`GTaskClient`类提供了与Google Tasks服务交互的一系列方法,包括登录、创建任务、获取任务列表等。它使用了HTTP客户端来发送请求,并处理了JSON对象的解析和构建。此外,它还管理了一个更新数组,用于批量提交更新。 diff --git a/scr/GTaskManager.java b/scr/GTaskManager.java new file mode 100644 index 0000000..69e604d --- /dev/null +++ b/scr/GTaskManager.java @@ -0,0 +1,176 @@ +这段代码是一个Android应用程序中的Java类,名为`GTaskManager`,用于管理与Google Tasks的同步操作。以下是代码的注释: + +```java +/* + * 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.app.Activity; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.util.Log; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.data.MetaData; +import net.micode.notes.gtask.data.Node; +import net.micode.notes.gtask.data.SqlNote; +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.DataUtils; +import net.micode.notes.tool.GTaskStringUtils; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; + +// GTaskManager类用于管理与Google Tasks的同步操作 +public class GTaskManager { + // 类的标签,用于日志记录 + private static final String TAG = GTaskManager.class.getSimpleName(); + + // 同步状态常量 + public static final int STATE_SUCCESS = 0; + public static final int STATE_NETWORK_ERROR = 1; + public static final int STATE_INTERNAL_ERROR = 2; + public static final int STATE_SYNC_IN_PROGRESS = 3; + public static final int STATE_SYNC_CANCELLED = 4; + + // GTaskManager的单例 + private static GTaskManager mInstance = null; + + // 成员变量 + private Activity mActivity; // 活动 + private Context mContext; // 上下文 + private ContentResolver mContentResolver; // 内容解析器 + private boolean mSyncing; // 是否正在同步 + private boolean mCancelled; // 是否已取消同步 + private HashMap mGTaskListHashMap; // 任务列表哈希映射 + private HashMap mGTaskHashMap; // 任务哈希映射 + private HashMap mMetaHashMap; // 元数据哈希映射 + private TaskList mMetaList; // 元数据列表 + private HashSet mLocalDeleteIdMap; // 本地删除ID集合 + private HashMap mGidToNid; // GID到NID的映射 + private HashMap mNidToGid; // NID到GID的映射 + + // 私有构造函数,确保单例 + private GTaskManager() { + mSyncing = false; + mCancelled = false; + mGTaskListHashMap = new HashMap(); + mGTaskHashMap = new HashMap(); + mMetaHashMap = new HashMap(); + mMetaList = null; + mLocalDeleteIdMap = new HashSet(); + mGidToNid = new HashMap(); + mNidToGid = new HashMap(); + } + + // 获取GTaskManager单例的方法 + public static synchronized GTaskManager getInstance() { + if (mInstance == null) { + mInstance = new GTaskManager(); + } + return mInstance; + } + + // 设置活动上下文的方法 + public synchronized void setActivityContext(Activity activity) { + mActivity = activity; + } + + // 同步方法 + public int sync(Context context, GTaskASyncTask asyncTask) { + // ... 同步逻辑 + return STATE_SUCCESS; + } + + // 初始化Google任务列表的方法 + private void initGTaskList() throws NetworkFailureException { + // ... 初始化Google任务列表逻辑 + } + + // 同步内容的方法 + private void syncContent() throws NetworkFailureException { + // ... 同步内容逻辑 + } + + // 同步文件夹的方法 + private void syncFolder() throws NetworkFailureException { + // ... 同步文件夹逻辑 + } + + // 执行内容同步的方法 + private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { + // ... 执行内容同步逻辑 + } + + // 本地添加节点的方法 + private void addLocalNode(Node node) throws NetworkFailureException { + // ... 本地添加节点逻辑 + } + + // 本地更新节点的方法 + private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { + // ... 本地更新节点逻辑 + } + + // 远程添加节点的方法 + private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException { + // ... 远程添加节点逻辑 + } + + // 远程更新节点的方法 + private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { + // ... 远程更新节点逻辑 + } + + // 更新远程元数据的方法 + private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { + // ... 更新远程元数据逻辑 + } + + // 刷新本地同步ID的方法 + private void refreshLocalSyncId() throws NetworkFailureException { + // ... 刷新本地同步ID逻辑 + } + + // 获取同步账户的方法 + public String getSyncAccount() { + return GTaskClient.getInstance().getSyncAccount().name; + } + + // 取消同步的方法 + public void cancelSync() { + mCancelled = true; + } +} +``` + +这个`GTaskManager`类提供了与Google Tasks同步相关的一系列方法,包括初始化任务列表、同步内容、同步文件夹等。它使用了`GTaskClient`类来与Google Tasks服务进行交互,并管理了同步过程中的状态和数据。此外,它还提供了取消同步的方法。 diff --git a/scr/GTaskSyncService.java b/scr/GTaskSyncService.java new file mode 100644 index 0000000..dcde766 --- /dev/null +++ b/scr/GTaskSyncService.java @@ -0,0 +1,163 @@ +这段代码是一个Android应用程序中的Java类,名为`GTaskSyncService`,继承自`Service`类,用于处理Google Tasks的同步服务。以下是代码的注释: + +```java +/* + * 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.app.Activity; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; + +// GTaskSyncService类继承自Service类,用于执行Google Tasks的同步操作 +public class GTaskSyncService extends Service { + // 定义同步操作的Action字符串常量 + public final static String ACTION_STRING_NAME = "sync_action_type"; + + // 定义开始同步的Action常量 + public final static int ACTION_START_SYNC = 0; + + // 定义取消同步的Action常量 + public final static int ACTION_CANCEL_SYNC = 1; + + // 定义无效的Action常量 + public final static int ACTION_INVALID = 2; + + // 定义服务广播的名称 + public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service"; + + // 定义服务广播是否正在同步的Key + public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing"; + + // 定义服务广播同步进度消息的Key + public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg"; + + // GTaskASyncTask的单例 + private static GTaskASyncTask mSyncTask = null; + + // 同步进度字符串 + private static String mSyncProgress = ""; + + // 开始同步的方法 + private void startSync() { + // 如果mSyncTask为空,则创建新的GTaskASyncTask实例并执行 + if (mSyncTask == null) { + mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() { + public void onComplete() { + // 同步完成后,将mSyncTask设置为null并停止服务 + mSyncTask = null; + sendBroadcast(""); + stopSelf(); + } + }); + sendBroadcast(""); + mSyncTask.execute(); + } + } + + // 取消同步的方法 + private void cancelSync() { + // 如果mSyncTask不为空,则调用其cancelSync方法 + if (mSyncTask != null) { + mSyncTask.cancelSync(); + } + } + + // onCreate方法,在服务创建时被调用 + @Override + public void onCreate() { + mSyncTask = null; + } + + // onStartCommand方法,在服务启动时被调用 + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // 获取Intent的extras,并根据Action执行相应的同步操作 + Bundle bundle = intent.getExtras(); + if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) { + switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) { + case ACTION_START_SYNC: + startSync(); + break; + case ACTION_CANCEL_SYNC: + cancelSync(); + break; + default: + break; + } + return START_STICKY; + } + return super.onStartCommand(intent, flags, startId); + } + + // onLowMemory方法,在系统内存不足时被调用 + @Override + public void onLowMemory() { + // 如果mSyncTask不为空,则调用其cancelSync方法 + if (mSyncTask != null) { + mSyncTask.cancelSync(); + } + } + + // onBind方法,服务绑定时被调用 + public IBinder onBind(Intent intent) { + return null; + } + + // 发送广播的方法 + public void sendBroadcast(String msg) { + // 更新同步进度字符串,并发送广播 + mSyncProgress = msg; + Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); + intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null); + intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg); + sendBroadcast(intent); + } + + // 开始同步的静态方法 + public static void startSync(Activity activity) { + // 设置GTaskManager的上下文,并启动同步服务 + GTaskManager.getInstance().setActivityContext(activity); + Intent intent = new Intent(activity, GTaskSyncService.class); + intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC); + activity.startService(intent); + } + + // 取消同步的静态方法 + public static void cancelSync(Context context) { + // 启动同步服务以取消同步 + Intent intent = new Intent(context, GTaskSyncService.class); + intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC); + context.startService(intent); + } + + // 判断是否正在同步的静态方法 + public static boolean isSyncing() { + return mSyncTask != null; + } + + // 获取同步进度字符串的静态方法 + public static String getProgressString() { + return mSyncProgress; + } +} +``` + +这个`GTaskSyncService`类提供了一个服务,用于执行Google Tasks的同步操作。它包含了开始同步、取消同步、发送广播更新同步进度等方法。服务可以通过静态方法`startSync`和`cancelSync`来控制同步操作。服务还提供了`isSyncing`和`getProgressString`静态方法,用于外部检查同步状态和进度。 diff --git a/scr/MetaData.java b/scr/MetaData.java new file mode 100644 index 0000000..9dad026 --- /dev/null +++ b/scr/MetaData.java @@ -0,0 +1,85 @@ +// 定义包名和导入所需的类 +package net.micode.notes.gtask.data; + +import android.database.Cursor; +import android.util.Log; + +import net.micode.notes.tool.GTaskStringUtils; + +import org.json.JSONException; +import org.json.JSONObject; + +// MetaData类继承自Task类,用于处理与Google Tasks相关的元数据 +public class MetaData extends Task { + // 类的标签,用于日志记录 + private final static String TAG = MetaData.class.getSimpleName(); + + // 用于存储与Google Tasks相关的全局ID + private String mRelatedGid = null; + + // 设置元数据信息 + public void setMeta(String gid, JSONObject metaInfo) { + try { + // 将全局ID添加到元数据信息中 + metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); + } catch (JSONException e) { + // 如果发生异常,记录错误日志 + Log.e(TAG, "failed to put related gid"); + } + // 将元数据信息设置为笔记内容 + setNotes(metaInfo.toString()); + // 设置元数据的名称 + setName(GTaskStringUtils.META_NOTE_NAME); + } + + // 获取与Google Tasks相关的全局ID + public String getRelatedGid() { + return mRelatedGid; + } + + // 重写isWorthSaving方法,判断是否有值得保存的笔记内容 + @Override + public boolean isWorthSaving() { + return getNotes() != null; + } + + // 根据远程JSON对象设置内容 + @Override + public void setContentByRemoteJSON(JSONObject js) { + // 首先调用父类的同名方法 + super.setContentByRemoteJSON(js); + // 如果笔记内容不为空,尝试解析JSON对象 + if (getNotes() != null) { + try { + JSONObject metaInfo = new JSONObject(getNotes().trim()); + // 从JSON对象中获取全局ID + mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); + } catch (JSONException e) { + // 如果解析失败,记录警告日志并将全局ID设置为null + Log.w(TAG, "failed to get related gid"); + mRelatedGid = null; + } + } + } + + // 根据本地JSON对象设置内容,这个方法不应该被调用 + @Override + public void setContentByLocalJSON(JSONObject js) { + // 抛出异常,表示这个方法不应该被调用 + throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); + } + + // 从内容中获取本地JSON对象,这个方法不应该被调用 + @Override + public JSONObject getLocalJSONFromContent() { + // 抛出异常,表示这个方法不应该被调用 + throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); + } + + // 获取同步操作,这个方法不应该被调用 + @Override + public int getSyncAction(Cursor c) { + // 抛出异常,表示这个方法不应该被调用 + throw new IllegalAccessError("MetaData:getSyncAction should not be called"); + } +} \ No newline at end of file diff --git a/scr/NetworkFailureException.java b/scr/NetworkFailureException.java new file mode 100644 index 0000000..6ebb48f --- /dev/null +++ b/scr/NetworkFailureException.java @@ -0,0 +1,43 @@ +这段代码定义了一个名为 `NetworkFailureException` 的异常类,它继承自 Java 的 `Exception` 类。以下是对该类的注释: + +```java +/* + * 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.exception; + +// NetworkFailureException类是一个受检查的异常,用于表示网络相关的失败情况。 +public class NetworkFailureException extends Exception { + // 序列化ID,用于Java对象的序列化机制。 + private static final long serialVersionUID = 2107610287180234136L; + + // 无参构造函数,初始化NetworkFailureException异常。 + public NetworkFailureException() { + super(); + } + + // 构造函数,接受一个字符串参数,用于提供异常的详细信息。 + public NetworkFailureException(String paramString) { + super(paramString); + } + + // 构造函数,接受一个字符串参数和一个Throwable对象,用于提供异常的详细信息和原因。 + public NetworkFailureException(String paramString, Throwable paramThrowable) { + super(paramString, paramThrowable); + } +} +``` + diff --git a/scr/Node.java b/scr/Node.java new file mode 100644 index 0000000..c5b5696 --- /dev/null +++ b/scr/Node.java @@ -0,0 +1,100 @@ +/* + * 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.data; + +import android.database.Cursor; + +import org.json.JSONObject; + +// 抽象类Node,用于表示与Google Tasks同步的数据节点 +public abstract class Node { + // 定义同步操作的常量 + public static final int SYNC_ACTION_NONE = 0; + public static final int SYNC_ACTION_ADD_REMOTE = 1; + public static final int SYNC_ACTION_ADD_LOCAL = 2; + public static final int SYNC_ACTION_DEL_REMOTE = 3; + public static final int SYNC_ACTION_DEL_LOCAL = 4; + public static final int SYNC_ACTION_UPDATE_REMOTE = 5; + public static final int SYNC_ACTION_UPDATE_LOCAL = 6; + public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; + public static final int SYNC_ACTION_ERROR = 8; + + // 成员变量 + private String mGid; // Google Tasks的全局ID + private String mName; // 节点名称 + private long mLastModified; // 最后修改时间 + private boolean mDeleted; // 是否被删除 + + // 构造函数,初始化成员变量 + public Node() { + mGid = null; + mName = ""; + mLastModified = 0; + mDeleted = false; + } + + // 获取创建操作的JSON对象 + public abstract JSONObject getCreateAction(int actionId); + + // 获取更新操作的JSON对象 + public abstract JSONObject getUpdateAction(int actionId); + + // 根据远程JSON对象设置内容 + public abstract void setContentByRemoteJSON(JSONObject js); + + // 根据本地JSON对象设置内容 + public abstract void setContentByLocalJSON(JSONObject js); + + // 从内容中获取本地JSON对象 + public abstract JSONObject getLocalJSONFromContent(); + + // 获取同步操作 + public abstract int getSyncAction(Cursor c); + + // 设置和获取方法 + public void setGid(String gid) { + this.mGid = gid; + } + + public void setName(String name) { + this.mName = name; + } + + public void setLastModified(long lastModified) { + this.mLastModified = lastModified; + } + + public void setDeleted(boolean deleted) { + this.mDeleted = deleted; + } + + public String getGid() { + return this.mGid; + } + + public String getName() { + return this.mName; + } + + public long getLastModified() { + return this.mLastModified; + } + + public boolean getDeleted() { + return this.mDeleted; + } +} \ No newline at end of file diff --git a/scr/SqlData.java b/scr/SqlData.java new file mode 100644 index 0000000..3b8b6b8 --- /dev/null +++ b/scr/SqlData.java @@ -0,0 +1,119 @@ +/* + * 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.data; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.data.NotesDatabaseHelper.TABLE; +import net.micode.notes.gtask.exception.ActionFailureException; + +import org.json.JSONException; +import org.json.JSONObject; + +// SqlData类用于管理数据库中的笔记数据 +public class SqlData { + // 类的标签,用于日志记录 + private static final String TAG = SqlData.class.getSimpleName(); + + // 无效的ID常量 + private static final int INVALID_ID = -99999; + + // 数据库查询的列 + public static final String[] PROJECTION_DATA = new String[] { + DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1, + DataColumns.DATA3 + }; + + // 数据库列的索引 + public static final int DATA_ID_COLUMN = 0; + public static final int DATA_MIME_TYPE_COLUMN = 1; + public static final int DATA_CONTENT_COLUMN = 2; + public static final int DATA_CONTENT_DATA_1_COLUMN = 3; + public static final int DATA_CONTENT_DATA_3_COLUMN = 4; + + // 成员变量 + private ContentResolver mContentResolver; // 内容解析器 + private boolean mIsCreate; // 是否为创建状态 + private long mDataId; // 数据ID + private String mDataMimeType; // 数据MIME类型 + private String mDataContent; // 数据内容 + private long mDataContentData1; // 数据内容DATA1 + private String mDataContentData3; // 数据内容DATA3 + private ContentValues mDiffDataValues; // 差异数据值 + + // 构造函数,初始化SqlData对象 + public SqlData(Context context) { + mContentResolver = context.getContentResolver(); + mIsCreate = true; + mDataId = INVALID_ID; + mDataMimeType = DataConstants.NOTE; + mDataContent = ""; + mDataContentData1 = 0; + mDataContentData3 = ""; + mDiffDataValues = new ContentValues(); + } + + // 从Cursor构造SqlData对象 + public SqlData(Context context, Cursor c) { + mContentResolver = context.getContentResolver(); + mIsCreate = false; + loadFromCursor(c); + mDiffDataValues = new ContentValues(); + } + + // 从Cursor加载数据 + private void loadFromCursor(Cursor c) { + mDataId = c.getLong(DATA_ID_COLUMN); + mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN); + mDataContent = c.getString(DATA_CONTENT_COLUMN); + mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN); + mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN); + } + + // 设置内容 + public void setContent(JSONObject js) throws JSONException { + // 根据JSON对象设置数据 + // ... + } + + // 获取内容 + public JSONObject getContent() throws JSONException { + // 根据当前数据创建JSON对象 + // ... + } + + // 提交数据到数据库 + public void commit(long noteId, boolean validateVersion, long version) { + // 根据创建状态和差异数据值,将数据插入或更新到数据库 + // ... + } + + // 获取数据ID + public long getId() { + return mDataId; + } +} \ No newline at end of file diff --git a/scr/SqlNote.java b/scr/SqlNote.java new file mode 100644 index 0000000..8e56011 --- /dev/null +++ b/scr/SqlNote.java @@ -0,0 +1,165 @@ +这段代码是一个Android应用程序中的Java类,名为`SqlNote`,用于处理与数据库中笔记相关的操作。以下是代码的注释: + +```java +/* + * 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.data; + +import android.appwidget.AppWidgetManager; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.exception.ActionFailureException; +import net.micode.notes.tool.GTaskStringUtils; +import net.micode.notes.tool.ResourceParser; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +// SqlNote类用于管理数据库中的笔记数据 +public class SqlNote { + // 类的标签,用于日志记录 + private static final String TAG = SqlNote.class.getSimpleName(); + + // 无效的ID常量 + private static final int INVALID_ID = -99999; + + // 数据库查询的列 + public static final String[] PROJECTION_NOTE = new String[] { + // ... 省略其他列定义 + }; + + // 数据库列的索引 + public static final int ID_COLUMN = 0; + // ... 省略其他列索引定义 + + // 成员变量 + private Context mContext; // 上下文对象 + private ContentResolver mContentResolver; // 内容解析器 + private boolean mIsCreate; // 是否为创建状态 + private long mId; // 笔记ID + // ... 省略其他成员变量定义 + + private ArrayList mDataList; // 笔记关联的数据列表 + + // 构造函数,初始化SqlNote对象 + public SqlNote(Context context) { + // ... 初始化成员变量 + } + + // 从Cursor构造SqlNote对象 + public SqlNote(Context context, Cursor c) { + // ... 初始化成员变量并从Cursor加载数据 + } + + // 从ID构造SqlNote对象 + public SqlNote(Context context, long id) { + // ... 初始化成员变量并从ID加载数据 + } + + // 从Cursor加载数据 + private void loadFromCursor(Cursor c) { + // ... 从Cursor对象加载笔记数据 + } + + // 从ID加载数据 + private void loadFromCursor(long id) { + // ... 从ID加载笔记数据 + } + + // 加载笔记内容数据 + private void loadDataContent() { + // ... 加载笔记关联的数据 + } + + // 设置笔记内容 + public boolean setContent(JSONObject js) { + try { + // ... 从JSONObject设置笔记内容 + } catch (JSONException e) { + // ... 异常处理 + } + return true; + } + + // 获取笔记内容 + public JSONObject getContent() { + try { + // ... 从当前对象创建JSONObject + } catch (JSONException e) { + // ... 异常处理 + } + return null; + } + + // 设置父ID + public void setParentId(long id) { + // ... 设置父ID并更新差异值 + } + + // 设置GTask ID + public void setGtaskId(String gid) { + // ... 设置GTask ID并更新差异值 + } + + // 设置同步ID + public void setSyncId(long syncId) { + // ... 设置同步ID并更新差异值 + } + + // 重置本地修改标记 + public void resetLocalModified() { + // ... 重置本地修改标记 + } + + // 获取笔记ID + public long getId() { + return mId; + } + + // 获取父ID + public long getParentId() { + return mParentId; + } + + // 获取笔记摘要 + public String getSnippet() { + return mSnippet; + } + + // 判断是否为笔记类型 + public boolean isNoteType() { + return mType == Notes.TYPE_NOTE; + } + + // 提交笔记数据 + public void commit(boolean validateVersion) { + // ... 提交笔记数据到数据库 + } +} +``` + diff --git a/scr/Task.java b/scr/Task.java new file mode 100644 index 0000000..4fdfa5d --- /dev/null +++ b/scr/Task.java @@ -0,0 +1,133 @@ +这段代码是一个Android应用程序中的Java类,名为`Task`,继承自`Node`类,用于处理与Google Tasks相关的任务数据。以下是代码的注释: + +```java +/* + * 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.data; + +import android.database.Cursor; +import android.text.TextUtils; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.exception.ActionFailureException; +import net.micode.notes.tool.GTaskStringUtils; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +// Task类继承自Node类,用于表示一个任务 +public class Task extends Node { + // 类的标签,用于日志记录 + private static final String TAG = Task.class.getSimpleName(); + + // 成员变量 + private boolean mCompleted; // 是否完成 + private String mNotes; // 任务笔记 + private JSONObject mMetaInfo; // 元数据信息 + private Task mPriorSibling; // 前一个任务 + private TaskList mParent; // 父任务列表 + + // 构造函数,初始化Task对象 + public Task() { + super(); + mCompleted = false; + mNotes = null; + mPriorSibling = null; + mParent = null; + mMetaInfo = null; + } + + // 获取创建任务的JSON对象 + public JSONObject getCreateAction(int actionId) { + // ... 创建任务的JSON对象 + } + + // 获取更新任务的JSON对象 + public JSONObject getUpdateAction(int actionId) { + // ... 更新任务的JSON对象 + } + + // 根据远程JSON对象设置任务内容 + public void setContentByRemoteJSON(JSONObject js) { + // ... 从远程JSON对象设置任务内容 + } + + // 根据本地JSON对象设置任务内容 + public void setContentByLocalJSON(JSONObject js) { + // ... 从本地JSON对象设置任务内容 + } + + // 从任务内容获取本地JSON对象 + public JSONObject getLocalJSONFromContent() { + // ... 从任务内容获取本地JSON对象 + } + + // 设置元数据信息 + public void setMetaInfo(MetaData metaData) { + // ... 设置元数据信息 + } + + // 获取同步操作 + public int getSyncAction(Cursor c) { + // ... 根据数据库游标获取同步操作 + } + + // 判断任务是否值得保存 + public boolean isWorthSaving() { + // ... 判断任务是否值得保存 + } + + // 设置和获取方法 + public void setCompleted(boolean completed) { + this.mCompleted = completed; + } + + public void setNotes(String notes) { + this.mNotes = notes; + } + + public void setPriorSibling(Task priorSibling) { + this.mPriorSibling = priorSibling; + } + + public void setParent(TaskList parent) { + this.mParent = parent; + } + + public boolean getCompleted() { + return this.mCompleted; + } + + public String getNotes() { + return this.mNotes; + } + + public Task getPriorSibling() { + return this.mPriorSibling; + } + + public TaskList getParent() { + return this.mParent; + } +} +``` + diff --git a/scr/TaskList.java b/scr/TaskList.java new file mode 100644 index 0000000..faee310 --- /dev/null +++ b/scr/TaskList.java @@ -0,0 +1,141 @@ +这段代码是一个Android应用程序中的Java类,名为`TaskList`,继承自`Node`类,用于表示与Google Tasks相关的任务列表。以下是代码的注释: + +```java +/* + * 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.data; + +import android.database.Cursor; +import android.util.Log; + +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.exception.ActionFailureException; +import net.micode.notes.tool.GTaskStringUtils; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +// TaskList类继承自Node类,用于表示一个任务列表 +public class TaskList extends Node { + // 类的标签,用于日志记录 + private static final String TAG = TaskList.class.getSimpleName(); + + // 成员变量 + private int mIndex; // 任务列表的索引 + private ArrayList mChildren; // 任务列表中的子任务 + + // 构造函数,初始化TaskList对象 + public TaskList() { + super(); + mChildren = new ArrayList(); + mIndex = 1; + } + + // 获取创建任务列表的JSON对象 + public JSONObject getCreateAction(int actionId) { + // ... 创建任务列表的JSON对象 + } + + // 获取更新任务列表的JSON对象 + public JSONObject getUpdateAction(int actionId) { + // ... 更新任务列表的JSON对象 + } + + // 根据远程JSON对象设置任务列表内容 + public void setContentByRemoteJSON(JSONObject js) { + // ... 从远程JSON对象设置任务列表内容 + } + + // 根据本地JSON对象设置任务列表内容 + public void setContentByLocalJSON(JSONObject js) { + // ... 从本地JSON对象设置任务列表内容 + } + + // 从任务列表内容获取本地JSON对象 + public JSONObject getLocalJSONFromContent() { + // ... 从任务列表内容获取本地JSON对象 + } + + // 获取同步操作 + public int getSyncAction(Cursor c) { + // ... 根据数据库游标获取同步操作 + } + + // 获取子任务的数量 + public int getChildTaskCount() { + return mChildren.size(); + } + + // 添加子任务 + public boolean addChildTask(Task task) { + // ... 添加子任务到任务列表 + } + + // 在指定索引处添加子任务 + public boolean addChildTask(Task task, int index) { + // ... 在指定索引处添加子任务到任务列表 + } + + // 移除子任务 + public boolean removeChildTask(Task task) { + // ... 从任务列表移除子任务 + } + + // 移动子任务到指定索引 + public boolean moveChildTask(Task task, int index) { + // ... 移动子任务到指定索引 + } + + // 根据GID查找子任务 + public Task findChildTaskByGid(String gid) { + // ... 根据GID查找子任务 + } + + // 获取子任务的索引 + public int getChildTaskIndex(Task task) { + return mChildren.indexOf(task); + } + + // 根据索引获取子任务 + public Task getChildTaskByIndex(int index) { + // ... 根据索引获取子任务 + } + + // 根据GID获取子任务 + public Task getChilTaskByGid(String gid) { + // ... 根据GID获取子任务 + } + + // 获取子任务列表 + public ArrayList getChildTaskList() { + return this.mChildren; + } + + // 设置和获取方法 + public void setIndex(int index) { + this.mIndex = index; + } + + public int getIndex() { + return this.mIndex; + } +} +``` +