Compare commits

...

2 Commits

Author SHA1 Message Date
SheYu 47ca33b54f 代码合并
10 months ago
SheYu adf5cfc4bd 最终代码合并
10 months ago

@ -1,20 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<!--- 定义应用程序的名称和版本号 --> <!--- 定义应用程序的名称和版本号 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.micode.notes" package="net.micode.notes"
@ -48,9 +32,10 @@
<!--- 应用程序组件声明 --> <!--- 应用程序组件声明 -->
<!--- 定义应用程序的图标和名称 --> <!--- 定义应用程序的图标和名称 -->
<application <application
android:icon="@drawable/icon_app" android:icon="@drawable/icon_app_1"
android:label="@string/app_name" android:label="@string/app_name"
android:requestLegacyExternalStorage="true"> android:requestLegacyExternalStorage="true"
android:testOnly="true" >
<activity <activity
android:name=".ui.SplashActivity" android:name=".ui.SplashActivity"
android:configChanges="orientation|keyboardHidden|screenSize" android:configChanges="orientation|keyboardHidden|screenSize"
@ -65,6 +50,7 @@
<!--- 应用程序的入口 NotesListActivity --> <!--- 应用程序的入口 NotesListActivity -->
<activity <activity
android:name=".ui.NotesListActivity" android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="true" android:exported="true"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name" android:label="@string/app_name"

@ -17,17 +17,11 @@
package net.micode.notes.data; package net.micode.notes.data;
import android.net.Uri; import android.net.Uri;
/** //Notes类就定义了很多常量是小米便签的数据库
* @Package: net.micode.notes.data
* @ClassName: Notes
* @Description:
* @Author: WuShuxian
* @CreateDate: 2023/12/21 19:32
* @Version: 1.0
*/
public class Notes { public class Notes {
public static final String AUTHORITY = "micode_notes"; public static final String AUTHORITY = "micode_notes";
public static final String TAG = "Notes"; public static final String TAG = "Notes";
//三个type
public static final int TYPE_NOTE = 0; public static final int TYPE_NOTE = 0;
public static final int TYPE_FOLDER = 1; public static final int TYPE_FOLDER = 1;
public static final int TYPE_SYSTEM = 2; public static final int TYPE_SYSTEM = 2;
@ -38,6 +32,7 @@ public class Notes {
* {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder * {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder
* {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records * {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records
*/ */
//不同种类的文件夹
public static final int ID_ROOT_FOLDER = 0; public static final int ID_ROOT_FOLDER = 0;
public static final int ID_TEMPARAY_FOLDER = -1; public static final int ID_TEMPARAY_FOLDER = -1;
public static final int ID_CALL_RECORD_FOLDER = -2; public static final int ID_CALL_RECORD_FOLDER = -2;
@ -53,12 +48,12 @@ public class Notes {
public static final int TYPE_WIDGET_INVALIDE = -1; public static final int TYPE_WIDGET_INVALIDE = -1;
public static final int TYPE_WIDGET_2X = 0; public static final int TYPE_WIDGET_2X = 0;
public static final int TYPE_WIDGET_4X = 1; public static final int TYPE_WIDGET_4X = 1;
//数据常量 包括普通note和call_note
public static class DataConstants { public static class DataConstants {
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; public static final String NOTE = TextNote.CONTENT_ITEM_TYPE;
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE;
} }
//两个指针,一个找便签和文件夹,一个用来找数据
/** /**
* Uri to query all notes and folders * Uri to query all notes and folders
*/ */
@ -67,72 +62,201 @@ public class Notes {
/** /**
* Uri to query data * Uri to query data
*/ */
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
//Notecolumns类用于创建数据库的表头
public interface NoteColumns { public interface NoteColumns {
//具体每一项都给了英文注释
/**
* The unique ID for a row
* <P> Type: INTEGER (long) </P>
*/
public static final String ID = "_id"; public static final String ID = "_id";
/**
* The parent's id for note or folder
* <P> Type: INTEGER (long) </P>
*/
public static final String PARENT_ID = "parent_id"; public static final String PARENT_ID = "parent_id";
/**
* Created data for note or folder
* <P> Type: INTEGER (long) </P>
*/
public static final String CREATED_DATE = "created_date"; public static final String CREATED_DATE = "created_date";
/**
* Latest modified date
* <P> Type: INTEGER (long) </P>
*/
public static final String MODIFIED_DATE = "modified_date"; public static final String MODIFIED_DATE = "modified_date";
/**
* Alert date
* <P> Type: INTEGER (long) </P>
*/
public static final String ALERTED_DATE = "alert_date"; public static final String ALERTED_DATE = "alert_date";
/**
* Folder's name or text content of note
* <P> Type: TEXT </P>
*/
public static final String SNIPPET = "snippet"; public static final String SNIPPET = "snippet";
/**
* Note's widget id
* <P> Type: INTEGER (long) </P>
*/
public static final String WIDGET_ID = "widget_id"; public static final String WIDGET_ID = "widget_id";
/**
* Note's widget type
* <P> Type: INTEGER (long) </P>
*/
public static final String WIDGET_TYPE = "widget_type"; public static final String WIDGET_TYPE = "widget_type";
/**
* Note's background color's id
* <P> Type: INTEGER (long) </P>
*/
public static final String BG_COLOR_ID = "bg_color_id"; public static final String BG_COLOR_ID = "bg_color_id";
/**
* For text note, it doesn't has attachment, for multi-media
* note, it has at least one attachment
* <P> Type: INTEGER </P>
*/
public static final String HAS_ATTACHMENT = "has_attachment"; public static final String HAS_ATTACHMENT = "has_attachment";
/**
* Folder's count of notes
* <P> Type: INTEGER (long) </P>
*/
public static final String NOTES_COUNT = "notes_count"; public static final String NOTES_COUNT = "notes_count";
/**
* The file type: folder or note
* <P> Type: INTEGER </P>
*/
public static final String TYPE = "type"; public static final String TYPE = "type";
/**
* The last sync id
* <P> Type: INTEGER (long) </P>
*/
public static final String SYNC_ID = "sync_id"; public static final String SYNC_ID = "sync_id";
/**
* Sign to indicate local modified or not
* <P> Type: INTEGER </P>
*/
public static final String LOCAL_MODIFIED = "local_modified"; public static final String LOCAL_MODIFIED = "local_modified";
/**
* Original parent id before moving into temporary folder
* <P> Type : INTEGER </P>
*/
public static final String ORIGIN_PARENT_ID = "origin_parent_id"; public static final String ORIGIN_PARENT_ID = "origin_parent_id";
/**
* The gtask id
* <P> Type : TEXT </P>
*/
public static final String GTASK_ID = "gtask_id"; public static final String GTASK_ID = "gtask_id";
/**
* The version code
* <P> Type : INTEGER (long) </P>
*/
public static final String VERSION = "version"; public static final String VERSION = "version";
}
public interface DataColumns { public static final String PASSWORD = "password";
public static final String IMPORTANCE = "importance";
}//便签的各种属性
/*
* 便
*/
public interface DataColumns {
/**
* The unique ID for a row
* <P> Type: INTEGER (long) </P>
*/
public static final String ID = "_id"; public static final String ID = "_id";
/**
* The MIME type of the item represented by this row.
* <P> Type: Text </P>
*/
public static final String MIME_TYPE = "mime_type"; public static final String MIME_TYPE = "mime_type";
/**
* The reference id to note that this data belongs to
* <P> Type: INTEGER (long) </P>
*/
public static final String NOTE_ID = "note_id"; public static final String NOTE_ID = "note_id";
/**
* Created data for note or folder
* <P> Type: INTEGER (long) </P>
*/
public static final String CREATED_DATE = "created_date"; public static final String CREATED_DATE = "created_date";
/**
* Latest modified date
* <P> Type: INTEGER (long) </P>
*/
public static final String MODIFIED_DATE = "modified_date"; public static final String MODIFIED_DATE = "modified_date";
/**
* Data's content
* <P> Type: TEXT </P>
*/
public static final String CONTENT = "content"; public static final String CONTENT = "content";
/**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
* integer data type
* <P> Type: INTEGER </P>
*/
public static final String DATA1 = "data1"; public static final String DATA1 = "data1";
/**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
* integer data type
* <P> Type: INTEGER </P>
*/
public static final String DATA2 = "data2"; public static final String DATA2 = "data2";
/**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
* TEXT data type
* <P> Type: TEXT </P>
*/
public static final String DATA3 = "data3"; public static final String DATA3 = "data3";
/**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
* TEXT data type
* <P> Type: TEXT </P>
*/
public static final String DATA4 = "data4"; public static final String DATA4 = "data4";
/**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for
* TEXT data type
* <P> Type: TEXT </P>
*/
public static final String DATA5 = "data5"; public static final String DATA5 = "data5";
} }//一个便签内部各种数据类型
public static final class TextNote implements DataColumns { public static final class TextNote implements DataColumns {
/**
* Mode to indicate the text in check list mode or not
* <P> Type: Integer 1:check list mode 0: normal mode </P>
*/
public static final String MODE = DATA1; public static final String MODE = DATA1;
public static final int MODE_CHECK_LIST = 1; public static final int MODE_CHECK_LIST = 1;
@ -142,12 +266,19 @@ public class Notes {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");
} }//一种是文本textnote
public static final class CallNote implements DataColumns { public static final class CallNote implements DataColumns {
/**
* Call date for this record
* <P> Type: INTEGER (long) </P>
*/
public static final String CALL_DATE = DATA1; public static final String CALL_DATE = DATA1;
/**
* Phone number for this record
* <P> Type: TEXT </P>
*/
public static final String PHONE_NUMBER = DATA3; public static final String PHONE_NUMBER = DATA3;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";
@ -155,5 +286,5 @@ public class Notes {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
} }//另一种是通话类型的callnote
} }

@ -16,31 +16,22 @@
package net.micode.notes.data; package net.micode.notes.data;
import android.content.ContentValues;//就是用于保存一些数据string boolean ...)信息,这些信息可以被数据库操作时使用。 import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.sqlite.SQLiteDatabase;//主要提供了对应于添加、删除、更新、查询的操作方法: insert()、delete()、update()和query()。配合content.values import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;//用来管理数据的创建和版本更新 import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log; import android.util.Log;
//引用了同一个包中的另一个子包Notes中一些接口
import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
/** //数据库操作
* @Package: net.micode.notes.data
* @ClassName: NotesDatabaseHelper
* @Description: 便
* @Author: WuShuxian
* @CreateDate: 2023/12/21 19:46
* @Version: 1.0
*/
public class NotesDatabaseHelper extends SQLiteOpenHelper { public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "note.db"; private static final String DB_NAME = "note.db";
private static final int DB_VERSION = 4; private static final int DB_VERSION = 4;
/** //接口两部分一个Note一个DATA
*
*/
public interface TABLE { public interface TABLE {
public static final String NOTE = "note"; public static final String NOTE = "note";
@ -50,9 +41,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "NotesDatabaseHelper"; private static final String TAG = "NotesDatabaseHelper";
private static NotesDatabaseHelper mInstance; private static NotesDatabaseHelper mInstance;
/** //基于NoteColumn创建一个NOTE_TABLE表格并附上初始数据
* 便
*/
private static final String CREATE_NOTE_TABLE_SQL = private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" + "CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," + NoteColumns.ID + " INTEGER PRIMARY KEY," +
@ -73,9 +62,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")"; ")";
/** //主要基于datacolumn来创建DATA_TABLE
* 便
*/
private static final String CREATE_DATA_TABLE_SQL = private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" + "CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," + DataColumns.ID + " INTEGER PRIMARY KEY," +
@ -90,13 +77,13 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")"; ")";
//这个数据是关于INDEX编号的
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL = private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " + "CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");"; TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
/** /**
* 便 * Increase folder's note count when move note to the folder
*/ */
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+ "CREATE TRIGGER increase_folder_count_on_update "+
@ -106,9 +93,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END"; " END";
//移入note时触发修改一系列数据从哪来之类的
/** /**
* 便 * Decrease folder's note count when move note from folder
*/ */
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " + "CREATE TRIGGER decrease_folder_count_on_update " +
@ -119,9 +106,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID + " WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" + " AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END"; " END";
//移除Note时触发与上面移入对应
/** /**
* 便 * Increase folder's note count when insert new note to the folder
*/ */
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " + "CREATE TRIGGER increase_folder_count_on_insert " +
@ -131,9 +118,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END"; " END";
//插入Note
/** /**
* 便 * Decrease folder's note count when delete note from the folder
*/ */
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " + "CREATE TRIGGER decrease_folder_count_on_delete " +
@ -144,7 +131,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID + " WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" + " AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END"; " END";
//删除note
/** /**
* Update note's content when insert data with type {@link DataConstants#NOTE} * Update note's content when insert data with type {@link DataConstants#NOTE}
*/ */
@ -157,7 +144,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END"; " END";
//当给note插入新数据时触发
/** /**
* Update note's content when data with {@link DataConstants#NOTE} type has changed * Update note's content when data with {@link DataConstants#NOTE} type has changed
*/ */
@ -169,7 +156,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END"; " END";//note数据被修改update
/** /**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted * Update note's content when data with {@link DataConstants#NOTE} type has deleted
@ -182,7 +169,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" + " SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END"; " END";//更新已经删除的便签的数据
/** /**
* Delete datas belong to note which has been deleted * Delete datas belong to note which has been deleted
@ -193,7 +180,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" BEGIN" + " BEGIN" +
" DELETE FROM " + TABLE.DATA + " DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";//删除 已经被删除的便签的数据
/** /**
* Delete notes belong to folder which has been deleted * Delete notes belong to folder which has been deleted
@ -204,7 +191,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" BEGIN" + " BEGIN" +
" DELETE FROM " + TABLE.NOTE + " DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";//删除 已删除folder文件夹 中的便签要修改的数据
/** /**
* Move notes belong to folder which has been moved to trash folder * Move notes belong to folder which has been moved to trash folder
@ -217,12 +204,12 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + " SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";//移动trash_folder中的便签
public NotesDatabaseHelper(Context context) { public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION); super(context, DB_NAME, null, DB_VERSION);
} }
//构造函数
public void createNoteTable(SQLiteDatabase db) { public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL); db.execSQL(CREATE_NOTE_TABLE_SQL);
reCreateNoteTableTriggers(db); reCreateNoteTableTriggers(db);
@ -246,48 +233,49 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER); db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER); db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER); db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
} }//数据库操作的API重新创建
/**
* @method createSystemFolder
* @description:
* @date: 2023/12/21 20:19
* @author: WuShuxian
* @param: db
* @return: void
*/
private void createSystemFolder(SQLiteDatabase db) { private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
//通话记录文件夹 /**
* call record foler for call notes
*/
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER); values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values);
//缺省根目录 /**
* root folder which is default folder
*/
values.clear(); values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER); values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values);
//临时文件夹 /**
* temporary folder which is used for moving note
*/
values.clear(); values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER); values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values);
//回收站文件夹 /**
* create trash folder
*/
values.clear(); values.clear();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values);
} }//创建系统文件夹
public void createDataTable(SQLiteDatabase db) { public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL); db.execSQL(CREATE_DATA_TABLE_SQL);
reCreateDataTableTriggers(db); reCreateDataTableTriggers(db);
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
Log.d(TAG, "data table has been created"); Log.d(TAG, "data table has been created");
} }//创建数据表格
private void reCreateDataTableTriggers(SQLiteDatabase db) { private void reCreateDataTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
@ -297,45 +285,38 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
} }//类似于recreatenotetable重新创建触发器
static synchronized NotesDatabaseHelper getInstance(Context context) { static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) { if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context); mInstance = new NotesDatabaseHelper(context);
} }
return mInstance; return mInstance;
} }//sync同步同一时刻只有一个线程执行
@Override @Override
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {
createNoteTable(db);//属性数据库 createNoteTable(db);
createDataTable(db);//内容数据库 createDataTable(db);
} }//创建Note Data两个表格
/**
* @method onUpgrade
* @description: 便使
* @date: 2023/12/21 20:42
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean reCreateTriggers = false; boolean reCreateTriggers = false;
boolean skipV2 = false; boolean skipV2 = false;
//V1->V2
if (oldVersion == 1) { if (oldVersion == 1) {
upgradeToV2(db); upgradeToV2(db);
skipV2 = true; // this upgrade including the upgrade from v2 to v3 skipV2 = true; // this upgrade including the upgrade from v2 to v3
oldVersion++; oldVersion++;
} }
//V2->V3
if (oldVersion == 2 && !skipV2) { if (oldVersion == 2 && !skipV2) {
upgradeToV3(db); upgradeToV3(db);
reCreateTriggers = true; reCreateTriggers = true;
oldVersion++; oldVersion++;
} }
//V3->V4
if (oldVersion == 3) { if (oldVersion == 3) {
upgradeToV4(db); upgradeToV4(db);
oldVersion++; oldVersion++;
@ -350,19 +331,15 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
throw new IllegalStateException("Upgrade notes database to version " + newVersion throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails"); + "fails");
} }
} }//数据库版本更新
/**
* V2
*/
private void upgradeToV2(SQLiteDatabase db) { private void upgradeToV2(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
createNoteTable(db); createNoteTable(db);
createDataTable(db); createDataTable(db);
} }//更新到V2
/**
* V3
*/
private void upgradeToV3(SQLiteDatabase db) { private void upgradeToV3(SQLiteDatabase db) {
// drop unused triggers // drop unused triggers
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
@ -376,12 +353,10 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values);
} }//更新到V3
/**
* V4
*/
private void upgradeToV4(SQLiteDatabase db) { private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0"); + " INTEGER NOT NULL DEFAULT 0");
} }//更新到V4
} }

@ -1,22 +1,5 @@
/*
* 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.data; package net.micode.notes.data;
import android.app.SearchManager; import android.app.SearchManager;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.ContentUris; import android.content.ContentUris;
@ -33,19 +16,15 @@ import net.micode.notes.R;
import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE; import net.micode.notes.data.NotesDatabaseHelper.TABLE;
//为存储和获取数据提供接口。可以在不同的应用程序之间共享数据
/** //ContentProvider提供的方法
* @Package: net.micode.notes.data //query查询
* @ClassName: NotesProvider //insert插入
* @Description: //update更新
* @Author: WuShuxian //delete删除
* @CreateDate: 2023/12/21 20:50 //getType得到数据类型
* @Version: 1.0
*/
public class NotesProvider extends ContentProvider { public class NotesProvider extends ContentProvider {
/** // UriMatcher用于匹配Uri
* UriMatcherUri
*/
private static final UriMatcher mMatcher; private static final UriMatcher mMatcher;
private NotesDatabaseHelper mHelper; private NotesDatabaseHelper mHelper;
@ -61,7 +40,9 @@ public class NotesProvider extends ContentProvider {
private static final int URI_SEARCH_SUGGEST = 6; private static final int URI_SEARCH_SUGGEST = 6;
static { static {
// 创建UriMatcher时调用UriMatcher(UriMatcher.NO_MATCH)表示不匹配任何路径的返回码
mMatcher = new UriMatcher(UriMatcher.NO_MATCH); mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 把需要匹配Uri路径全部给注册上
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
@ -72,44 +53,43 @@ public class NotesProvider extends ContentProvider {
} }
/** /**
*
* x'0A' represents the '\n' character in sqlite. For title and content in the search result, * x'0A' represents the '\n' character in sqlite. For title and content in the search result,
* we will trim '\n' and white space in order to show more information. * we will trim '\n' and white space in order to show more information.
*/ */
// 声明 NOTES_SEARCH_PROJECTION
private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + ","
+ NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + ","
+ R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
+ "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
+ "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA;
// 声明NOTES_SNIPPET_SEARCH_QUERY
private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION
+ " FROM " + TABLE.NOTE + " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.SNIPPET + " LIKE ?" + " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
+ " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
+ " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
@Override @Override
// Context只有在onCreate()中才被初始化
// 对mHelper进行实例化
public boolean onCreate() { public boolean onCreate() {
mHelper = NotesDatabaseHelper.getInstance(getContext()); mHelper = NotesDatabaseHelper.getInstance(getContext());
return true; return true;
} }
/**
* @Package: net.micode.notes.data
* @ClassName: NotesProvider
* @Description: Uri
* @Author: WuShuxian
* @CreateDate: 2023/12/21 21:06
* @Version: 1.0
*/
@Override @Override
// 查询uri在数据库中对应的位置
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) { String sortOrder) {
Cursor c = null; Cursor c = null;
SQLiteDatabase db = mHelper.getReadableDatabase();//读数据库 // 获取可读数据库
SQLiteDatabase db = mHelper.getReadableDatabase();
String id = null; String id = null;
// 匹配查找uri
switch (mMatcher.match(uri)) { switch (mMatcher.match(uri)) {
// 对于不同的匹配值,在数据库中查找相应的条目
case URI_NOTE: case URI_NOTE:
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder); sortOrder);
@ -131,6 +111,7 @@ public class NotesProvider extends ContentProvider {
case URI_SEARCH: case URI_SEARCH:
case URI_SEARCH_SUGGEST: case URI_SEARCH_SUGGEST:
if (sortOrder != null || projection != null) { if (sortOrder != null || projection != null) {
// 不合法的参数异常
throw new IllegalArgumentException( throw new IllegalArgumentException(
"do not specify sortOrder, selection, selectionArgs, or projection" + "with this query"); "do not specify sortOrder, selection, selectionArgs, or projection" + "with this query");
} }
@ -138,6 +119,8 @@ public class NotesProvider extends ContentProvider {
String searchString = null; String searchString = null;
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) { if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
if (uri.getPathSegments().size() > 1) { if (uri.getPathSegments().size() > 1) {
// getPathSegments()方法得到一个String的List
// 在uri.getPathSegments().get(1)为第2个元素
searchString = uri.getPathSegments().get(1); searchString = uri.getPathSegments().get(1);
} }
} else { } else {
@ -149,7 +132,7 @@ public class NotesProvider extends ContentProvider {
} }
try { try {
searchString = String.format("%%%s%%", searchString);//在新建便签并输入内容保存后会跳到这里,暂时不知道为什么 searchString = String.format("%%%s%%", searchString);
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY, c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY,
new String[] { searchString }); new String[] { searchString });
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
@ -157,6 +140,7 @@ public class NotesProvider extends ContentProvider {
} }
break; break;
default: default:
// 抛出异常
throw new IllegalArgumentException("Unknown URI " + uri); throw new IllegalArgumentException("Unknown URI " + uri);
} }
if (c != null) { if (c != null) {
@ -165,22 +149,18 @@ public class NotesProvider extends ContentProvider {
return c; return c;
} }
/**
* @method insert
* @description: Uri便
* @date: 2023/12/21 21:16
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
// 插入一个uri
public Uri insert(Uri uri, ContentValues values) { public Uri insert(Uri uri, ContentValues values) {
// 获得可写的数据库
SQLiteDatabase db = mHelper.getWritableDatabase(); SQLiteDatabase db = mHelper.getWritableDatabase();
long dataId = 0, noteId = 0, insertedId = 0; long dataId = 0, noteId = 0, insertedId = 0;
switch (mMatcher.match(uri)) { switch (mMatcher.match(uri)) {
// 新增一个条目
case URI_NOTE: case URI_NOTE:
insertedId = noteId = db.insert(TABLE.NOTE, null, values); insertedId = noteId = db.insert(TABLE.NOTE, null, values);
break; break;
// 如果存在查找NOTE_ID
case URI_DATA: case URI_DATA:
if (values.containsKey(DataColumns.NOTE_ID)) { if (values.containsKey(DataColumns.NOTE_ID)) {
noteId = values.getAsLong(DataColumns.NOTE_ID); noteId = values.getAsLong(DataColumns.NOTE_ID);
@ -193,6 +173,7 @@ public class NotesProvider extends ContentProvider {
throw new IllegalArgumentException("Unknown URI " + uri); throw new IllegalArgumentException("Unknown URI " + uri);
} }
// Notify the note uri // Notify the note uri
// notifyChange获得一个ContextResolver对象并且更新里面的内容
if (noteId > 0) { if (noteId > 0) {
getContext().getContentResolver().notifyChange( getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null); ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
@ -204,20 +185,17 @@ public class NotesProvider extends ContentProvider {
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null); ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
} }
// 返回插入的uri的路径
return ContentUris.withAppendedId(uri, insertedId); return ContentUris.withAppendedId(uri, insertedId);
} }
/**
* @method delete
* @description: Uri便
* @date: 2023/12/21 21:17
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
// 删除一个uri
public int delete(Uri uri, String selection, String[] selectionArgs) { public int delete(Uri uri, String selection, String[] selectionArgs) {
//Uri代表要操作的数据Android上可用的每种资源 -包括 图像、视频片段、音频资源等都可以用Uri来表示。
int count = 0; int count = 0;
String id = null; String id = null;
// 获得可写的数据库
SQLiteDatabase db = mHelper.getWritableDatabase(); SQLiteDatabase db = mHelper.getWritableDatabase();
boolean deleteData = false; boolean deleteData = false;
switch (mMatcher.match(uri)) { switch (mMatcher.match(uri)) {
@ -226,7 +204,7 @@ public class NotesProvider extends ContentProvider {
count = db.delete(TABLE.NOTE, selection, selectionArgs); count = db.delete(TABLE.NOTE, selection, selectionArgs);
break; break;
case URI_NOTE_ITEM: case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);//修改便签内容时会触发,原因不明 id = uri.getPathSegments().get(1);
/** /**
* ID that smaller than 0 is system folder which is not allowed to * ID that smaller than 0 is system folder which is not allowed to
* trash * trash
@ -259,15 +237,9 @@ public class NotesProvider extends ContentProvider {
} }
return count; return count;
} }
/**
* @method update
* @description: Uri便delete
* @date: 2023/12/21 21:19
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
// 更新一个uri
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0; int count = 0;
String id = null; String id = null;
@ -307,10 +279,12 @@ public class NotesProvider extends ContentProvider {
return count; return count;
} }
// 将字符串解析成规定格式
private String parseSelection(String selection) { private String parseSelection(String selection) {
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
} }
//增加一个noteVersion
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
StringBuilder sql = new StringBuilder(120); StringBuilder sql = new StringBuilder(120);
sql.append("UPDATE "); sql.append("UPDATE ");
@ -333,6 +307,7 @@ public class NotesProvider extends ContentProvider {
sql.append(selectString); sql.append(selectString);
} }
// execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句
mHelper.getWritableDatabase().execSQL(sql.toString()); mHelper.getWritableDatabase().execSQL(sql.toString());
} }
@ -342,4 +317,4 @@ public class NotesProvider extends ContentProvider {
return null; return null;
} }
} }

@ -24,26 +24,12 @@ import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: MetaData
* @Description:
* @Author: WuShuxian
* @CreateDate: 2023/12/22 21:45
* @Version: 1.0
*/
public class MetaData extends Task { public class MetaData extends Task {
private final static String TAG = MetaData.class.getSimpleName(); private final static String TAG = MetaData.class.getSimpleName();
private String mRelatedGid = null; private String mRelatedGid = null;
/**
* @method setMeta
* @description:
* @date: 2023/12/24 20:07
* @author: WuShuxian
* @param:
* @return:
*/
public void setMeta(String gid, JSONObject metaInfo) { public void setMeta(String gid, JSONObject metaInfo) {
try { try {
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
@ -62,14 +48,7 @@ public class MetaData extends Task {
public boolean isWorthSaving() { public boolean isWorthSaving() {
return getNotes() != null; return getNotes() != null;
} }
/**
* @method setContentByRemoteJSON
* @description: Json
* @date: 2023/12/24 20:11
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
public void setContentByRemoteJSON(JSONObject js) { public void setContentByRemoteJSON(JSONObject js) {
super.setContentByRemoteJSON(js); super.setContentByRemoteJSON(js);
@ -83,14 +62,7 @@ public class MetaData extends Task {
} }
} }
} }
/**
* @method setContentByLocalJSON
* @description: Json
* @date: 2023/12/24 20:12
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
public void setContentByLocalJSON(JSONObject js) { public void setContentByLocalJSON(JSONObject js) {
// this function should not be called // this function should not be called

@ -19,50 +19,24 @@ package net.micode.notes.gtask.data;
import android.database.Cursor; import android.database.Cursor;
import org.json.JSONObject; import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: Node
* @Description: Git
* @Author: WuShuxian
* @CreateDate: 2023/12/21 21:30
* @Version: 1.0
*/
public abstract class Node { public abstract class Node {
/**
*
*/
public static final int SYNC_ACTION_NONE = 0; public static final int SYNC_ACTION_NONE = 0;
/**
*
*/
public static final int SYNC_ACTION_ADD_REMOTE = 1; public static final int SYNC_ACTION_ADD_REMOTE = 1;
/**
*
*/
public static final int SYNC_ACTION_ADD_LOCAL = 2; 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_REMOTE = 3;
/**
*
*/
public static final int SYNC_ACTION_DEL_LOCAL = 4; 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_REMOTE = 5;
/**
*
*/
public static final int SYNC_ACTION_UPDATE_LOCAL = 6; public static final int SYNC_ACTION_UPDATE_LOCAL = 6;
/**
*
*/
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;
/**
*
*/
public static final int SYNC_ACTION_ERROR = 8; public static final int SYNC_ACTION_ERROR = 8;
private String mGid; private String mGid;

@ -34,15 +34,7 @@ import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: SqlData
* @Description: 便sqlnotedatanote
* SqlData
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:13
* @Version: 1.0
*/
public class SqlData { public class SqlData {
private static final String TAG = SqlData.class.getSimpleName(); private static final String TAG = SqlData.class.getSimpleName();
@ -52,9 +44,7 @@ public class SqlData {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1, DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3 DataColumns.DATA3
}; };
/**
* sql5
*/
public static final int DATA_ID_COLUMN = 0; public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1; public static final int DATA_MIME_TYPE_COLUMN = 1;
@ -80,14 +70,7 @@ public class SqlData {
private String mDataContentData3; private String mDataContentData3;
private ContentValues mDiffDataValues; private ContentValues mDiffDataValues;
/**
* @method SqlData
* @description:
* @date: 2023/12/24 20:17
* @author: WuShuxian
* @param:
* @return:
*/
public SqlData(Context context) { public SqlData(Context context) {
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = true; mIsCreate = true;
@ -98,28 +81,14 @@ public class SqlData {
mDataContentData3 = ""; mDataContentData3 = "";
mDiffDataValues = new ContentValues(); mDiffDataValues = new ContentValues();
} }
/**
* @method SqlData
* @description:
* @date: 2023/12/24 20:17
* @author: WuShuxian
* @param:
* @return:
*/
public SqlData(Context context, Cursor c) { public SqlData(Context context, Cursor c) {
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = false; mIsCreate = false;
loadFromCursor(c); loadFromCursor(c);
mDiffDataValues = new ContentValues(); mDiffDataValues = new ContentValues();
} }
/**
* @method loadFromCursor
* @description:
* @date: 2023/12/24 20:18
* @author: WuShuxian
* @param: c:
* @return: void
*/
private void loadFromCursor(Cursor c) { private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN); mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN); mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
@ -127,14 +96,7 @@ public class SqlData {
mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN); mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN);
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN); mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
} }
/**
* @method setContent
* @description:
* @date: 2023/12/24 20:19
* @author: WuShuxian
* @param: js: Json
* @return: void
*/
public void setContent(JSONObject js) throws JSONException { public void setContent(JSONObject js) throws JSONException {
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID; long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId != dataId) { if (mIsCreate || mDataId != dataId) {
@ -181,16 +143,7 @@ public class SqlData {
js.put(DataColumns.DATA3, mDataContentData3); js.put(DataColumns.DATA3, mDataContentData3);
return js; return js;
} }
/**
* @method commit
* @description: commit
* @date: 2023/12/24 20:21
* @author: WuShuxian
* @param: noteId便ID
* validateVersion
* version
* @return: void
*/
public void commit(long noteId, boolean validateVersion, long version) { public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) { if (mIsCreate) {

@ -37,14 +37,7 @@ import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: SqlNote
* @Description: 便sqldatanotedata
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:23
* @Version: 1.0
*/
public class SqlNote { public class SqlNote {
private static final String TAG = SqlNote.class.getSimpleName(); private static final String TAG = SqlNote.class.getSimpleName();
@ -128,24 +121,17 @@ public class SqlNote {
private ContentValues mDiffNoteValues; private ContentValues mDiffNoteValues;
private ArrayList<SqlData> mDataList; private ArrayList<SqlData> mDataList;
/**
* @method SqlNote
* @description: context
* @date: 2023/12/24 20:24
* @author: WuShuxian
* @param:
* @return:
*/
public SqlNote(Context context) { public SqlNote(Context context) {
mContext = context; mContext = context;
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = true;//用于标识构造方法 mIsCreate = true;
mId = INVALID_ID; mId = INVALID_ID;
mAlertDate = 0; mAlertDate = 0;
mBgColorId = ResourceParser.getDefaultBgId(context); mBgColorId = ResourceParser.getDefaultBgId(context);
mCreatedDate = System.currentTimeMillis();//调用系统函数获得创建时间 mCreatedDate = System.currentTimeMillis();
mHasAttachment = 0; mHasAttachment = 0;
mModifiedDate = System.currentTimeMillis();//最后一次修改时间初始化为创建时间 mModifiedDate = System.currentTimeMillis();
mParentId = 0; mParentId = 0;
mSnippet = ""; mSnippet = "";
mType = Notes.TYPE_NOTE; mType = Notes.TYPE_NOTE;
@ -156,36 +142,22 @@ public class SqlNote {
mDiffNoteValues = new ContentValues(); mDiffNoteValues = new ContentValues();
mDataList = new ArrayList<SqlData>(); mDataList = new ArrayList<SqlData>();
} }
/**
* @method SqlNote
* @description:
* @date: 2023/12/24 20:25
* @author: WuShuxian
* @param:
* @return:
*/
public SqlNote(Context context, Cursor c) { public SqlNote(Context context, Cursor c) {
mContext = context; mContext = context;
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = false;//用于标识构造方法 mIsCreate = false;
loadFromCursor(c); loadFromCursor(c);
mDataList = new ArrayList<SqlData>(); mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE) if (mType == Notes.TYPE_NOTE)
loadDataContent(); loadDataContent();
mDiffNoteValues = new ContentValues(); mDiffNoteValues = new ContentValues();
} }
/**
* @method SqlNote
* @description: ID
* @date: 2023/12/24 20:27
* @author: WuShuxian
* @param:
* @return:
*/
public SqlNote(Context context, long id) { public SqlNote(Context context, long id) {
mContext = context; mContext = context;
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = false;//标识构造方法 mIsCreate = false;
loadFromCursor(id); loadFromCursor(id);
mDataList = new ArrayList<SqlData>(); mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE) if (mType == Notes.TYPE_NOTE)
@ -227,14 +199,7 @@ public class SqlNote {
mWidgetType = c.getInt(WIDGET_TYPE_COLUMN); mWidgetType = c.getInt(WIDGET_TYPE_COLUMN);
mVersion = c.getLong(VERSION_COLUMN); mVersion = c.getLong(VERSION_COLUMN);
} }
/**
* @method loadDataContent
* @description: content
* @date: 2023/12/24 20:29
* @author: WuShuxian
* @param:
* @return:
*/
private void loadDataContent() { private void loadDataContent() {
Cursor c = null; Cursor c = null;
mDataList.clear(); mDataList.clear();
@ -474,14 +439,7 @@ public class SqlNote {
public boolean isNoteType() { public boolean isNoteType() {
return mType == Notes.TYPE_NOTE; return mType == Notes.TYPE_NOTE;
} }
/**
* @method commit
* @description: commit
* @date: 2023/12/24 20:30
* @author: WuShuxian
* @param:
* @return:
*/
public void commit(boolean validateVersion) { public void commit(boolean validateVersion) {
if (mIsCreate) { if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) { if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {

@ -31,14 +31,7 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: Task
* @Description: Node
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:31
* @Version: 1.0
*/
public class Task extends Node { public class Task extends Node {
private static final String TAG = Task.class.getSimpleName(); private static final String TAG = Task.class.getSimpleName();
@ -60,25 +53,22 @@ public class Task extends Node {
mParent = null; mParent = null;
mMetaInfo = null; mMetaInfo = null;
} }
/**
* @method getCreateAction
* @description: Json
* @date: 2023/12/24 20:33
* @author: WuShuxian
* @param:
* @return:
*/
public JSONObject getCreateAction(int actionId) { public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
// action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// index
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this)); js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
// entity_delta
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
@ -89,13 +79,17 @@ public class Task extends Node {
} }
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
// parent_id
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid()); js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
// dest_parent_type
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE, js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP); GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
// list_id
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid()); js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
// prior_sibling_id
if (mPriorSibling != null) { if (mPriorSibling != null) {
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid()); js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());
} }
@ -108,25 +102,22 @@ public class Task extends Node {
return js; return js;
} }
/**
* @method getUpdateAction
* @description: Json
* @date: 2023/12/24 20:34
* @author: WuShuxian
* @param:
* @return:
*/
public JSONObject getUpdateAction(int actionId) { public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// id
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// entity_delta
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
if (getNotes() != null) { if (getNotes() != null) {
@ -147,26 +138,32 @@ public class Task extends Node {
public void setContentByRemoteJSON(JSONObject js) { public void setContentByRemoteJSON(JSONObject js) {
if (js != null) { if (js != null) {
try { try {
// id
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
} }
// last_modified
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
} }
// name
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
} }
// notes
if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) { if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES)); setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
} }
// deleted
if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) { if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED)); setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
} }
// completed
if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) { if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) {
setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED)); setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED));
} }
@ -211,6 +208,7 @@ public class Task extends Node {
String name = getName(); String name = getName();
try { try {
if (mMetaInfo == null) { if (mMetaInfo == null) {
// new task created from web
if (name == null) { if (name == null) {
Log.w(TAG, "the note seems to be an empty one"); Log.w(TAG, "the note seems to be an empty one");
return null; return null;
@ -227,6 +225,7 @@ public class Task extends Node {
js.put(GTaskStringUtils.META_HEAD_NOTE, note); js.put(GTaskStringUtils.META_HEAD_NOTE, note);
return js; return js;
} else { } else {
// synced task
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA); JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
@ -276,24 +275,29 @@ public class Task extends Node {
return SYNC_ACTION_UPDATE_LOCAL; return SYNC_ACTION_UPDATE_LOCAL;
} }
// 立即验证note id // validate the note id now
if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) { if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) {
Log.w(TAG, "note id doesn't match"); Log.w(TAG, "note id doesn't match");
return SYNC_ACTION_UPDATE_LOCAL; return SYNC_ACTION_UPDATE_LOCAL;
} }
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
// there is no local update
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// no update both side
return SYNC_ACTION_NONE; return SYNC_ACTION_NONE;
} else { } else {
// apply remote to local
return SYNC_ACTION_UPDATE_LOCAL; return SYNC_ACTION_UPDATE_LOCAL;
} }
} else { } else {
// validate gtask id
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "gtask id doesn't match"); Log.e(TAG, "gtask id doesn't match");
return SYNC_ACTION_ERROR; return SYNC_ACTION_ERROR;
} }
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// local modification only
return SYNC_ACTION_UPDATE_REMOTE; return SYNC_ACTION_UPDATE_REMOTE;
} else { } else {
return SYNC_ACTION_UPDATE_CONFLICT; return SYNC_ACTION_UPDATE_CONFLICT;

@ -29,14 +29,7 @@ import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
/**
* @Package: net.micode.notes.gtask.data
* @ClassName: TaskList
* @Description: Node
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:40
* @Version: 1.0
*/
public class TaskList extends Node { public class TaskList extends Node {
private static final String TAG = TaskList.class.getSimpleName(); private static final String TAG = TaskList.class.getSimpleName();
@ -54,13 +47,17 @@ public class TaskList extends Node {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);// 动作类型 GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);// 动作编号 // action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// index
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// entity_delta
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
@ -81,13 +78,17 @@ public class TaskList extends Node {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
try { try {
// action_type
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);//动作类型 GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);//动作编号 // action_id
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// id
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// entity_delta
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
@ -105,14 +106,17 @@ public class TaskList extends Node {
public void setContentByRemoteJSON(JSONObject js) { public void setContentByRemoteJSON(JSONObject js) {
if (js != null) { if (js != null) {
try { try {
// id
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
} }
// last_modified
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
} }
// name
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
} }
@ -221,6 +225,7 @@ public class TaskList extends Node {
if (task != null && !mChildren.contains(task)) { if (task != null && !mChildren.contains(task)) {
ret = mChildren.add(task); ret = mChildren.add(task);
if (ret) { if (ret) {
// need to set prior sibling and parent
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren task.setPriorSibling(mChildren.isEmpty() ? null : mChildren
.get(mChildren.size() - 1)); .get(mChildren.size() - 1));
task.setParent(this); task.setParent(this);
@ -239,7 +244,7 @@ public class TaskList extends Node {
if (task != null && pos == -1) { if (task != null && pos == -1) {
mChildren.add(index, task); mChildren.add(index, task);
// 更新任务列表 // update the task list
Task preTask = null; Task preTask = null;
Task afterTask = null; Task afterTask = null;
if (index != 0) if (index != 0)
@ -262,9 +267,11 @@ public class TaskList extends Node {
ret = mChildren.remove(task); ret = mChildren.remove(task);
if (ret) { if (ret) {
// reset prior sibling and parent
task.setPriorSibling(null); task.setPriorSibling(null);
task.setParent(null); task.setParent(null);
// update the task list
if (index != mChildren.size()) { if (index != mChildren.size()) {
mChildren.get(index).setPriorSibling( mChildren.get(index).setPriorSibling(
index == 0 ? null : mChildren.get(index - 1)); index == 0 ? null : mChildren.get(index - 1));

@ -15,19 +15,8 @@
*/ */
package net.micode.notes.gtask.exception; package net.micode.notes.gtask.exception;
/**
* @Package: net.micode.notes.gtask.exception
* @ClassName: ActionFailureException
* @Description: 便
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:45
* @Version: 1.0
*/
public class ActionFailureException extends RuntimeException { public class ActionFailureException extends RuntimeException {
/**
* serialVersionUIDjava
* serialVersionUID
*/
private static final long serialVersionUID = 4425249765923293627L; private static final long serialVersionUID = 4425249765923293627L;
public ActionFailureException() { public ActionFailureException() {

@ -15,19 +15,8 @@
*/ */
package net.micode.notes.gtask.exception; package net.micode.notes.gtask.exception;
/**
* @Package: net.micode.notes.gtask.exception
* @ClassName: NetworkFailureException
* @Description: 便
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:46
* @Version: 1.0
*/
public class NetworkFailureException extends Exception { public class NetworkFailureException extends Exception {
/**
* serialVersionUIDjava
* serialVersionUID
*/
private static final long serialVersionUID = 2107610287180234136L; private static final long serialVersionUID = 2107610287180234136L;
public NetworkFailureException() { public NetworkFailureException() {

@ -28,14 +28,7 @@ import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity; import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity; import net.micode.notes.ui.NotesPreferenceActivity;
/**
* @Package: net.micode.notes.gtask.remote
* @ClassName: GTaskASyncTask
* @Description: GTask
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:49
* @Version: 1.0
*/
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> { public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
@ -69,22 +62,9 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
message message
}); });
} }
/**
* @method showNotification
* @description:
* @date: 2023/12/24 20:50
* @author: WuShuxian
* @param:
* @return:
*/
private void showNotification(int tickerId, String content) { 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 pendingIntent;
//如果同步不成功那么从系统取得一个用于启动一个NotesPreferenceActivity的PendingIntent对象
//如果同步成功那么从系统取得一个用于启动一个NotesListActivity的PendingIntent对象
if (tickerId != R.string.ticker_success) { if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0); NotesPreferenceActivity.class), 0);
@ -93,18 +73,21 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0); NotesListActivity.class), 0);
} }
//notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
//pendingIntent);
Notification.Builder builder = new Notification.Builder(mContext)
.setAutoCancel(true)
.setContentTitle(mContext.getString(R.string.app_name))
.setContentText(content)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setOngoing(true);
Notification notification=builder.getNotification();
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
} }
/**
* @method doInBackground
* @description: 线
* @date: 2023/12/24 20:51
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
protected Integer doInBackground(Void... unused) { protected Integer doInBackground(Void... unused) {
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
@ -112,14 +95,6 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
return mTaskManager.sync(mContext, this); return mTaskManager.sync(mContext, this);
} }
/**
* @method onProgressUpdate
* @description: 使 线
* @date: 2023/12/24 20:51
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
protected void onProgressUpdate(String... progress) { protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]); showNotification(R.string.ticker_syncing, progress[0]);
@ -128,14 +103,6 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
} }
} }
/**
* @method onPostExecute
* @description: Handler UI使doInBackground UI
* @date: 2023/12/24 20:51
* @author: WuShuxian
* @param:
* @return:
*/
@Override @Override
protected void onPostExecute(Integer result) { protected void onPostExecute(Integer result) {
if (result == GTaskManager.STATE_SUCCESS) { if (result == GTaskManager.STATE_SUCCESS) {

@ -60,14 +60,7 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater; import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
/**
* @Package: net.micode.notes.gtask.remote
* @ClassName: GTaskClient
* @Description: GTASKGTASK
* @Author: WuShuxian
* @CreateDate: 2023/12/24 20:55
* @Version: 1.0
*/
public class GTaskClient { public class GTaskClient {
private static final String TAG = GTaskClient.class.getSimpleName(); private static final String TAG = GTaskClient.class.getSimpleName();
@ -97,12 +90,6 @@ public class GTaskClient {
private JSONArray mUpdateArray; private JSONArray mUpdateArray;
/**
* @method GTaskClient
* @description:
* @date: 2023/12/24 20:56
* @author: WuShuxian
*/
private GTaskClient() { private GTaskClient() {
mHttpClient = null; mHttpClient = null;
mGetUrl = GTASK_GET_URL; mGetUrl = GTASK_GET_URL;
@ -121,40 +108,35 @@ public class GTaskClient {
} }
return mInstance; return mInstance;
} }
/**
* @method login
* @description: 使URL使URL
* @date: 2023/12/24 21:15
* @author: WuShuxian
* @param: activity
* @return: boolean
*/
public boolean login(Activity activity) { public boolean login(Activity activity) {
//判断距离最后一次登录操作是否超过5分钟 // we suppose that the cookie would expire after 5 minutes
// then we need to re-login
final long interval = 1000 * 60 * 5; final long interval = 1000 * 60 * 5;
if (mLastLoginTime + interval < System.currentTimeMillis()) { if (mLastLoginTime + interval < System.currentTimeMillis()) {
mLoggedin = false; mLoggedin = false;
} }
// 重新登陆操作 // need to re-login after account switch
if (mLoggedin if (mLoggedin
&& !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity
.getSyncAccountName(activity))) { .getSyncAccountName(activity))) {
mLoggedin = false; mLoggedin = false;
} }
//如果没超过时间,则不需要重新登录
if (mLoggedin) { if (mLoggedin) {
Log.d(TAG, "already logged in"); Log.d(TAG, "already logged in");
return true; return true;
} }
mLastLoginTime = System.currentTimeMillis();//更新最后登录时间为系统当前的时间 mLastLoginTime = System.currentTimeMillis();
String authToken = loginGoogleAccount(activity, false);//判断是否登录到谷歌账户 String authToken = loginGoogleAccount(activity, false);
if (authToken == null) { if (authToken == null) {
Log.e(TAG, "login google account failed"); Log.e(TAG, "login google account failed");
return false; return false;
} }
// login with custom domain if necessary
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase() if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
.endsWith("googlemail.com"))) { .endsWith("googlemail.com"))) {
StringBuilder url = new StringBuilder(GTASK_URL).append("a/"); StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
@ -168,7 +150,8 @@ public class GTaskClient {
mLoggedin = true; mLoggedin = true;
} }
} }
//如果用户账户无法登录则使用谷歌官方的URI进行登录
// try to login with google official url
if (!mLoggedin) { if (!mLoggedin) {
mGetUrl = GTASK_GET_URL; mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL; mPostUrl = GTASK_POST_URL;
@ -180,14 +163,7 @@ public class GTaskClient {
mLoggedin = true; mLoggedin = true;
return true; return true;
} }
/**
* @method loginGoogleAccount
* @description:
* @date: 2023/12/24 23:07
* @author: WuShuxian
* @param: activity
* @return: String
*/
private String loginGoogleAccount(Activity activity, boolean invalidateToken) { private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
String authToken; String authToken;
AccountManager accountManager = AccountManager.get(activity); AccountManager accountManager = AccountManager.get(activity);
@ -200,7 +176,6 @@ public class GTaskClient {
String accountName = NotesPreferenceActivity.getSyncAccountName(activity); String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
Account account = null; Account account = null;
//遍历获得的accounts信息寻找已经记录过的账户信息
for (Account a : accounts) { for (Account a : accounts) {
if (a.name.equals(accountName)) { if (a.name.equals(accountName)) {
account = a; account = a;
@ -214,7 +189,7 @@ public class GTaskClient {
return null; return null;
} }
//获取令牌 // get the token now
AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account, AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null); "goanna_mobile", null, activity, null, null);
try { try {
@ -231,16 +206,11 @@ public class GTaskClient {
return authToken; return authToken;
} }
/**
* @method tryToLoginGtask
* @description: GtaskGTask,
* @date: 2023/12/24 21:01
* @author: WuShuxian
* @param:
* @return:
*/
private boolean tryToLoginGtask(Activity activity, String authToken) { private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) { if (!loginGtask(authToken)) {
// maybe the auth token is out of date, now let's invalidate the
// token and try again
authToken = loginGoogleAccount(activity, true); authToken = loginGoogleAccount(activity, true);
if (authToken == null) { if (authToken == null) {
Log.e(TAG, "login google account failed"); Log.e(TAG, "login google account failed");
@ -254,33 +224,26 @@ public class GTaskClient {
} }
return true; return true;
} }
/**
* @method loginGtask
* @description:
* @date: 2023/12/24 21:05
* @author: WuShuxian
* @param:
* @return:
*/
private boolean loginGtask(String authToken) { private boolean loginGtask(String authToken) {
int timeoutConnection = 10000; int timeoutConnection = 10000;
int timeoutSocket = 15000; //socket是一种通信连接实现数据的交换的端口 int timeoutSocket = 15000;
HttpParams httpParameters = new BasicHttpParams(); //实例化一个新的HTTP参数类 HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);//设置连接超时时间 HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);//设置设置端口超时时间 HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
mHttpClient = new DefaultHttpClient(httpParameters); mHttpClient = new DefaultHttpClient(httpParameters);
BasicCookieStore localBasicCookieStore = new BasicCookieStore(); BasicCookieStore localBasicCookieStore = new BasicCookieStore();
mHttpClient.setCookieStore(localBasicCookieStore); mHttpClient.setCookieStore(localBasicCookieStore);
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false); HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false);
//登录操作 // login gtask
try { try {
String loginUrl = mGetUrl + "?auth=" + authToken;//设置登录的URL String loginUrl = mGetUrl + "?auth=" + authToken;
HttpGet httpGet = new HttpGet(loginUrl);//通过登录的uri实例化网页上资源的查找 HttpGet httpGet = new HttpGet(loginUrl);
HttpResponse response = null; HttpResponse response = null;
response = mHttpClient.execute(httpGet); response = mHttpClient.execute(httpGet);
//获取CookieStore里存放的cookie,如果存有“GTL”则cookie有效 // get the cookie now
List<Cookie> cookies = mHttpClient.getCookieStore().getCookies(); List<Cookie> cookies = mHttpClient.getCookieStore().getCookies();
boolean hasAuthCookie = false; boolean hasAuthCookie = false;
for (Cookie cookie : cookies) { for (Cookie cookie : cookies) {
@ -292,7 +255,7 @@ public class GTaskClient {
Log.w(TAG, "it seems that there is no auth cookie"); Log.w(TAG, "it seems that there is no auth cookie");
} }
//获取client的内容 // get the client version
String resString = getResponseContent(response.getEntity()); String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup("; String jsBegin = "_setup(";
String jsEnd = ")}</script>"; String jsEnd = ")}</script>";
@ -309,6 +272,7 @@ public class GTaskClient {
e.printStackTrace(); e.printStackTrace();
return false; return false;
} catch (Exception e) { } catch (Exception e) {
// simply catch all exceptions
Log.e(TAG, "httpget gtask_url failed"); Log.e(TAG, "httpget gtask_url failed");
return false; return false;
} }
@ -319,24 +283,14 @@ public class GTaskClient {
private int getActionId() { private int getActionId() {
return mActionId++; return mActionId++;
} }
/**
* @method createHttpPost
* @description:
* @date: 2023/12/24 23:13
* @author: WuShuxian
*/
private HttpPost createHttpPost() { private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl); HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
httpPost.setHeader("AT", "1"); httpPost.setHeader("AT", "1");
return httpPost; return httpPost;
} }
/**
* @method getResponseContent
* @description: URL
* @date: 2023/12/24 21:06
* @author: WuShuxian
*/
private String getResponseContent(HttpEntity entity) throws IOException { private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null; String contentEncoding = null;
if (entity.getContentEncoding() != null) { if (entity.getContentEncoding() != null) {
@ -368,20 +322,13 @@ public class GTaskClient {
input.close(); input.close();
} }
} }
/**
* @method postRequest
* @description: Json
* @date: 2023/12/24 21:07
* @author: WuShuxian
* @param: js
* @return:
*/
private JSONObject postRequest(JSONObject js) throws NetworkFailureException { private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) { if (!mLoggedin) {
Log.e(TAG, "please login first"); Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in"); throw new ActionFailureException("not logged in");
} }
//实例化一个httpPost的对象用来向服务器传输数据在这里就是发送请求而请求的内容在js里
HttpPost httpPost = createHttpPost(); HttpPost httpPost = createHttpPost();
try { try {
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>(); LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
@ -389,8 +336,9 @@ public class GTaskClient {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
httpPost.setEntity(entity); httpPost.setEntity(entity);
// execute the post
HttpResponse response = mHttpClient.execute(httpPost); HttpResponse response = mHttpClient.execute(httpPost);
String jsString = getResponseContent(response.getEntity());//得到返回的数据和资源 String jsString = getResponseContent(response.getEntity());
return new JSONObject(jsString); return new JSONObject(jsString);
} catch (ClientProtocolException e) { } catch (ClientProtocolException e) {
@ -411,25 +359,21 @@ public class GTaskClient {
throw new ActionFailureException("error occurs when posting request"); throw new ActionFailureException("error occurs when posting request");
} }
} }
/**
* @method createTask
* @description:
* @date: 2023/12/24 21:08
* @author: WuShuxian
* @param: task
* @return: void
*/
public void createTask(Task task) throws NetworkFailureException { public void createTask(Task task) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
JSONObject jsPost = new JSONObject(); JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray(); JSONArray actionList = new JSONArray();
// action_list
actionList.put(task.getCreateAction(getActionId())); actionList.put(task.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
// post
JSONObject jsResponse = postRequest(jsPost); JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray( JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0); GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
@ -441,29 +385,25 @@ public class GTaskClient {
throw new ActionFailureException("create task: handing jsonobject failed"); throw new ActionFailureException("create task: handing jsonobject failed");
} }
} }
/**
* @method createTaskList
* @description: createTasktasklistgid
* @date: 2023/12/24 21:09
* @author: WuShuxian
* @param: tasklist
* @return: void
*/
public void createTaskList(TaskList tasklist) throws NetworkFailureException { public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
JSONObject jsPost = new JSONObject(); JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray(); JSONArray actionList = new JSONArray();
// action_list
actionList.put(tasklist.getCreateAction(getActionId())); actionList.put(tasklist.getCreateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
JSONObject jsResponse = postRequest(jsPost);//得到任务的返回信息 // post
JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray( JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0); GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));//设置task的new_id tasklist.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
} catch (JSONException e) { } catch (JSONException e) {
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
@ -477,8 +417,10 @@ public class GTaskClient {
try { try {
JSONObject jsPost = new JSONObject(); JSONObject jsPost = new JSONObject();
// action_list
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray);
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost); postRequest(jsPost);
@ -490,17 +432,11 @@ public class GTaskClient {
} }
} }
} }
/**
* @method addUpdateNode
* @description:
* @date: 2023/12/24 23:19
* @author: WuShuxian
* @param: node
* @return: void
*/
public void addUpdateNode(Node node) throws NetworkFailureException { public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) { if (node != null) {
//设置更新同步项目数量上限10 // too many update items may result in an error
// set max to 10 items
if (mUpdateArray != null && mUpdateArray.length() > 10) { if (mUpdateArray != null && mUpdateArray.length() > 10) {
commitUpdate(); commitUpdate();
} }
@ -510,14 +446,7 @@ public class GTaskClient {
mUpdateArray.put(node.getUpdateAction(getActionId())); mUpdateArray.put(node.getUpdateAction(getActionId()));
} }
} }
/**
* @method moveTask
* @description: task,tasktask
* @date: 2023/12/24 23:19
* @author: WuShuxian
* @param: taskpreParentcurParent
* @return: void
*/
public void moveTask(Task task, TaskList preParent, TaskList curParent) public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException { throws NetworkFailureException {
commitUpdate(); commitUpdate();
@ -526,22 +455,26 @@ public class GTaskClient {
JSONArray actionList = new JSONArray(); JSONArray actionList = new JSONArray();
JSONObject action = new JSONObject(); JSONObject action = new JSONObject();
// 动作序列 // action_list
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid()); action.put(GTaskStringUtils.GTASK_JSON_ID, task.getGid());
if (preParent == curParent && task.getPriorSibling() != null) { if (preParent == curParent && task.getPriorSibling() != null) {
action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling());//设置优先级ID只有当移动是发生在文件中 // 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_SOURCE_LIST, preParent.getGid()); action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid());
action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid());
if (preParent != curParent) { if (preParent != curParent) {
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());//仅当在任务列表之间移动时才放入dest_list // put the dest_list only if moving between tasklists
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());
} }
actionList.put(action); actionList.put(action);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);//将ACTION_LIST加入到jsPost中 jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost); postRequest(jsPost);
@ -552,27 +485,22 @@ public class GTaskClient {
throw new ActionFailureException("move task: handing jsonobject failed"); throw new ActionFailureException("move task: handing jsonobject failed");
} }
} }
/**
* @method deleteNode
* @description:
* @date: 2023/12/24 23:22
* @author: WuShuxian
* @param: node
* @return: void
*/
public void deleteNode(Node node) throws NetworkFailureException { public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
JSONObject jsPost = new JSONObject(); JSONObject jsPost = new JSONObject();
JSONArray actionList = new JSONArray(); JSONArray actionList = new JSONArray();
// action_list
node.setDeleted(true); node.setDeleted(true);
actionList.put(node.getUpdateAction(getActionId()));//获取删除操作的ID加入actionLiast actionList.put(node.getUpdateAction(getActionId()));
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
postRequest(jsPost);//使用postRequest发送删除后的结果 postRequest(jsPost);
mUpdateArray = null; mUpdateArray = null;
} catch (JSONException e) { } catch (JSONException e) {
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
@ -580,14 +508,7 @@ public class GTaskClient {
throw new ActionFailureException("delete node: handing jsonobject failed"); throw new ActionFailureException("delete node: handing jsonobject failed");
} }
} }
/**
* @method getTaskLists
* @description:
* @date: 2023/12/24 23:24
* @author: WuShuxian
* @param: void
* @return:
*/
public JSONArray getTaskLists() throws NetworkFailureException { public JSONArray getTaskLists() throws NetworkFailureException {
if (!mLoggedin) { if (!mLoggedin) {
Log.e(TAG, "please login first"); Log.e(TAG, "please login first");
@ -599,8 +520,8 @@ public class GTaskClient {
HttpResponse response = null; HttpResponse response = null;
response = mHttpClient.execute(httpGet); response = mHttpClient.execute(httpGet);
// 获取任务列表把筛选出的字符串放入jsString // get the task list
String resString = getResponseContent(response.getEntity());//从网上获取数据 String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup("; String jsBegin = "_setup(";
String jsEnd = ")}</script>"; String jsEnd = ")}</script>";
int begin = resString.indexOf(jsBegin); int begin = resString.indexOf(jsBegin);
@ -625,14 +546,7 @@ public class GTaskClient {
throw new ActionFailureException("get task lists: handing jasonobject failed"); throw new ActionFailureException("get task lists: handing jasonobject failed");
} }
} }
/**
* @method getTaskList
* @description: TASKListgid,
* @date: 2023/12/24 23:28
* @author: WuShuxian
* @param: listGid
* @return:
*/
public JSONArray getTaskList(String listGid) throws NetworkFailureException { public JSONArray getTaskList(String listGid) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
@ -640,6 +554,7 @@ public class GTaskClient {
JSONArray actionList = new JSONArray(); JSONArray actionList = new JSONArray();
JSONObject action = new JSONObject(); JSONObject action = new JSONObject();
// action_list
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
@ -648,6 +563,7 @@ public class GTaskClient {
actionList.put(action); actionList.put(action);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion); jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
JSONObject jsResponse = postRequest(jsPost); JSONObject jsResponse = postRequest(jsPost);

@ -47,14 +47,7 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
/**
* @Package: net.micode.notes.gtask.remote
* @ClassName: GTaskManager
* @Description:
* @Author: WuShuxian
* @CreateDate: 2023/12/24 21:13
* @Version: 1.0
*/
public class GTaskManager { public class GTaskManager {
private static final String TAG = GTaskManager.class.getSimpleName(); private static final String TAG = GTaskManager.class.getSimpleName();
@ -93,17 +86,10 @@ public class GTaskManager {
private HashMap<String, Long> mGidToNid; private HashMap<String, Long> mGidToNid;
private HashMap<Long, String> mNidToGid; private HashMap<Long, String> mNidToGid;
/**
* @method GTaskManager
* @description:
* @date: 2023/12/24 23:30
* @author: WuShuxian
* @param: void
* @return: void
*/
private GTaskManager() { private GTaskManager() {
mSyncing = false;//正在同步,flase代表未执行 mSyncing = false;
mCancelled = false;//全局标识flase代表可以执行 mCancelled = false;
mGTaskListHashMap = new HashMap<String, TaskList>(); mGTaskListHashMap = new HashMap<String, TaskList>();
mGTaskHashMap = new HashMap<String, Node>(); mGTaskHashMap = new HashMap<String, Node>();
mMetaHashMap = new HashMap<String, MetaData>(); mMetaHashMap = new HashMap<String, MetaData>();
@ -112,14 +98,7 @@ public class GTaskManager {
mGidToNid = new HashMap<String, Long>(); mGidToNid = new HashMap<String, Long>();
mNidToGid = new HashMap<Long, String>(); mNidToGid = new HashMap<Long, String>();
} }
/**
* @method getInstance
* @description: synchronized线
* @date: 2023/12/24 23:31
* @author: WuShuxian
* @param: void
* @return: GTaskManager
*/
public static synchronized GTaskManager getInstance() { public static synchronized GTaskManager getInstance() {
if (mInstance == null) { if (mInstance == null) {
mInstance = new GTaskManager(); mInstance = new GTaskManager();
@ -128,17 +107,10 @@ public class GTaskManager {
} }
public synchronized void setActivityContext(Activity activity) { public synchronized void setActivityContext(Activity activity) {
// used for getting authtoken
mActivity = activity; mActivity = activity;
} }
/**
* @method sync
* @description:
* @date: 2023/12/24 23:32
* @author: WuShuxian
* @param: context
* asyncTask
* @return: int
*/
public int sync(Context context, GTaskASyncTask asyncTask) { public int sync(Context context, GTaskASyncTask asyncTask) {
if (mSyncing) { if (mSyncing) {
Log.d(TAG, "Sync is in progress"); Log.d(TAG, "Sync is in progress");
@ -155,9 +127,8 @@ public class GTaskManager {
mGidToNid.clear(); mGidToNid.clear();
mNidToGid.clear(); mNidToGid.clear();
//进行同步操作,并作异常处理:网络异常、操作异常
try { try {
GTaskClient client = GTaskClient.getInstance();//创建一个实例client GTaskClient client = GTaskClient.getInstance();
client.resetUpdateArray(); client.resetUpdateArray();
// login google task // login google task
@ -168,19 +139,18 @@ public class GTaskManager {
} }
// get the task list from google // get the task list from google
//从google获取task list
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list)); asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list));
initGTaskList(); initGTaskList();
//进行同步操作 // do content sync work
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing)); asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing));
syncContent(); syncContent();
} catch (NetworkFailureException e) { } catch (NetworkFailureException e) {
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
return STATE_NETWORK_ERROR;//网络异常 return STATE_NETWORK_ERROR;
} catch (ActionFailureException e) { } catch (ActionFailureException e) {
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
return STATE_INTERNAL_ERROR;//操作异常 return STATE_INTERNAL_ERROR;
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
e.printStackTrace(); e.printStackTrace();
@ -197,14 +167,7 @@ public class GTaskManager {
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
} }
/**
* @method initGTaskList
* @description: GtaskListGoogleJSONtasklistTaskList
* @date: 2023/12/24 23:39
* @author: WuShuxian
* @param:
* @return:
*/
private void initGTaskList() throws NetworkFailureException { private void initGTaskList() throws NetworkFailureException {
if (mCancelled) if (mCancelled)
return; return;
@ -212,7 +175,7 @@ public class GTaskManager {
try { try {
JSONArray jsTaskLists = client.getTaskLists(); JSONArray jsTaskLists = client.getTaskLists();
//初始化元列表 // init meta list first
mMetaList = null; mMetaList = null;
for (int i = 0; i < jsTaskLists.length(); i++) { for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i); JSONObject object = jsTaskLists.getJSONObject(i);

@ -23,6 +23,14 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
/**
* @Package: net.micode.notes.gtask.remote
* @ClassName: GTaskSyncService
* @Description:
* @Author: WuShuxian
* @CreateDate: 2024/1/15 21:36
* @Version: 1.0
*/
public class GTaskSyncService extends Service { public class GTaskSyncService extends Service {
public final static String ACTION_STRING_NAME = "sync_action_type"; public final static String ACTION_STRING_NAME = "sync_action_type";
@ -118,10 +126,17 @@ public class GTaskSyncService extends Service {
context.startService(intent); context.startService(intent);
} }
/**
* @method isSyncing
* @description:
* @date: 2024/1/15 21:38
* @author: WuShuxian
*/
public static boolean isSyncing() { public static boolean isSyncing() {
return mSyncTask != null; return mSyncTask != null;
} }
public static String getProgressString() { public static String getProgressString() {
return mSyncProgress; return mSyncProgress;
} }

@ -14,6 +14,8 @@ import android.content.SharedPreferences;
import android.graphics.Paint; import android.graphics.Paint;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
@ -71,6 +73,9 @@ import java.util.regex.Pattern;
*/ */
public class NoteEditActivity extends Activity implements OnClickListener, public class NoteEditActivity extends Activity implements OnClickListener,
NoteSettingChangedListener, OnTextViewChangeListener { NoteSettingChangedListener, OnTextViewChangeListener {
/**
*
*/
private class HeadViewHolder { private class HeadViewHolder {
public TextView tvModified; public TextView tvModified;
@ -82,6 +87,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public TextView textNum; public TextView textNum;
} }
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>(); private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
static { static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW); sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
@ -123,13 +129,21 @@ public class NoteEditActivity extends Activity implements OnClickListener,
"android.permission.WRITE_EXTERNAL_STORAGE" };//权限名称 "android.permission.WRITE_EXTERNAL_STORAGE" };//权限名称
private static final String TAG = "NoteEditActivity"; private static final String TAG = "NoteEditActivity";
private HeadViewHolder mNoteHeaderHolder; private HeadViewHolder mNoteHeaderHolder;
private View mHeadViewPanel; private View mHeadViewPanel;
private View mNoteBgColorSelector; private View mNoteBgColorSelector;
private View mFontSizeSelector; private View mFontSizeSelector;
private EditText mNoteEditor; private EditText mNoteEditor;
private View mNoteEditorPanel; private View mNoteEditorPanel;
public WorkingNote mWorkingNote;
private WorkingNote mWorkingNote;
private SharedPreferences mSharedPrefs; private SharedPreferences mSharedPrefs;
private int mFontSizeId; private int mFontSizeId;
@ -215,6 +229,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.setContentView(R.layout.note_edit); this.setContentView(R.layout.note_edit);
checkStoragePermissions(this);//动态申请权限
if (savedInstanceState == null && !initActivityState(getIntent())) { if (savedInstanceState == null && !initActivityState(getIntent())) {
finish(); finish();
return; return;
@ -237,6 +253,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
}); });
convertToImage();//将路径显示为图片 convertToImage();//将路径显示为图片
count();
} }
/** /**
@ -257,7 +274,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
} }
private boolean initActivityState(Intent intent) { private boolean initActivityState(Intent intent) {
/** /**
* If the user specified the {@link Intent#ACTION_VIEW} but not provided with id, * If the user specified the {@link Intent#ACTION_VIEW} but not provided with id,
@ -298,6 +314,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
} else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) { } else if(TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
// New note
long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0); long folderId = intent.getLongExtra(Notes.INTENT_EXTRA_FOLDER_ID, 0);
int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID, int widgetId = intent.getIntExtra(Notes.INTENT_EXTRA_WIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID); AppWidgetManager.INVALID_APPWIDGET_ID);
@ -305,6 +322,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Notes.TYPE_WIDGET_INVALIDE); Notes.TYPE_WIDGET_INVALIDE);
int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, int bgResId = intent.getIntExtra(Notes.INTENT_EXTRA_BACKGROUND_ID,
ResourceParser.getDefaultBgId(this)); ResourceParser.getDefaultBgId(this));
// Parse call-record note
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0); long callDate = intent.getLongExtra(Notes.INTENT_EXTRA_CALL_DATE, 0);
if (callDate != 0 && phoneNumber != null) { if (callDate != 0 && phoneNumber != null) {
@ -398,8 +417,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if (time > mWorkingNote.getAlertDate()) { if (time > mWorkingNote.getAlertDate()) {
mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired); mNoteHeaderHolder.tvAlertDate.setText(R.string.note_alert_expired);
} } else {
else {
mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString( mNoteHeaderHolder.tvAlertDate.setText(DateUtils.getRelativeTimeSpanString(
mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS)); mWorkingNote.getAlertDate(), time, DateUtils.MINUTE_IN_MILLIS));
} }
@ -411,12 +429,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}; };
} }
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); super.onNewIntent(intent);
initActivityState(intent); initActivityState(intent);
} }
@Override @Override
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
@ -431,6 +449,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId()); outState.putLong(Intent.EXTRA_UID, mWorkingNote.getNoteId());
Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState"); Log.d(TAG, "Save working note id: " + mWorkingNote.getNoteId() + " onSaveInstanceState");
} }
@Override @Override
public boolean dispatchTouchEvent(MotionEvent ev) { public boolean dispatchTouchEvent(MotionEvent ev) {
if (mNoteBgColorSelector.getVisibility() == View.VISIBLE if (mNoteBgColorSelector.getVisibility() == View.VISIBLE
@ -455,10 +474,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
if (ev.getX() < x if (ev.getX() < x
|| ev.getX() > (x + view.getWidth()) || ev.getX() > (x + view.getWidth())
|| ev.getY() < y || ev.getY() < y
|| ev.getY() > (y + view.getHeight())) || ev.getY() > (y + view.getHeight())) {
{ return false;
return false; }
}
return true; return true;
} }
@ -495,6 +513,24 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE; mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
} }
mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list); mEditTextList = (LinearLayout) findViewById(R.id.note_edit_list);
//朗读
mTTS = new TextToSpeech(this,new TextToSpeech.OnInitListener(){
@Override
public void onInit(int status){
// 判断是否转化成功
if (status == TextToSpeech.SUCCESS){
//默认设定语言为中文
int result = mTTS.setLanguage(Locale.CHINESE);
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED){
Toast.makeText(NoteEditActivity.this, "Language not available.", Toast.LENGTH_SHORT).show();
}else{
//不支持中文就将语言设置为英文
mTTS.setLanguage(Locale.US);
}
}
}
});
} }
@Override @Override
@ -530,7 +566,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
setResult(RESULT_OK, intent); setResult(RESULT_OK, intent);
} }
public void onClick(View v) { public void onClick(View v) {
int id = v.getId(); int id = v.getId();
if (id == R.id.btn_set_bg_color) { if (id == R.id.btn_set_bg_color) {
@ -596,6 +631,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId()); mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId()); mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
} }
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
if (isFinishing()) { if (isFinishing()) {
@ -620,6 +656,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
return true; return true;
} }
@Override @Override
/** /**
* @method onOptionsItemSelected * @method onOptionsItemSelected
@ -662,6 +699,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
setReminder(); setReminder();
} else if (itemId == R.id.menu_delete_remind) { } else if (itemId == R.id.menu_delete_remind) {
mWorkingNote.setAlertDate(0, false); mWorkingNote.setAlertDate(0, false);
} else if (itemId == R.id.menu_voice){
Log.d("voiceOut","in");
textToSpeach();
} }
return true; return true;
} }
@ -683,7 +723,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
d.show(); d.show();
} }
/** /**
* Share note to apps that support {@link Intent#ACTION_SEND} action * Share note to apps that support {@link Intent#ACTION_SEND} action
* and {@text/plain} type * and {@text/plain} type
@ -940,16 +979,20 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public void onCheckListModeChanged(int oldMode, int newMode) { public void onCheckListModeChanged(int oldMode, int newMode) {
if (newMode == TextNote.MODE_CHECK_LIST) { if (newMode == TextNote.MODE_CHECK_LIST) {
switchToListMode(mNoteEditor.getText().toString()); switchToListMode(mNoteEditor.getText().toString());
//检查模式切换到列表模式
} else { } else {
if (!getWorkingText()) { if (!getWorkingText()) {
mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ", mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
"")); ""));
} }
//若是获取到文本就改变其检查标记
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery)); mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mEditTextList.setVisibility(View.GONE); mEditTextList.setVisibility(View.GONE);
mNoteEditor.setVisibility(View.VISIBLE); mNoteEditor.setVisibility(View.VISIBLE);
//修改文本编辑器的内容和可见性
} }
} }
/** /**
* @method getWorkingText * @method getWorkingText
* @description * @description
@ -958,26 +1001,23 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* @return * @return
*/ */
private boolean getWorkingText() { private boolean getWorkingText() {
boolean hasChecked = false;//初始化check标记 boolean hasChecked = false;
//初始化check标记
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
/** // 若模式为CHECK_LIST
* CHECK_LIST
*
*
*/
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
//创建可变字符串
for (int i = 0; i < mEditTextList.getChildCount(); i++) { for (int i = 0; i < mEditTextList.getChildCount(); i++) {
View view = mEditTextList.getChildAt(i); View view = mEditTextList.getChildAt(i);
//遍历所有子编辑框的视图
NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
if (!TextUtils.isEmpty(edit.getText())) { if (!TextUtils.isEmpty(edit.getText())) {
/** //若文本不为空
*
*
* true
*/
if (((CheckBox) view.findViewById(R.id.cb_edit_item)).isChecked()) { if (((CheckBox) view.findViewById(R.id.cb_edit_item)).isChecked()) {
//该选项框已打钩
sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n"); sb.append(TAG_CHECKED).append(" ").append(edit.getText()).append("\n");
hasChecked = true; hasChecked = true;
//扩展字符串为已打钩并把标记置true
} else { } else {
//扩展字符串添加未打钩 //扩展字符串添加未打钩
sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n"); sb.append(TAG_UNCHECKED).append(" ").append(edit.getText()).append("\n");
@ -985,8 +1025,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} }
} }
mWorkingNote.setWorkingText(sb.toString());//利用编辑好的字符串设置运行便签的内容 mWorkingNote.setWorkingText(sb.toString());//利用编辑好的字符串设置运行便签的内容
//利用编辑好的字符串设置运行便签的内容
} else {// 若不是该模式直接用编辑器中的内容设置运行中标签的内容 } else {// 若不是该模式直接用编辑器中的内容设置运行中标签的内容
mWorkingNote.setWorkingText(mNoteEditor.getText().toString()); mWorkingNote.setWorkingText(mNoteEditor.getText().toString());
//若是获取到文本就改变其检查标记
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mEditTextList.setVisibility(View.GONE);
mNoteEditor.setVisibility(View.VISIBLE);
//修改文本编辑器的内容和可见性
} }
return hasChecked; return hasChecked;
} }
@ -1000,6 +1046,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private boolean saveNote() { private boolean saveNote() {
getWorkingText(); getWorkingText();
boolean saved = mWorkingNote.saveNote(); boolean saved = mWorkingNote.saveNote();
//如果便签内容为空,则删除
if (TextUtils.isEmpty(mWorkingNote.getContent())) {
deleteCurrentNote();//删除当前便签
saved = false; // 标记为未保存
}
//运行 getWorkingText()之后保存 //运行 getWorkingText()之后保存
if (saved) { if (saved) {
/** /**
@ -1055,6 +1106,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
showToast(R.string.error_note_empty_for_send_to_desktop); showToast(R.string.error_note_empty_for_send_to_desktop);
} }
} }
/** /**
* @method makeShortcutIconTitle * @method makeShortcutIconTitle
* @description * @description
@ -1069,9 +1121,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0, return content.length() > SHORTCUT_ICON_TITLE_MAX_LEN ? content.substring(0,
SHORTCUT_ICON_TITLE_MAX_LEN) : content; SHORTCUT_ICON_TITLE_MAX_LEN) : content;
} }
private void showToast(int resId) { private void showToast(int resId) {
showToast(resId, Toast.LENGTH_SHORT); showToast(resId, Toast.LENGTH_SHORT);
} }
private void showToast(int resId, int duration) { private void showToast(int resId, int duration) {
Toast.makeText(this, resId, duration).show(); Toast.makeText(this, resId, duration).show();
} }
@ -1292,4 +1346,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
e.printStackTrace(); e.printStackTrace();
} }
} }
/**
* @method textToSpeach
* @description:
* @date: 2024/1/16 20:21
* @author: WuShuxian
*/
private void textToSpeach(){
mTTS.speak(mNoteEditor.getText().toString(),TextToSpeech.QUEUE_FLUSH,null);
}
} }

@ -405,7 +405,7 @@
android:src="@drawable/selected" /> android:src="@drawable/selected" />
</FrameLayout> </FrameLayout>
</LinearLayout> </LinearLayout>
<!--插入图片的按钮-->
<ImageButton <ImageButton
android:id="@+id/add_img_btn" android:id="@+id/add_img_btn"
android:layout_width="51dp" android:layout_width="51dp"

@ -39,7 +39,6 @@
<string name="file_name_txt_format">notes_%s.txt</string> <string name="file_name_txt_format">notes_%s.txt</string>
<!-- notes list string --> <!-- notes list string -->
<string name="format_folder_files_count">(%d)</string> <string name="format_folder_files_count">(%d)</string>
<string name="add_img_btn">Add picture</string>
<string name="menu_create_folder">New Folder</string> <string name="menu_create_folder">New Folder</string>
<string name="menu_export_text">Export text</string> <string name="menu_export_text">Export text</string>
<string name="menu_sync">Sync</string> <string name="menu_sync">Sync</string>

Loading…
Cancel
Save