Compare commits

...

2 Commits

Author SHA1 Message Date
蔡玉祥 026e1f0cba Merge branch 'master' of https://bdgit.educoder.net/mbhvfy6mx/gitProject
2 years ago
蔡玉祥 1446cf7d54 更新
2 years ago

@ -10,84 +10,35 @@
</component>
<component name="ChangeListManager">
<list default="true" id="2531eea7-ec98-43ef-9f7f-09fe1004db56" name="变更" comment="庞浩的注释">
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/checksums/checksums.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/checksums/md5-checksums.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/checksums/sha1-checksums.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/dependencies-accessors/dependencies-accessors.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/dependencies-accessors/gc.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/executionHistory/executionHistory.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/fileChanges/last-build.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/fileHashes/fileHashes.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.4.2/gc.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/checksums/checksums.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/checksums/md5-checksums.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/checksums/sha1-checksums.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/dependencies-accessors/dependencies-accessors.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/dependencies-accessors/gc.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/executionHistory/executionHistory.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/executionHistory/executionHistory.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/fileChanges/last-build.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/fileHashes/fileHashes.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/fileHashes/fileHashes.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/fileHashes/resourceHashesCache.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/7.5/gc.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/buildOutputCleanup/buildOutputCleanup.lock" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/buildOutputCleanup/cache.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/buildOutputCleanup/outputFiles.bin" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/file-system.probe" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.gradle/vcs-1/gc.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/.gitignore" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/compiler.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/deploymentTargetDropDown.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/gradle.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/jarRepositories.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/misc.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/modules.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.androidTest.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.main.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.unitTest.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/build.gradle" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/gradle/wrapper/gradle-wrapper.jar" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/gradle/wrapper/gradle-wrapper.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/gradlew" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/gradlew.bat" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/import-summary.txt" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/local.properties" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/minote.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/settings.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.gitignore" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/compiler.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/deploymentTargetDropDown.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/gradle.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/jarRepositories.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules/app/minote.app.androidTest.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules/app/minote.app.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules/app/minote.app.main.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules/app/minote.app.unitTest.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/vcs.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/net/micode/notes/data/NotesProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/net/micode/notes/data/NotesProvider.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/net/micode/notes/model/Note.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/net/micode/notes/model/Note.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/net/micode/notes/model/WorkingNote.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/net/micode/notes/model/WorkingNote.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/build.gradle" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/gradle/wrapper/gradle-wrapper.jar" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/gradle/wrapper/gradle-wrapper.properties" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/gradlew" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/gradlew.bat" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/import-summary.txt" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/local.properties" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/minote.iml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/settings.gradle" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/compiler.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/compiler.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/deploymentTargetDropDown.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/deploymentTargetDropDown.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/gradle.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/gradle.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/modules.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/modules.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.androidTest.iml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.androidTest.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.iml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.main.iml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.main.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.unitTest.iml" beforeDir="false" afterPath="$PROJECT_DIR$/src/.idea/modules/app/minote.app.unitTest.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/MetaData.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/MetaData.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/Node.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/Node.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/SqlData.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/SqlData.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/Task.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/Task.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/TaskList.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/data/TaskList.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/exception/ActionFailureException.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/exception/NetworkFailureException.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/src/main/java/net/micode/notes/gtask/remote/GTaskClient.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/local.properties" beforeDir="false" afterPath="$PROJECT_DIR$/src/local.properties" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/minote.iml" beforeDir="false" afterPath="$PROJECT_DIR$/src/minote.iml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="device_and_snapshot_combo_box_target[C:\Users\庞浩的电脑\.android\avd\Pixel_3_API_22.avd]" />
<component name="ExecutionTargetManager" SELECTED_TARGET="device_and_snapshot_combo_box_target[C:\Users\蔡玉祥\.android\avd\Pixel_2_API_30.avd]" />
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
@ -115,7 +66,7 @@
&quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;D:/softwareengineering/Notes-master&quot;,
&quot;last_opened_file_path&quot;: &quot;D:/TOUGE/gitProject&quot;,
&quot;project.structure.last.edited&quot;: &quot;Modules&quot;,
&quot;project.structure.proportion&quot;: &quot;0.17&quot;,
&quot;project.structure.side.proportion&quot;: &quot;0.2&quot;,
@ -177,9 +128,7 @@
<option name="ACTIVITY_CLASS" value="" />
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
<method v="2" />
</configuration>
<configuration name="D:/softwareengineering/minote/app/build.gradle" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>

@ -12,10 +12,18 @@
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<<<<<<< HEAD
<<<<<<< HEAD:src/.idea/deploymentTargetDropDown.xml
<timeTargetWasSelectedWithDropDown value="2023-04-07T06:36:29.852905700Z" />
=======
<timeTargetWasSelectedWithDropDown value="2023-04-07T06:44:46.634860500Z" />
>>>>>>> cyx_branch:.idea/deploymentTargetDropDown.xml
=======
<<<<<<< HEAD:.idea/deploymentTargetDropDown.xml
<timeTargetWasSelectedWithDropDown value="2023-04-07T06:44:46.634860500Z" />
=======
<timeTargetWasSelectedWithDropDown value="2023-04-07T06:36:29.852905700Z" />
>>>>>>> master:src/.idea/deploymentTargetDropDown.xml
>>>>>>> 25eb5a04c09307c5edd9569e8d491a90234c9d82
</component>
</project>

@ -45,6 +45,13 @@ public class SqlData {
DataColumns.DATA3
};
/*JavaSqlData
<<<<<<< HEAD
TAGSqlData
INVALID_IDID-99999
PROJECTION_DATADataColumnsIDMIME_TYPECONTENTDATA1DATA3
访
使*/
=======
TAGSqlData
@ -53,6 +60,7 @@ public class SqlData {
PROJECTION_DATADataColumnsIDMIME_TYPECONTENTDATA1DATA3
访使*/
>>>>>>> 25eb5a04c09307c5edd9569e8d491a90234c9d82
public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1;

@ -51,7 +51,28 @@ public class SqlNote {
NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID,
NoteColumns.VERSION
};
/*SqlNotePROJECTION_NOTE
PROJECTION_NOTE
ID
ALERTED_DATE
BG_COLOR_ID
CREATED_DATE
HAS_ATTACHMENT
MODIFIED_DATE
NOTES_COUNT
PARENT_ID
WIDGET_ID
WIDGET_TYPE
SYNC_ID
LOCAL_MODIFIED
ORIGIN_PARENT_ID
GTASK_ID Google Tasks
SqlNote便使*/
public static final int ID_COLUMN = 0;
public static final int ALERTED_DATE_COLUMN = 1;
@ -85,7 +106,9 @@ public class SqlNote {
public static final int GTASK_ID_COLUMN = 15;
public static final int VERSION_COLUMN = 16;
/*SqlNotePROJECTION_NOTE
访
*/
private Context mContext;
private ContentResolver mContentResolver;
@ -121,7 +144,28 @@ public class SqlNote {
private ContentValues mDiffNoteValues;
private ArrayList<SqlData> mDataList;
/*SqlNote
mContext 访
mContentResolver 访
mIsCreate
mId
mAlertDate
mBgColorId
mCreatedDate
mHasAttachment
mModifiedDate
mParentId:
mSnippet:
mType:
mWidgetId:
mWidgetType:
mOriginParent:
mVersion:
mDiffNoteValues: ContentValues
mDataList: ArrayList
SqlNote
*/
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
@ -142,7 +186,26 @@ public class SqlNote {
mDiffNoteValues = new ContentValues();
mDataList = new ArrayList<SqlData>();
}
/*SqlNoteSqlNoteSqlNote
mContext
mContentResolver
mIsCreate true
mId INVALID_ID
mAlertDate 0
mBgColorId
mCreatedDate
mHasAttachment 0
mModifiedDate
mParentId 0
mSnippet
mType Notes.TYPE_NOTE
mWidgetId AppWidgetManager.INVALID_APPWIDGET_ID
mWidgetType Notes.TYPE_WIDGET_INVALIDE
mOriginParent 0
mVersion 00
mDiffNoteValues ContentValues
mDataList ArrayList
SqlNote*/
public SqlNote(Context context, Cursor c) {
mContext = context;
mContentResolver = context.getContentResolver();
@ -153,7 +216,15 @@ public class SqlNote {
loadDataContent();
mDiffNoteValues = new ContentValues();
}
/*SqlNoteSqlNoteSqlNote
mContext
mContentResolver
mIsCreate falseSqlNote
loadFromCursorc loadFromCursorc
mDataList ArrayList
loadDataContent loadDataContent
mDiffNoteValues ContentValues
SqlNote*/
public SqlNote(Context context, long id) {
mContext = context;
mContentResolver = context.getContentResolver();
@ -165,7 +236,15 @@ public class SqlNote {
mDiffNoteValues = new ContentValues();
}
/*SqlNoteidSqlNoteSqlNote
mContext
mContentResolver
mIsCreate falseSqlNote
loadFromCursorid loadFromCursorid
mDataList ArrayList
loadDataContent loadDataContent
mDiffNoteValues ContentValues
SqlNoteid*/
private void loadFromCursor(long id) {
Cursor c = null;
try {
@ -184,7 +263,11 @@ public class SqlNote {
c.close();
}
}
/*SqlNoteid
Notes.CONTENT_NOTE_URIID
nullloadFromCursor(Cursor c)SqlNote
SqlNoteid*/
private void loadFromCursor(Cursor c) {
mId = c.getLong(ID_COLUMN);
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
@ -199,7 +282,22 @@ public class SqlNote {
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN);
}
/*SqlNote
cSqlNote
mId
mAlertDate
mBgColorId
mCreatedDate
mHasAttachment 01
mModifiedDate
mParentId
mSnippet
mType 便
mWidgetId
mWidgetType
m
SqlNote*/
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
@ -225,13 +323,24 @@ public class SqlNote {
c.close();
}
}
/*SqlNote
Notes.CONTENT_DATA_URIID
mDataList
null使SqlDatamDataList
SqlNoteid*/
public boolean setContent(JSONObject js) {
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
Log.w(TAG, "cannot set system folder");
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
}
/*SqlNote
Jsonjsnote
Notes.TYPE_SYSTEMfalse
falseSqlNoteJson*/
else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
// for folder we can only update the snnipet and type
String snippet = note.has(NoteColumns.SNIPPET) ? note
.getString(NoteColumns.SNIPPET) : "";
@ -246,42 +355,60 @@ public class SqlNote {
mDiffNoteValues.put(NoteColumns.TYPE, type);
}
mType = type;
} else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
}
/*Notes.TYPE_FOLDERNoteColumns.SNIPPETNoteColumns.TYPE
JsonNoteColumns.SNIPPET
SqlNote
mSnippetsnippet
JsonNoteColumns.TYPEtypeNotes.TYPE_NOTE
SqlNote
mTypetype
SqlNoteJson*/
else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) {
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID;
if (mIsCreate || mId != id) {
mDiffNoteValues.put(NoteColumns.ID, id);
}
mId = id;
/*JSONArraydataArray JSON js.
mIsCreate true ID mId ID ID HashMapmDiffNoteValues使put()NoteColumns.ID ID*/
long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note
.getLong(NoteColumns.ALERTED_DATE) : 0;
if (mIsCreate || mAlertDate != alertDate) {
mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate);
}
mAlertDate = alertDate;
/*has()NoteColumns.ALERTED_DATEgetLong()NoteColumns.ALERTED_DATE 0
mIsCreate true mAlertDateHashMapmDiffNoteValues使put()NoteColumns.ALERTED_DATE
mAlertDate.使*/
int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note
.getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext);
if (mIsCreate || mBgColorId != bgColorId) {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
}
mBgColorId = bgColorId;
/*
mIsCreate true ID truemBgColorId ID ID HashMapmDiffNoteValues使put()NoteColumns.BG_COLOR_ID
ID mBgColorId.使*/
long createDate = note.has(NoteColumns.CREATED_DATE) ? note
.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
if (mIsCreate || mCreatedDate != createDate) {
mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate);
}
mCreatedDate = createDate;
/*has()NoteColumns.CREATED_DATEgetLong()NoteColumns.CREATED_DATESystem.currentTimeMillis()
mIsCreatemCreatedDateHashMapmDiffNoteValues使put()NoteColumns.CREATED_DATE
mCreatedDate.*/
int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note
.getInt(NoteColumns.HAS_ATTACHMENT) : 0;
if (mIsCreate || mHasAttachment != hasAttachment) {
mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment);
}
mHasAttachment = hasAttachment;
/* 0
true 使*/
long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note
.getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis();
if (mIsCreate || mModifiedDate != modifiedDate) {
@ -323,14 +450,22 @@ public class SqlNote {
mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType);
}
mWidgetType = widgetType;
/*
mModifiedDate
ID0IDIDIDmParentId
mSnippet
NotemType
IDIDIDIDIDmWidgetId
mWidgetType*/
long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note
.getLong(NoteColumns.ORIGIN_PARENT_ID) : 0;
if (mIsCreate || mOriginParent != originParent) {
mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent);
}
mOriginParent = originParent;
/*ID0ID
ID
IDmOriginParent*/
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
SqlData sqlData = null;
@ -342,12 +477,15 @@ public class SqlNote {
}
}
}
/*使forJSON
JSONIDSqlDataIDSqlDataSqlDatasqlData
sqlDatanull*/
if (sqlData == null) {
sqlData = new SqlData(mContext);
mDataList.add(sqlData);
}
/*JSONIDSqlDataSqlData
SqlDatasqlData*/
sqlData.setContent(data);
}
}
@ -358,7 +496,9 @@ public class SqlNote {
}
return true;
}
/*JSONIDSqlDatasetContentJSON使JSONSqlDataSqlData
try-catchJSONException
true*/
public JSONObject getContent() {
try {
JSONObject js = new JSONObject();
@ -367,7 +507,10 @@ public class SqlNote {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
/*JSONObjectmIsCreate
trueSqlDatanull
使putSqlDataJSONObject
SqlDataJSONObject*/
JSONObject note = new JSONObject();
if (mType == Notes.TYPE_NOTE) {
note.put(NoteColumns.ID, mId);
@ -392,7 +535,11 @@ public class SqlNote {
}
}
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
}
/*JSONObjectnote使putSqlDatanoteJSONObjectjs使putGTaskStringUtils.META_HEAD_NOTE
JSONArraydataArray使formDataListSqlDataSqlDatagetContentJSONnullnulldataArray
dataArrayjs使putGTaskStringUtils.META_HEAD_DATAmTypeNotes.TYPE_NOTEjs*/
else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.SNIPPET, mSnippet);
@ -406,7 +553,9 @@ public class SqlNote {
}
return null;
}
/*mTypeNotes.TYPE_FOLDERNotes.TYPE_SYSTEMJSONObjectnote使putSqlDatanoteJSONObjectjs使putGTaskStringUtils.META_HEAD_NOTE
JSONExceptionnullSqlDataJSONObjectjs
SqlDataJSONJSONObject*/
public void setParentId(long id) {
mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
@ -439,7 +588,14 @@ public class SqlNote {
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE;
}
/*setParentId(long id): idmParentId使putNoteColumns.PARENT_IDidmDiffNoteValues
setGtaskId(String gid): 使putNoteColumns.GTASK_IDgidmDiffNoteValues
setSyncId(long syncId): 使putNoteColumns.SYNC_IDsyncIdmDiffNoteValues
resetLocalModified(): 使put0NoteColumns.LOCAL_MODIFIEDmDiffNoteValuesSqlData
getId(): mId
getParentId(): mParentId
getSnippet(): mSnippet
isNoteType(): mTypeNotes.TYPE_NOTEtruefalseSqlData*/
public void commit(boolean validateVersion) {
if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
@ -462,7 +618,11 @@ public class SqlNote {
sqlData.commit(mId, false, -1);
}
}
} else {
}
/*mIsCreatetrueSqlDatamIdINVALID_ID-1mDiffNoteValuesNoteColumns.IDmDiffNoteValues使insertmDiffNoteValuesNotes.CONTENT_NOTE_URIUriuri
使getPathSegmentsurilongmIdNumberFormatExceptionActionFailureExceptionmId0IllegalStateException
mTypeNotes.TYPE_NOTESqlDatamDataListSqlDataSqlDatacommitmId便*/
else {
if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) {
Log.e(TAG, "No such note");
throw new IllegalStateException("Try to update note with invalid id");
@ -503,3 +663,8 @@ public class SqlNote {
mIsCreate = false;
}
}
/*mIsCreatefalseSqlDatamIdmId0Notes.ID_ROOT_FOLDERNotes.ID_CALL_RECORD_FOLDERIllegalStateExceptionmDiffNoteValuesmVersion使update
validateVersiontruemVersionupdateWHEREvalidateVersionfalse
0update
mTypeNotes.TYPE_NOTESqlDatamDataListSqlDataSqlDatacommitmIdvalidateVersion
mDiffNoteValuesmIsCreatefalse*/

@ -53,10 +53,22 @@ public class Task extends Node {
mParent = null;
mMetaInfo = null;
}
/*TaskJavaNodeTask
mCompleted
mNotes
mMetaInfoJSONObject
mPriorSiblingTask
mParentTaskList
TaskmCompletedmNotesmPriorSiblingmParentmMetaInfonullfalse
NodeNodeTaskListTaskmPriorSiblingmParentmMetaInfo*/
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
/*JSONObject
actionIdID
JSONObjectjs
"type""action"
ID"action_id"actionId
js*/
try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
@ -74,6 +86,12 @@ public class Task extends Node {
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_TASK);
/*getCreateActionJSONObject jsGTaskStringUtils.GTASK_JSON_ACTION_TYPEGTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE
IDGTaskStringUtils.GTASK_JSON_ACTION_IDactionId
GTaskStringUtils.GTASK_JSON_INDEXmParent.getChildTaskIndex(this)
"entity_delta"JSONObjectentityentityID
getName()ID"null"GTaskStringUtils.GTASK_JSON_TYPE_TASK
js*/
if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
}
@ -88,7 +106,11 @@ public class Task extends Node {
// list_id
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
/*entityGTaskStringUtils.GTASK_JSON_NOTESgetNotes()entityjsGTaskStringUtils.GTASK_JSON_ENTITY_DELTA
IDGTaskStringUtils.GTASK_JSON_PARENT_IDGIDmParent.getGid()
GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPEGTaskStringUtils.GTASK_JSON_TYPE_GROUP
IDGTaskStringUtils.GTASK_JSON_LIST_IDGID
js*/
// prior_sibling_id
if (mPriorSibling != null) {
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());
@ -101,69 +123,75 @@ public class Task extends Node {
}
return js;
}
}/*ID
js ID GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID GID mPriorSibling.getGid()
JSONException ActionFailureException
JSONObject */
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// action_type
// action_type 字段设置为 GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// action_id
// action_id 字段设置为传入的 actionId 参数
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// id
// id 字段设置为当前任务的 GID
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// entity_delta
// 将 entity_delta 字段设置为一个 JSONObject 对象,
// 该对象表示要更新的任务的属性和值
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
if (getNotes() != null) {
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 任务名称
if (getNotes() != null) { // 如果任务的注释不为空,则添加注释字段
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
}
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); // 任务是否被删除
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) {
// 如果出现 JSONException 异常,则打印异常信息,并抛出 ActionFailureException 异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to generate task-update jsonobject");
}
// 返回表示更新任务的动作的 JSONObject 对象
return js;
}
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
try {
// id
// 解析 id 字段,将其设置为本地任务对象的 GID
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
}
// last_modified
// 解析 last_modified 字段,将其设置为本地任务对象的最后修改时间
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
}
// name
// 解析 name 字段,将其设置为本地任务对象的名称
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
}
// notes
// 解析 notes 字段,将其设置为本地任务对象的注释
if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
}
// deleted
// 解析 deleted 字段,将其设置为本地任务对象的删除状态
if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
}
// completed
// 解析 completed 字段,将其设置为本地任务对象的完成状态
if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) {
setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED));
}
@ -182,14 +210,19 @@ public class Task extends Node {
}
try {
// 解析任务的注释信息
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 解析任务的数据信息
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 检查任务的类型是否为 Notes.TYPE_NOTE
if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) {
Log.e(TAG, "invalid type");
return;
}
// 解析任务的名称
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
@ -206,14 +239,16 @@ public class Task extends Node {
public JSONObject getLocalJSONFromContent() {
String name = getName();
try {
if (mMetaInfo == null) {
// new task created from web
// 如果当前任务对象没有元信息,则表示该任务是从 Web 创建的
if (name == null) {
Log.w(TAG, "the note seems to be an empty one");
return null;
}
// 创建一个新的 JSONObject并将任务的名称添加到其中
JSONObject js = new JSONObject();
JSONObject note = new JSONObject();
JSONArray dataArray = new JSONArray();
@ -225,10 +260,11 @@ public class Task extends Node {
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
return js;
} else {
// synced task
// 如果当前任务对象有元信息,则表示该任务是同步过来的
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 遍历任务的数据信息,找到 MIME_TYPE 为 DataConstants.NOTE 的 JSONObject并将其 CONTENT 字段设置为任务的名称
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
@ -237,6 +273,7 @@ public class Task extends Node {
}
}
// 将任务的类型设置为 Notes.TYPE_NOTE并返回元信息对象
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
return mMetaInfo;
}
@ -247,9 +284,11 @@ public class Task extends Node {
}
}
public void setMetaInfo(MetaData metaData) {
if (metaData != null && metaData.getNotes() != null) {
try {
// 将元数据对象的 notes 字段转换为 JSONObject 对象,并存储在当前对象的 mMetaInfo 变量中
mMetaInfo = new JSONObject(metaData.getNotes());
} catch (JSONException e) {
Log.w(TAG, e.toString());
@ -261,45 +300,49 @@ public class Task extends Node {
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null;
// 从 mMetaInfo 变量中获取笔记的元数据信息
if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) {
noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
}
if (noteInfo == null) {
// 如果笔记的元数据信息不存在,则需要更新远程数据
Log.w(TAG, "it seems that note meta has been deleted");
return SYNC_ACTION_UPDATE_REMOTE;
}
if (!noteInfo.has(NoteColumns.ID)) {
// 如果笔记的元数据信息中没有 ID 字段,则需要更新本地数据
Log.w(TAG, "remote note id seems to be deleted");
return SYNC_ACTION_UPDATE_LOCAL;
}
// validate the note id now
// 检查笔记的 ID 是否匹配
if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) {
Log.w(TAG, "note id doesn't match");
return SYNC_ACTION_UPDATE_LOCAL;
}
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
// there is no local update
// 如果本地没有修改笔记,则比较修改时间来判断是否需要更新数据
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// no update both side
// 本地和远程都没有修改,无需同步
return SYNC_ACTION_NONE;
} else {
// apply remote to local
// 将远程数据应用到本地
return SYNC_ACTION_UPDATE_LOCAL;
}
} else {
// validate gtask id
// 如果本地有修改笔记,则需要比较修改时间和 GTask ID 来判断同步操作
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "gtask id doesn't match");
return SYNC_ACTION_ERROR;
}
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// local modification only
// 只有本地有修改,将本地数据更新到远程
return SYNC_ACTION_UPDATE_REMOTE;
} else {
// 本地和远程都有修改,需要解决冲突
return SYNC_ACTION_UPDATE_CONFLICT;
}
}
@ -312,39 +355,49 @@ public class Task extends Node {
}
public boolean isWorthSaving() {
return mMetaInfo != null || (getName() != null && getName().trim().length() > 0)
|| (getNotes() != null && getNotes().trim().length() > 0);
// 判断对象是否值得保存
return mMetaInfo != null // 如果 mMetaInfo 不为空
|| (getName() != null && getName().trim().length() > 0) // 或者 name 不为空且去除空格后长度大于 0
|| (getNotes() != null && getNotes().trim().length() > 0); // 或者 notes 不为空且去除空格后长度大于 0
}
public void setCompleted(boolean completed) {
// 设置对象的 mCompleted 变量为给定的布尔值
this.mCompleted = completed;
}
public void setNotes(String notes) {
// 设置对象的 mNotes 变量为给定的字符串
this.mNotes = notes;
}
public void setPriorSibling(Task priorSibling) {
// 设置对象的 mPriorSibling 变量为给定的 Task 对象
this.mPriorSibling = priorSibling;
}
public void setParent(TaskList parent) {
// 设置对象的 mParent 变量为给定的 TaskList 对象
this.mParent = parent;
}
public boolean getCompleted() {
// 返回对象的 mCompleted 变量
return this.mCompleted;
}
public String getNotes() {
// 返回对象的 mNotes 变量
return this.mNotes;
}
public Task getPriorSibling() {
// 返回对象的 mPriorSibling 变量,其中 mPriorSibling 是一个 Task 对象
return this.mPriorSibling;
}
public TaskList getParent() {
// 返回对象的 mParent 变量,其中 mParent 是一个 TaskList 对象
return this.mParent;
}

@ -31,180 +31,189 @@ import java.util.ArrayList;
public class TaskList extends Node {
// 定义一个 TaskList 类,继承自 Node 类
private static final String TAG = TaskList.class.getSimpleName();
// 定义一个 TAG 常量,类型为字符串,值为 TaskList 类的简单名称
private int mIndex;
// 定义一个整型变量 mIndex用于存储任务列表的索引值
private ArrayList<Task> mChildren;
// 定义一个 ArrayList 类型的 mChildren 变量,用于存储该任务列表的子任务列表
public TaskList() {
// 默认构造方法
super();
// 调用父类的默认构造方法
mChildren = new ArrayList<Task>();
// 初始化 mChildren 变量为一个新的空的 ArrayList
mIndex = 1;
// 初始化 mIndex 变量为 1
}
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
JSONObject js = new JSONObject(); // 创建一个新的 JSONObject 对象
try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); // 添加 action_type 键值对,值为 "create"
// action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); // 添加 action_id 键值对,值为传入的参数 actionId
// index
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); // 添加 index 键值对,值为成员变量 mIndex 的值
// entity_delta
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
JSONObject entity = new JSONObject(); // 创建一个新的 JSONObject 对象,用于表示实体的 delta
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 添加 name 键值对,值为 getName() 方法的返回值
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); // 添加 creator_id 键值对,值为 "null"
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
GTaskStringUtils.GTASK_JSON_TYPE_GROUP); // 添加 entity_type 键值对,值为 "GROUP"
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); // 添加 entity_delta 键值对,值为上面创建的 entity 对象
} catch (JSONException e) {
Log.e(TAG, e.toString());
} catch (JSONException e) { // 如果在添加键值对的过程中出现 JSONException 异常
Log.e(TAG, e.toString()); // 打印异常堆栈跟踪信息
e.printStackTrace();
throw new ActionFailureException("fail to generate tasklist-create jsonobject");
throw new ActionFailureException("fail to generate tasklist-create jsonobject"); // 抛出一个自定义异常 ActionFailureException并传递一个异常信息字符串
}
return js;
return js; // 返回创建的 JSONObject 对象
}
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
JSONObject js = new JSONObject(); // 创建一个新的 JSONObject 对象
try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); // 添加 action_type 键值对,值为 "update"
// action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); // 添加 action_id 键值对,值为传入的参数 actionId
// id
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); // 添加 id 键值对,值为调用 getGid() 方法的返回值,表示任务列表的全局唯一标识符
// entity_delta
JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
JSONObject entity = new JSONObject(); // 创建一个新的 JSONObject 对象,用于表示实体的 delta
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); // 添加 name 键值对,值为 getName() 方法的返回值,表示任务列表的名称
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); // 添加 deleted 键值对,值为 getDeleted() 方法的返回值,表示任务列表是否被删除
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); // 添加 entity_delta 键值对,值为上面创建的 entity 对象
} catch (JSONException e) {
Log.e(TAG, e.toString());
} catch (JSONException e) { // 如果在添加键值对的过程中出现 JSONException 异常
Log.e(TAG, e.toString()); // 打印异常堆栈跟踪信息
e.printStackTrace();
throw new ActionFailureException("fail to generate tasklist-update jsonobject");
throw new ActionFailureException("fail to generate tasklist-update jsonobject"); // 抛出一个自定义异常 ActionFailureException并传递一个异常信息字符串
}
return js;
return js; // 返回创建的 JSONObject 对象
}
public void setContentByRemoteJSON(JSONObject js) {
if (js != null) {
if (js != null) { // 如果传入的 JSONObject 对象不为 null
try {
// id
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { // 如果 JSONObject 对象中包含 id 键值对
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); // 将 id 键对应的值作为参数调用 setGid() 方法,将任务列表的全局唯一标识符设置为该值
}
// last_modified
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { // 如果 JSONObject 对象中包含 last_modified 键值对
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); // 将 last_modified 键对应的值作为参数调用 setLastModified() 方法,将任务列表的最后修改时间设置为该值
}
// name
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { // 如果 JSONObject 对象中包含 name 键值对
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); // 将 name 键对应的值作为参数调用 setName() 方法,将任务列表的名称设置为该值
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
} catch (JSONException e) { // 如果在读取键值对的过程中出现 JSONException 异常
Log.e(TAG, e.toString()); // 打印异常堆栈跟踪信息
e.printStackTrace();
throw new ActionFailureException("fail to get tasklist content from jsonobject");
throw new ActionFailureException("fail to get tasklist content from jsonobject"); // 抛出一个自定义异常 ActionFailureException并传递一个异常信息字符串
}
}
}
public void setContentByLocalJSON(JSONObject js) {
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { // 如果传入的 JSONObject 对象为 null或者它不包含 META_HEAD_NOTE 键值对
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); // 打印一条警告日志,表示没有可用的信息
}
try {
JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
String name = folder.getString(NoteColumns.SNIPPET);
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name);
} else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER)
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT);
else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER)
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX
+ GTaskStringUtils.FOLDER_CALL_NOTE);
JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); // 获取 META_HEAD_NOTE 键对应的值,该值应该是一个 JSON 对象,表示笔记的元信息
if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { // 如果元信息中的 TYPE 键对应的值为 TYPE_FOLDER表示这是一个文件夹笔记
String name = folder.getString(NoteColumns.SNIPPET); // 获取元信息中的 SNIPPET 键对应的值,该值应该是文件夹的名称
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); // 将文件夹名称加上一个前缀字符串,作为任务列表的名称
} else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { // 如果元信息中的 TYPE 键对应的值为 TYPE_SYSTEM表示这是一个系统笔记
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) // 如果元信息中的 ID 键对应的值为 ID_ROOT_FOLDER表示这是根文件夹笔记
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT); // 将默认的任务列表名称设置为 MIUI_FOLDER_PREFFIX + FOLDER_DEFAULT
else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) // 如果元信息中的 ID 键对应的值为 ID_CALL_RECORD_FOLDER表示这是一条来电记录笔记
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE); // 将来电记录的任务列表名称设置为 MIUI_FOLDER_PREFFIX + FOLDER_CALL_NOTE
else
Log.e(TAG, "invalid system folder");
Log.e(TAG, "invalid system folder"); // 如果元信息中的 TYPE 和 ID 值都不符合要求,打印一条错误日志
} else {
Log.e(TAG, "error type");
Log.e(TAG, "error type"); // 如果元信息中的 TYPE 键对应的值既不是 TYPE_FOLDER也不是 TYPE_SYSTEM打印一条错误日志
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
} catch (JSONException e) { // 如果在读取元信息的过程中出现 JSONException 异常
Log.e(TAG, e.toString()); // 打印异常堆栈跟踪信息
e.printStackTrace();
}
}
public JSONObject getLocalJSONFromContent() {
try {
JSONObject js = new JSONObject();
JSONObject folder = new JSONObject();
String folderName = getName();
if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX))
folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(),
folderName.length());
folder.put(NoteColumns.SNIPPET, folderName);
if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT)
|| folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE))
folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
JSONObject js = new JSONObject(); // 创建一个新的 JSONObject 对象
JSONObject folder = new JSONObject(); // 创建一个新的 JSONObject 对象,表示笔记的元信息
String folderName = getName(); // 获取任务列表名称
if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)) // 如果任务列表名称以 MIUI_FOLDER_PREFFIX 开头
folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(), folderName.length()); // 将 MIUI_FOLDER_PREFFIX 从任务列表名称中去掉
folder.put(NoteColumns.SNIPPET, folderName); // 将去掉 MIUI_FOLDER_PREFFIX 的任务列表名称存入元信息中的 SNIPPET 键
if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT) || folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE)) // 如果任务列表名称是默认任务列表或来电记录任务列表
folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); // 将元信息中的 TYPE 键设置为 TYPE_SYSTEM
else
folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); // 否则将元信息中的 TYPE 键设置为 TYPE_FOLDER
js.put(GTaskStringUtils.META_HEAD_NOTE, folder);
js.put(GTaskStringUtils.META_HEAD_NOTE, folder); // 将元信息对象存入 js 对象中,以 META_HEAD_NOTE 键为键名
return js;
} catch (JSONException e) {
Log.e(TAG, e.toString());
return js; // 返回创建好的 JSONObject 对象
} catch (JSONException e) { // 如果在创建 JSONObject 对象的过程中出现异常
Log.e(TAG, e.toString()); // 打印异常信息
e.printStackTrace();
return null;
return null; // 返回 null
}
}
public int getSyncAction(Cursor c) {
try {
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
// there is no local update
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// no update both side
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { // 如果本地没有更新
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { // 如果本地最后一次修改时间与云端最后一次修改时间相同
// 两边都没有更新
return SYNC_ACTION_NONE;
} else {
// apply remote to local
// 将云端的修改应用到本地
return SYNC_ACTION_UPDATE_LOCAL;
}
} else {
// validate gtask id
} else { // 如果本地有更新
// 验证 gtask id 是否匹配
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "gtask id doesn't match");
return SYNC_ACTION_ERROR;
}
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// local modification only
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { // 如果本地最后一次修改时间与云端最后一次修改时间相同
// 只有本地修改
return SYNC_ACTION_UPDATE_REMOTE;
} else {
// for folder conflicts, just apply local modification
// 对于文件夹冲突,只应用本地修改
return SYNC_ACTION_UPDATE_REMOTE;
}
}
@ -213,38 +222,37 @@ public class TaskList extends Node {
e.printStackTrace();
}
return SYNC_ACTION_ERROR;
return SYNC_ACTION_ERROR; // 如果在执行过程中出现异常,返回 SYNC_ACTION_ERROR
}
public int getChildTaskCount() {
return mChildren.size();
}
}//返回一个私有成员变量mChildren中存储的子任务数量
public boolean addChildTask(Task task) {
boolean ret = false;
if (task != null && !mChildren.contains(task)) {
ret = mChildren.add(task);
if (task != null && !mChildren.contains(task)) { // 如果任务不为空且不包含在子任务列表中
ret = mChildren.add(task); // 添加任务到子任务列表中
if (ret) {
// need to set prior sibling and parent
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren
.get(mChildren.size() - 1));
task.setParent(this);
// 需要设置前一个兄弟和父任务
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren.get(mChildren.size() - 1)); // 设置前一个兄弟,如果子任务列表为空,则前一个兄弟为 null
task.setParent(this); // 设置父任务为当前任务
}
}
return ret;
}
public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index");
if (index < 0 || index > mChildren.size()) { // 如果索引位置小于 0 或大于子任务列表的大小
Log.e(TAG, "add child task: invalid index"); // 打印错误日志
return false;
}
int pos = mChildren.indexOf(task);
if (task != null && pos == -1) {
mChildren.add(index, task);
int pos = mChildren.indexOf(task); // 获取任务在子任务列表中的位置
if (task != null && pos == -1) { // 如果任务不为空且不在子任务列表中
mChildren.add(index, task); // 在指定索引位置添加任务
// update the task list
// 更新任务列表
Task preTask = null;
Task afterTask = null;
if (index != 0)
@ -252,9 +260,9 @@ public class TaskList extends Node {
if (index != mChildren.size() - 1)
afterTask = mChildren.get(index + 1);
task.setPriorSibling(preTask);
task.setPriorSibling(preTask); // 设置前一个兄弟任务
if (afterTask != null)
afterTask.setPriorSibling(task);
afterTask.setPriorSibling(task); // 设置后一个兄弟任务的前一个兄弟任务为当前任务
}
return true;
@ -262,16 +270,16 @@ public class TaskList extends Node {
public boolean removeChildTask(Task task) {
boolean ret = false;
int index = mChildren.indexOf(task);
if (index != -1) {
ret = mChildren.remove(task);
int index = mChildren.indexOf(task); // 获取任务在子任务列表中的位置
if (index != -1) { // 如果任务在子任务列表中
ret = mChildren.remove(task); // 从子任务列表中移除任务
if (ret) {
// reset prior sibling and parent
// 重置前一个兄弟任务和父任务
task.setPriorSibling(null);
task.setParent(null);
// update the task list
// 更新任务列表
if (index != mChildren.size()) {
mChildren.get(index).setPriorSibling(
index == 0 ? null : mChildren.get(index - 1));
@ -282,62 +290,61 @@ public class TaskList extends Node {
}
public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "move child task: invalid index");
if (index < 0 || index >= mChildren.size()) { // 如果索引位置小于 0 或大于等于子任务列表的大小
Log.e(TAG, "move child task: invalid index"); // 打印错误日志
return false;
}
int pos = mChildren.indexOf(task);
if (pos == -1) {
Log.e(TAG, "move child task: the task should in the list");
int pos = mChildren.indexOf(task); // 获取任务在子任务列表中的位置
if (pos == -1) { // 如果任务不在子任务列表中
Log.e(TAG, "move child task: the task should in the list"); // 打印错误日志
return false;
}
if (pos == index)
return true;
return (removeChildTask(task) && addChildTask(task, index));
return (removeChildTask(task) && addChildTask(task, index)); // 先将任务从原位置移除,再将其移动到新位置
}
public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) {
for (int i = 0; i < mChildren.size(); i++) { // 遍历子任务列表
Task t = mChildren.get(i);
if (t.getGid().equals(gid)) {
return t;
if (t.getGid().equals(gid)) { // 如果找到了 GID 匹配的任务
return t; // 返回该任务
}
}
return null;
return null; // 如果没有找到匹配的任务,则返回 null
}
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
return mChildren.indexOf(task); // 获取指定任务在子任务列表中的位置
}
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
if (index < 0 || index >= mChildren.size()) { // 如果索引位置小于 0 或大于等于子任务列表的大小
Log.e(TAG, "getTaskByIndex: invalid index"); // 打印错误日志
return null;
}
return mChildren.get(index);
return mChildren.get(index); // 返回指定位置的任务
}
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
return task;
for (Task task : mChildren) { // 遍历子任务列表中的所有任务
if (task.getGid().equals(gid)) // 如果找到了 GID 匹配的任务
return task; // 返回该任务
}
return null;
return null; // 如果没有找到匹配的任务,则返回 null
}
public ArrayList<Task> getChildTaskList() {
return this.mChildren;
return this.mChildren; // 返回子任务列表
}
public void setIndex(int index) {
this.mIndex = index;
this.mIndex = index; // 设置任务列表的索引位置
}
public int getIndex() {
return this.mIndex;
return this.mIndex; // 获取任务列表的索引位置
}
}

@ -17,17 +17,18 @@
package net.micode.notes.gtask.exception;
public class ActionFailureException extends RuntimeException {
private static final long serialVersionUID = 4425249765923293627L;
public ActionFailureException() {
super();
super(); // 调用父类的构造函数
}
public ActionFailureException(String paramString) {
super(paramString);
super(paramString); // 调用父类的构造函数,并传入异常信息
}
public ActionFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable);
super(paramString, paramThrowable); // 调用父类的构造函数,并传入异常信息和原始异常
}
}

@ -17,17 +17,18 @@
package net.micode.notes.gtask.exception;
public class NetworkFailureException extends Exception {
private static final long serialVersionUID = 2107610287180234136L;
public NetworkFailureException() {
super();
super(); // 调用父类的构造函数
}
public NetworkFailureException(String paramString) {
super(paramString);
super(paramString); // 调用父类的构造函数,并传入异常信息
}
public NetworkFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable);
super(paramString, paramThrowable); // 调用父类的构造函数,并传入异常信息和原始异常
}
}

@ -37,82 +37,82 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
void onComplete();
}
private Context mContext;
private Context mContext; // 上下文对象
private NotificationManager mNotifiManager;
private NotificationManager mNotifiManager; // 通知管理器对象
private GTaskManager mTaskManager;
private GTaskManager mTaskManager; // GTask 管理器对象
private OnCompleteListener mOnCompleteListener;
private OnCompleteListener mOnCompleteListener; // 异步任务完成后的回调接口
public GTaskASyncTask(Context context, OnCompleteListener listener) {
mContext = context;
mOnCompleteListener = listener;
mContext = context; // 初始化上下文对象
mOnCompleteListener = listener; // 初始化回调接口
mNotifiManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
mTaskManager = GTaskManager.getInstance();
.getSystemService(Context.NOTIFICATION_SERVICE); // 初始化通知管理器对象
mTaskManager = GTaskManager.getInstance(); // 获取 GTask 管理器对象的单例
}
public void cancelSync() {
mTaskManager.cancelSync();
mTaskManager.cancelSync(); // 取消 GTask 同步
}
public void publishProgess(String message) {
publishProgress(new String[] {
message
});
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;
.getString(tickerId), System.currentTimeMillis()); // 创建通知
notification.defaults = Notification.DEFAULT_LIGHTS; // 设置默认的通知灯光
notification.flags = Notification.FLAG_AUTO_CANCEL; // 设置通知被点击后自动取消
PendingIntent pendingIntent;
if (tickerId != R.string.ticker_success) {
if (tickerId != R.string.ticker_success) { // 如果是同步失败的通知
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0);
NotesPreferenceActivity.class), 0); // 点击通知后打开 NotesPreferenceActivity
} else {
} else { // 如果是同步成功的通知
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0);
NotesListActivity.class), 0); // 点击通知后打开 NotesListActivity
}
//notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
// pendingIntent);
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
// 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);
.getSyncAccountName(mContext))); // 向主线程发布进度更新,显示正在登录的提示信息
return mTaskManager.sync(mContext, this); // 开始 GTask 同步,并返回同步结果
}
@Override
protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]);
showNotification(R.string.ticker_syncing, progress[0]); // 显示同步进度的通知
if (mContext instanceof GTaskSyncService) {
((GTaskSyncService) mContext).sendBroadcast(progress[0]);
((GTaskSyncService) mContext).sendBroadcast(progress[0]); // 向 GTaskSyncService 发送广播,以便更新 UI
}
}
@Override
protected void onPostExecute(Integer result) {
if (result == GTaskManager.STATE_SUCCESS) {
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) {
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));
.getString(R.string.error_sync_cancelled)); // 显示同步被取消的通知
}
if (mOnCompleteListener != null) {
new Thread(new Runnable() {
if (mOnCompleteListener != null) { // 如果设置了 OnCompleteListener
new Thread(new Runnable() { // 在新线程中执行 OnCompleteListener
public void run() {
mOnCompleteListener.onComplete();
@ -120,4 +120,4 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
}).start();
}
}
}
}

@ -64,50 +64,52 @@ import java.util.zip.InflaterInputStream;
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_URL = "https://mail.google.com/tasks/"; // GTask 的基础 URL
private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig";
private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig"; // 获取 GTask 数据的 URL
private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig";
private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig"; // 提交 GTask 数据的 URL
private static GTaskClient mInstance = null;
private static GTaskClient mInstance = null; // 单例模式,保存 GTaskClient 的唯一实例
private DefaultHttpClient mHttpClient;
private DefaultHttpClient mHttpClient; // HTTP 客户端
private String mGetUrl;
private String mGetUrl; // 获取 GTask 数据的完整 URL
private String mPostUrl;
private String mPostUrl; // 提交 GTask 数据的完整 URL
private long mClientVersion;
private long mClientVersion; // 客户端版本号
private boolean mLoggedin;
private boolean mLoggedin; // 是否已登录
private long mLastLoginTime;
private long mLastLoginTime; // 上次登录时间
private int mActionId;
private int mActionId; // 操作 ID
private Account mAccount;
private JSONArray mUpdateArray;
private Account mAccount; // GTask 帐户
private JSONArray mUpdateArray; // 待更新的 GTask 数据
private GTaskClient() {
mHttpClient = null;
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
mClientVersion = -1;
mLoggedin = false;
mLastLoginTime = 0;
mActionId = 1;
mAccount = null;
mUpdateArray = null;
}
mHttpClient = null; // 初始化 HTTP 客户端为 null
mGetUrl = GTASK_GET_URL; // 初始化获取 GTask 数据的 URL
mPostUrl = GTASK_POST_URL; // 初始化提交 GTask 数据的 URL
mClientVersion = -1; // 初始化客户端版本号为 -1
mLoggedin = false; // 初始化登录状态为 false
mLastLoginTime = 0; // 初始化上次登录时间为 0
mActionId = 1; // 初始化操作 ID 为 1
mAccount = null; // 初始化 GTask 帐户为 null
mUpdateArray = null; // 初始化待更新的 GTask 数据为 null
}/*GTaskClientmHttpClientmAccountmUpdateArray null mGetUrlmPostUrl GTask URLmClientVersion -1mLoggedin falsemLastLoginTime 0mActionId 1
使访privateGTaskClient使GTaskClient*/
public static synchronized GTaskClient getInstance() {
if (mInstance == null) {
mInstance = new GTaskClient();
if (mInstance == null) { // 如果唯一实例不存在
mInstance = new GTaskClient(); // 则创建一个新实例
}
return mInstance;
}
return mInstance; // 返回唯一实例
}/*GTaskClientmInstance
线使synchronized线访
mInstanceGTaskClient.getInstance()GTaskClient*/
public boolean login(Activity activity) {
// we suppose that the cookie would expire after 5 minutes
@ -120,38 +122,38 @@ public class GTaskClient {
// need to re-login after account switch
if (mLoggedin
&& !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity
.getSyncAccountName(activity))) {
.getSyncAccountName(activity))) {
mLoggedin = false;
}
if (mLoggedin) {
if (mLoggedin) { // 如果已登录,则直接返回
Log.d(TAG, "already logged in");
return true;
}
mLastLoginTime = System.currentTimeMillis();
String authToken = loginGoogleAccount(activity, false);
if (authToken == null) {
mLastLoginTime = System.currentTimeMillis(); // 记录登录时间
String authToken = loginGoogleAccount(activity, false); // 登录 Google 帐户,获取授权令牌
if (authToken == null) { // 如果登录失败,则返回 false
Log.e(TAG, "login google account failed");
return false;
}
// login with custom domain if necessary
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
.endsWith("googlemail.com"))) {
StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
.endsWith("googlemail.com"))) { // 如果不是 Gmail 或 Googlemail 帐户,则使用自定义域名登录
StringBuilder url = new StringBuilder(GTASK_URL).append("a/"); // 构造自定义域名的 URL
int index = mAccount.name.indexOf('@') + 1;
String suffix = mAccount.name.substring(index);
url.append(suffix + "/");
mGetUrl = url.toString() + "ig";
mPostUrl = url.toString() + "r/ig";
mGetUrl = url.toString() + "ig"; // 更新获取 GTask 数据的 URL
mPostUrl = url.toString() + "r/ig"; // 更新提交 GTask 数据的 URL
if (tryToLoginGtask(activity, authToken)) {
mLoggedin = true;
if (tryToLoginGtask(activity, authToken)) { // 尝试登录 GTask
mLoggedin = true; // 登录成功
}
}
// try to login with google official url
// 如果自定义域名登录失败,则使用 Google 官方 URL 登录
if (!mLoggedin) {
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
@ -160,30 +162,35 @@ public class GTaskClient {
}
}
mLoggedin = true;
mLoggedin = true; // 登录成功
return true;
}
}/* GTask 5 mLoggedin false
mLoggedin false
true使loginGoogleAccount() Google
false Gmail Googlemail 使 GTask GTask URL GTask
使 Google URL
使mLoggedin true*/
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
String authToken;
AccountManager accountManager = AccountManager.get(activity);
Account[] accounts = accountManager.getAccountsByType("com.google");
AccountManager accountManager = AccountManager.get(activity); // 获取 AccountManager 实例
Account[] accounts = accountManager.getAccountsByType("com.google"); // 获取所有 Google 帐户
if (accounts.length == 0) {
if (accounts.length == 0) { // 如果没有可用的 Google 帐户,则返回 null
Log.e(TAG, "there is no available google account");
return null;
}
String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
String accountName = NotesPreferenceActivity.getSyncAccountName(activity); // 获取设置中的同步帐户名称
Account account = null;
for (Account a : accounts) {
if (a.name.equals(accountName)) {
if (a.name.equals(accountName)) { // 如果找到同名帐户,则使用该帐户
account = a;
break;
}
}
if (account != null) {
mAccount = account;
mAccount = account; // 更新当前使用的帐户
} else {
Log.e(TAG, "unable to get an account with the same name in the settings");
return null;
@ -191,39 +198,48 @@ public class GTaskClient {
// get the token now
AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null);
"goanna_mobile", null, activity, null, null); // 获取 token
try {
Bundle authTokenBundle = accountManagerFuture.getResult();
authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN);
if (invalidateToken) {
accountManager.invalidateAuthToken("com.google", authToken);
loginGoogleAccount(activity, false);
authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN); // 从 Bundle 中获取 token
if (invalidateToken) { // 如果需要使 token 失效
accountManager.invalidateAuthToken("com.google", authToken); // 使 token 失效
loginGoogleAccount(activity, false); // 重新登录
}
} catch (Exception e) {
} catch (Exception e) { // 获取 token 失败
Log.e(TAG, "get auth token failed");
authToken = null;
}
return authToken;
return authToken; // 返回 token
}
/* Google token访 Google
Google 使
使AccountManager token token
invalidateTokentrue使 token token
*/
private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) {
if (!loginGtask(authToken)) { // 如果登录 GTask 失败
// maybe the auth token is out of date, now let's invalidate the
// token and try again
authToken = loginGoogleAccount(activity, true);
if (authToken == null) {
authToken = loginGoogleAccount(activity, true); // 使 token 失效并重新登录
if (authToken == null) { // 如果重新登录失败,则返回 false
Log.e(TAG, "login google account failed");
return false;
}
if (!loginGtask(authToken)) {
if (!loginGtask(authToken)) { // 如果重新登录 GTask 仍然失败,则返回 false
Log.e(TAG, "login gtask failed");
return false;
}
}
return true;
return true; // 登录 GTask 成功,返回 true
}
/* GTaskauthTokenloginGoogleAccount() Google token
GTask 使 token GTask
falsetrue
*/
private boolean loginGtask(String authToken) {
int timeoutConnection = 10000;
@ -231,6 +247,8 @@ public class GTaskClient {
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
// 设置 HttpClient 的参数
mHttpClient = new DefaultHttpClient(httpParameters);
BasicCookieStore localBasicCookieStore = new BasicCookieStore();
mHttpClient.setCookieStore(localBasicCookieStore);
@ -239,11 +257,10 @@ public class GTaskClient {
// login gtask
try {
String loginUrl = mGetUrl + "?auth=" + authToken;
HttpGet httpGet = new HttpGet(loginUrl);
HttpResponse response = null;
response = mHttpClient.execute(httpGet);
HttpGet httpGet = new HttpGet(loginUrl); // 创建 HTTP GET 请求
HttpResponse response = mHttpClient.execute(httpGet); // 执行请求
// get the cookie now
// 获取 cookie
List<Cookie> cookies = mHttpClient.getCookieStore().getCookies();
boolean hasAuthCookie = false;
for (Cookie cookie : cookies) {
@ -255,7 +272,7 @@ public class GTaskClient {
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>";
@ -279,49 +296,63 @@ public class GTaskClient {
return true;
}
/*使authToken GTask
HTTP GET authToken URL
cookiemClientVersion
truefalsefalse
*/
private int getActionId() {
return mActionId++;
return mActionId++; // 返回下一个 action ID并将 mActionId 加 1
}
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;
}
HttpPost httpPost = new HttpPost(mPostUrl); // 创建一个 HTTP POST 请求
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); // 设置请求头的 Content-Type
httpPost.setHeader("AT", "1"); // 设置请求头的 AT 字段为 1
return httpPost; // 返回创建的 HTTP POST 请求
}/*getActionId() action IDmActionId 1 1
createHttpPost() HTTP POST Content-Type application/x-www-form-urlencoded;charset=utf-8 AT 1
HTTP POST
*/
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
if (entity.getContentEncoding() != null) {
contentEncoding = entity.getContentEncoding().getValue();
contentEncoding = entity.getContentEncoding().getValue(); // 获取响应内容的编码方式
Log.d(TAG, "encoding: " + contentEncoding);
}
InputStream input = entity.getContent();
InputStream input = entity.getContent(); // 获取响应内容的输入流
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {
input = new GZIPInputStream(entity.getContent());
input = new GZIPInputStream(entity.getContent()); // 如果响应内容被 gzip 压缩了,则创建一个 GZIPInputStream 解压缩
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {
Inflater inflater = new Inflater(true);
input = new InflaterInputStream(entity.getContent(), inflater);
input = new InflaterInputStream(entity.getContent(), inflater); // 如果响应内容被 deflate 压缩了,则创建一个 InflaterInputStream 解压缩
}
try {
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
InputStreamReader isr = new InputStreamReader(input); // 创建一个 InputStreamReader 对象
BufferedReader br = new BufferedReader(isr); // 创建一个 BufferedReader 对象
StringBuilder sb = new StringBuilder(); // 创建一个 StringBuilder 对象
while (true) {
String buff = br.readLine();
String buff = br.readLine(); // 逐行读取响应内容
if (buff == null) {
return sb.toString();
return sb.toString(); // 如果读到了末尾,则返回读取到的响应内容
}
sb = sb.append(buff);
sb = sb.append(buff); // 将读取到的响应内容追加到 StringBuilder 对象中
}
} finally {
input.close();
input.close(); // 关闭输入流
}
}
/*getResponseContent(HttpEntity entity)HttpEntity
gzip GZIPInputStream ; deflate InflaterInputStream
使 InputStreamReader BufferedReader StringBuilder
*/
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) {
@ -329,17 +360,17 @@ public class GTaskClient {
throw new ActionFailureException("not logged in");
}
HttpPost httpPost = createHttpPost();
HttpPost httpPost = createHttpPost(); // 创建 HTTP POST 请求
try {
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
list.add(new BasicNameValuePair("r", js.toString()));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
httpPost.setEntity(entity);
list.add(new BasicNameValuePair("r", js.toString())); // 将传入的 JSONObject 对象转为字符串,并添加到请求参数中
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); // 创建一个 UrlEncodedFormEntity 对象,用于封装请求参数
httpPost.setEntity(entity); // 将 UrlEncodedFormEntity 对象设置为 HTTP POST 请求的实体
// execute the post
HttpResponse response = mHttpClient.execute(httpPost);
String jsString = getResponseContent(response.getEntity());
return new JSONObject(jsString);
HttpResponse response = mHttpClient.execute(httpPost); // 执行 HTTP POST 请求
String jsString = getResponseContent(response.getEntity()); // 获取响应内容,并将其解压(如果响应内容被压缩了),然后转为字符串
return new JSONObject(jsString); // 将响应内容转为 JSONObject 对象
} catch (ClientProtocolException e) {
Log.e(TAG, e.toString());
@ -359,25 +390,30 @@ public class GTaskClient {
throw new ActionFailureException("error occurs when posting request");
}
}
/*postRequest(JSONObject js) HTTP POST JSONObject
HTTP POST JSONObject UrlEncodedFormEntity HTTP POST
HTTP POST JSONObject JSONObject
HTTP POST JSONObject
*/
public void createTask(Task task) throws NetworkFailureException {
commitUpdate();
commitUpdate(); // 提交所有未提交的更新操作
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
JSONObject jsPost = new JSONObject(); // 创建一个新的 JSONObject 对象
JSONArray actionList = new JSONArray(); // 创建一个新的 JSONArray 对象,用于存储操作列表
// action_list
actionList.put(task.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
actionList.put(task.getCreateAction(getActionId())); // 将新增任务的操作添加到操作列表中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将操作列表添加到 JSONObject 对象中
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); // 添加客户端版本号到 JSONObject 对象中
// post
JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResponse = postRequest(jsPost); // 向服务器发送 HTTP POST 请求,并获取响应内容
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
task.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
GTaskStringUtils.GTASK_JSON_RESULTS).get(0); // 从响应内容中获取结果列表,并获取第一个结果
task.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID)); // 获取新任务的 ID并将其设置为 Task 对象的 gid 属性
} catch (JSONException e) {
Log.e(TAG, e.toString());
@ -385,25 +421,30 @@ public class GTaskClient {
throw new ActionFailureException("create task: handing jsonobject failed");
}
}
/*createTask(Task task)commitUpdate()
JSONObject JSONArray JSONObject JSONObject
HTTP POST ID Task gid
JSONObject
*/
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate();
commitUpdate(); // 提交所有未提交的更新操作
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
JSONObject jsPost = new JSONObject(); // 创建一个新的 JSONObject 对象
JSONArray actionList = new JSONArray(); // 创建一个新的 JSONArray 对象,用于存储操作列表
// action_list
actionList.put(tasklist.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
actionList.put(tasklist.getCreateAction(getActionId())); // 将新增任务列表的操作添加到操作列表中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将操作列表添加到 JSONObject 对象中
// client version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); // 添加客户端版本号到 JSONObject 对象中
// post
JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResponse = postRequest(jsPost); // 向服务器发送 HTTP POST 请求,并获取响应内容
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
GTaskStringUtils.GTASK_JSON_RESULTS).get(0); // 从响应内容中获取结果列表,并获取第一个结果
tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID)); // 获取新任务列表的 ID并将其设置为 TaskList 对象的 gid 属性
} catch (JSONException e) {
Log.e(TAG, e.toString());
@ -411,20 +452,25 @@ public class GTaskClient {
throw new ActionFailureException("create tasklist: handing jsonobject failed");
}
}
/*createTaskList(TaskList tasklist)commitUpdate()
JSONObject JSONArray JSONObject JSONObject
HTTP POST ID TaskList gid
JSONObject
*/
public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) {
if (mUpdateArray != null) { // 判断更新操作列表是否为空
try {
JSONObject jsPost = new JSONObject();
JSONObject jsPost = new JSONObject(); // 创建一个新的 JSONObject 对象
// action_list
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray); // 将更新操作列表添加到 JSONObject 对象中
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); // 添加客户端版本号到 JSONObject 对象中
postRequest(jsPost); // 向服务器发送 HTTP POST 请求,提交更新操作
mUpdateArray = null; // 更新操作提交成功后,清空更新操作列表
postRequest(jsPost);
mUpdateArray = null;
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
@ -432,52 +478,63 @@ public class GTaskClient {
}
}
}
/*commitUpdate() JSONObject JSONObject JSONObject
HTTP POST
JSONObject
*/
public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) {
if (node != null) { // 判断 Node 对象是否为空
// too many update items may result in an error
// set max to 10 items
if (mUpdateArray != null && mUpdateArray.length() > 10) {
commitUpdate();
if (mUpdateArray != null && mUpdateArray.length() > 10) { // 判断更新操作列表是否已满
commitUpdate(); // 如果已满,则提交所有未提交的更新操作
}
if (mUpdateArray == null)
mUpdateArray = new JSONArray();
mUpdateArray.put(node.getUpdateAction(getActionId()));
mUpdateArray = new JSONArray(); // 如果更新操作列表还未创建,则创建一个新的 JSONArray 对象
mUpdateArray.put(node.getUpdateAction(getActionId())); // 将 Node 对象的更新操作添加到更新操作列表中
}
}
/*addUpdateNode(Node node) Node
10commitUpdate()
JSONArray
Node
*/
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
commitUpdate();
commitUpdate(); // 先提交所有未提交的更新操作
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
JSONObject action = new JSONObject();
JSONObject jsPost = new JSONObject(); // 创建一个新的 JSONObject 对象
JSONArray actionList = new JSONArray(); // 创建一个新的 JSONArray 对象,用于存储更新操作
JSONObject action = new JSONObject(); // 创建一个新的 JSONObject 对象,用于存储移动任务的操作
// action_list
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());
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE); // 设置操作类型为移动任务
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); // 设置操作 ID
action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid()); // 设置任务的 GID
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());
action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling()); // 如果是在同一任务列表中移动任务,则设置前一个任务的 GID
}
action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid());
action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid());
action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid()); // 设置任务的原始任务列表的 GID
action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); // 设置任务的目标任务列表的 GID
if (preParent != curParent) {
// put the dest_list only if moving between tasklists
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid()); // 如果是在不同的任务列表之间移动任务,则设置任务的目标任务列表的 GID
}
actionList.put(action);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
actionList.put(action); // 将移动任务的操作添加到更新操作列表中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将更新操作列表添加到 JSONObject 对象中
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); // 添加客户端版本号到 JSONObject 对象中
postRequest(jsPost);
postRequest(jsPost); // 向服务器发送 HTTP POST 请求,提交更新操作
} catch (JSONException e) {
Log.e(TAG, e.toString());
@ -485,101 +542,127 @@ public class GTaskClient {
throw new ActionFailureException("move task: handing jsonobject failed");
}
}
/*moveTask(Task task, TaskList preParent, TaskList curParent)
commitUpdate() JSONObject
ID GID GID GID GID GID
JSONObject JSONObject HTTP POST
JSONObject ActionFailureException
*/
public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate();
commitUpdate(); // 先提交所有未提交的更新操作
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
JSONObject jsPost = new JSONObject(); // 创建一个新的 JSONObject 对象
JSONArray actionList = new JSONArray(); // 创建一个新的 JSONArray 对象,用于存储更新操作
// action_list
node.setDeleted(true);
actionList.put(node.getUpdateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
node.setDeleted(true); // 将节点标记为已删除
actionList.put(node.getUpdateAction(getActionId())); // 将节点的更新操作添加到更新操作列表中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将更新操作列表添加到 JSONObject 对象中
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); // 添加客户端版本号到 JSONObject 对象中
postRequest(jsPost); // 向服务器发送 HTTP POST 请求,提交更新操作
mUpdateArray = null; // 将更新操作数组置为空
postRequest(jsPost);
mUpdateArray = null;
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("delete node: handing jsonobject failed");
throw new ActionFailureException("delete node: handing jsonobject failed"); // 处理 JSONObject 对象时出现异常,则抛出 ActionFailureException 异常
}
}
/*
JSONObject
HTTP POST JSONObject ActionFailureException
*/
public JSONArray getTaskLists() throws NetworkFailureException {
if (!mLoggedin) {
if (!mLoggedin) { // 如果用户没有登录,则抛出 ActionFailureException 异常
Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in");
}
try {
HttpGet httpGet = new HttpGet(mGetUrl);
HttpGet httpGet = new HttpGet(mGetUrl); // 创建一个新的 HttpGet 请求对象
HttpResponse response = null;
response = mHttpClient.execute(httpGet);
response = mHttpClient.execute(httpGet); // 执行 HttpGet 请求
// get the task list
String resString = getResponseContent(response.getEntity());
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) {
if (begin != -1 && end != -1 && begin < end) { // 如果响应内容中包含任务列表,那么提取出来
jsString = resString.substring(begin + jsBegin.length(), end);
}
JSONObject js = new JSONObject(jsString);
return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS);
} catch (ClientProtocolException e) {
JSONObject js = new JSONObject(jsString); // 将任务列表转换成 JSONObject 对象
return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS); // 返回任务列表数组
} catch (ClientProtocolException e) { // 如果发生协议错误,则抛出 NetworkFailureException 异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new NetworkFailureException("gettasklists: httpget failed");
} catch (IOException e) {
} catch (IOException e) { // 如果发生 I/O 错误,则抛出 NetworkFailureException 异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new NetworkFailureException("gettasklists: httpget failed");
} catch (JSONException e) {
} catch (JSONException e) { // 如果处理 JSONObject 对象时出现异常,则抛出 ActionFailureException 异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("get task lists: handing jasonobject failed");
}
}
/* JSONArray
HttpGet
JSONObject
HttpGet JSONObject NetworkFailureException ActionFailureException
*/
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
commitUpdate();
commitUpdate(); // 提交所有未提交的更改
try {
JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray();
JSONObject action = new JSONObject();
JSONObject jsPost = new JSONObject(); // 创建一个新的 JSONObject 对象
JSONArray actionList = new JSONArray(); // 创建一个新的 JSONArray 对象
JSONObject action = new JSONObject(); // 创建一个新的 JSONObject 对象
// action_list
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);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL); // 设置 action 的类型为 "getall"
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); // 设置 action 的 ID
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid); // 设置 action 操作的任务列表 ID
action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false); // 设置是否获取已删除的任务
actionList.put(action); // 将 action 添加到 action_list 中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); // 将 action_list 添加到 jsPost 中
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); // 设置客户端版本号
JSONObject jsResponse = postRequest(jsPost);
return jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_TASKS);
} catch (JSONException e) {
JSONObject jsResponse = postRequest(jsPost); // 发送请求并获取响应
return jsResponse.getJSONArray(GTaskStringUtils.GTASK_JSON_TASKS); // 从响应中获取任务列表并返回
} catch (JSONException e) { // 如果处理 JSONObject 对象时出现异常,则抛出 ActionFailureException 异常
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("get task list: handing jsonobject failed");
}
}
/* JSONArray
JSONArray
JSONObject ActionFailureException
*/
public Account getSyncAccount() {
return mAccount;
}
//这个方法返回GTaskClient的同步账户即当前使用的 Google 帐户)。
public void resetUpdateArray() {
mUpdateArray = null;
}
}
/*GTaskClientmUpdateArraynull
commitUpdate()resetUpdateArray()
*/
Loading…
Cancel
Save