Lwq 2 years ago
parent 63a86ef72c
commit 6072c639e7

Binary file not shown.

@ -0,0 +1,77 @@
/*
* 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;
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import java.util.HashMap;
public class Contact {//创建类:联系人
private static HashMap<String, String> sContactCache;//存储联系人数据
private static final String TAG = "Contact";//自定义标签TAG指向Contact
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER//自定义字符串caller id selection
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
+ " AND " + Data.RAW_CONTACT_ID + " IN "//定义的callerIDSELEDTION所包含的各项数据
+ "(SELECT raw_contact_id "
+ " FROM phone_lookup"
+ " WHERE min_match = '+')";
public static String getContact(Context context, String phoneNumber) {//获取联系人
if(sContactCache == null) {
sContactCache = new HashMap<String, String>();
}
//查找HashMap中是否已有phoneNumber信息
if(sContactCache.containsKey(phoneNumber)) {
return sContactCache.get(phoneNumber);
}
String selection = CALLER_ID_SELECTION.replace("+",
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));//查找数据库中phoneNumber的信息
Cursor cursor = context.getContentResolver().query(
Data.CONTENT_URI,
new String [] { Phone.DISPLAY_NAME },
selection,
new String[] { phoneNumber },
null);
//判定查询结果
//moveToFirst()返回第一条
if (cursor != null && cursor.moveToFirst()) {
try {//找到相关信息
String name = cursor.getString(0);
sContactCache.put(phoneNumber, name);
return name;
//异常
} catch (IndexOutOfBoundsException e) {//如果超出了范围则在相关日志中进行写Cursor get string error信息
Log.e(TAG, " Cursor get string error " + e.toString());
return null;
} finally {
cursor.close();
}
//这里的try和finally和catch都是用来捕捉异常三个在一起使用时可以保持系统完整性对异常进行处理。
} else {
Log.d(TAG, "No contact matched with number:" + phoneNumber);
return null;
}
}
}

@ -0,0 +1,284 @@
/*
* 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;
import android.net.Uri;
public class Notes {//Notes类定义一些基本标识符。该类不对标识符进行任何操作仅仅只是定义供其他类调用
public static final String AUTHORITY = "micode_notes";//定义一个权限名
public static final String TAG = "Notes";//设置标签表示APP的名称是Notes
public static final int TYPE_NOTE = 0;//以下三个常量对NoteColumns.TYPE的值进行设置时会用到
public static final int TYPE_FOLDER = 1;
public static final int TYPE_SYSTEM = 2;
/**
* Following IDs are system folders' identifiers
* {@link Notes#ID_ROOT_FOLDER } is default folder
* {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder
* {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records
*/
//系统文件标识根目录0临时文件夹-1通话记录-2垃圾文件夹-3
public static final int ID_ROOT_FOLDER = 0;
public static final int ID_TEMPARAY_FOLDER = -1;
public static final int ID_CALL_RECORD_FOLDER = -2;
public static final int ID_TRASH_FOLER = -3;
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date";//定义了通知日期的ID
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id";//定义背景颜色的ID
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id";//定义桌面插件的名称
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type";//定义桌面插件的类型
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id";//定义Note标识text_note的存放地址
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date";//定义Call_note标识call_note的存放地址
public static final int TYPE_WIDGET_INVALIDE = -1;//小部件标识:无效小部件-12*2大小小部件04*4大小小部件1
public static final int TYPE_WIDGET_2X = 0;
public static final int TYPE_WIDGET_4X = 1;
public static class DataConstants {//DataContants类存放textnotes和callnotes地址
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE;//定义变量NOTE用来识别text_note的存放地址
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE;//定义变量CALL_NOTE用来标志call_note的存放地址
}
/**
* Uri to query all notes and folders
*/
//定义查询便签和文件夹的指针。
public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note");
/**
* Uri to query data
*/
//定义查找数据的指针。
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
public interface NoteColumns {//定义NoteColumns的常量,用于后面创建数据库的表头
/**
* The unique ID for a row
* <P> Type: INTEGER (long) </P>
*/
public static final String ID = "_id";//定义每一行id
/**
* The parent's id for note or folder
* <P> Type: INTEGER (long) </P>
*/
public static final String PARENT_ID = "parent_id";//父节点id的字符串
/**
* Created data for note or folder
* <P> Type: INTEGER (long) </P>
*/
public static final String CREATED_DATE = "created_date";//用来保存一些创建信息,比如时间
/**
* Latest modified date
* <P> Type: INTEGER (long) </P>
*/
public static final String MODIFIED_DATE = "modified_date";//最近更新的时间等数据
/**
* Alert date
* <P> Type: INTEGER (long) </P>
*/
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";//文件夹的名称或便签的内容等数据
/**
* Note's widget id
* <P> Type: INTEGER (long) </P>
*/
public static final String WIDGET_ID = "widget_id";//note的布局ID
/**
* Note's widget type
* <P> Type: INTEGER (long) </P>
*/
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";//便签背景颜色的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";//设置附件是否存在
/**
* Folder's count of notes
* <P> Type: INTEGER (long) </P>
*/
public static final String NOTES_COUNT = "notes_count";//通过对相应标签字符串的定义,方便以后准确的引用
/**
* The file type: folder or note
* <P> Type: INTEGER </P>
*/
public static final String TYPE = "type";//文件夹类型还是note类型
/**
* The last sync id
* <P> Type: INTEGER (long) </P>
*/
public static final String SYNC_ID = "sync_id";//最后一次同步的ID
/**
* Sign to indicate local modified or not
* <P> Type: INTEGER </P>
*/
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";//移动到临时文件夹之前的父节点的ID
/**
* The gtask id
* <P> Type : TEXT </P>
*/
public static final String GTASK_ID = "gtask_id";//后台任务的ID
/**
* The version code
* <P> Type : INTEGER (long) </P>
*/
public static final String VERSION = "version";//定义版本号
}//定义便签属性的常量
public interface DataColumns {// 定义DataColumns的常量,用于后面创建数据库的表头
/**
* The unique ID for a row
* <P> Type: INTEGER (long) </P>
*/
public static final String ID = "_id";//定义DataColumns的部分常量
/**
* The MIME type of the item represented by this row.
* <P> Type: Text </P>
*/
public static final String MIME_TYPE = "mime_type";//MIME类型能包含视频、图像、文本、音频、应用程序等数据
/**
* The reference id to note that this data belongs to
* <P> Type: INTEGER (long) </P>
*/
public static final String NOTE_ID = "note_id";//设置标签的id
/**
* Created data for note or folder
* <P> Type: INTEGER (long) </P>
*/
public static final String CREATED_DATE = "created_date";//创建时间
/**
* Latest modified date
* <P> Type: INTEGER (long) </P>
*/
public static final String MODIFIED_DATE = "modified_date";//最新的修改时间
/**
* Data's content
* <P> Type: TEXT </P>
*/
public static final String CONTENT = "content";//数据包含的内容
/**
* Generic data column, the meaning is {@link #MIME_TYPE} specific, used for
* integer data type
* <P> Type: INTEGER </P>
*/
public static final String DATA1 = "data1";//文本内容的数据结构
/**
* Generic data column, the meaning is {@link #MIME_TYPE} specific, used for
* integer data type
* <P> Type: INTEGER </P>
*/
public static final String DATA2 = "data2";//定义文本内容的类型
/**
* Generic data column, the meaning is {@link #MIME_TYPE} specific, used for
* TEXT data type
* <P> Type: TEXT </P>
*/
public static final String DATA3 = "data3";//用于文本类型
/**
* Generic data column, the meaning is {@link #MIME_TYPE} specific, used for
* TEXT data type
* <P> Type: TEXT </P>
*/
public static final String DATA4 = "data4";//定义常量
/**
* Generic data column, the meaning is {@link #MIME_TYPE} specific, used for
* TEXT data type
* <P> Type: TEXT </P>
*/
public static final String DATA5 = "data5";//文本内容的数据结构
}//主要定义存储便签内容数据
public static final class TextNote implements DataColumns {//创建文本数据TextNote继承上面的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;//继承了DataColumns中的DATA1
public static final int MODE_CHECK_LIST = 1;//note中内容的类型
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/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 class CallNote implements DataColumns {//通话数据CallNote继承了接口类而后进行了格式适配
/**
* Call date for this record
* <P> Type: INTEGER (long) </P>
*/
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 CONTENT_TYPE = "vnd.android.cursor.dir/call_note";//修改CONTENT_TYPE属性
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");//内容标识符
}//电话内容的数据结构
}

@ -0,0 +1,362 @@
/*
* 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;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "note.db";
private static final int DB_VERSION = 4;
public interface TABLE {//接口分成note和data
public static final String NOTE = "note";
public static final String DATA = "data";
}
private static final String TAG = "NotesDatabaseHelper";
private static NotesDatabaseHelper mInstance;
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";//数据库中需要存储的项目的名称,就相当于创建一个表格的表头的内容
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";//文件夹删除note触发
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
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 =
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";//在文件夹中移入一个Note之后需要更改的数据的表格
/**
* Decrease folder's note count when move note from folder
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" 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 =
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";//在文件夹中插入一个Note之后需要更改的数据的表格
/**
* Decrease folder's note count when delete note from the folder
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";//在文件夹中删除一个Note之后需要更改的数据的表格
/**
* Update note's content when insert data with type {@link DataConstants#NOTE}
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";//在文件夹中对一个Note导入新的数据之后需要更改的数据的表格
/**
* Update note's content when data with {@link DataConstants#NOTE} type has changed
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";//Note数据被修改后需要更改的数据的表格
/**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";//Note数据被删除后需要更改的数据的表格
/**
* Delete datas belong to note which has been deleted
*/
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";//删除已删除的便签的数据后需要更改的数据的表格
/**
* Delete notes belong to folder which has been deleted
*/
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";//删除已删除的文件夹的便签后需要更改的数据的表格
/**
* Move notes belong to folder which has been moved to trash folder
*/
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";//还原垃圾桶中便签后需要更改的数据的表格
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}//构造函数,传入数据库的名称和版本
public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL);
reCreateNoteTableTriggers(db);
createSystemFolder(db);
Log.d(TAG, "note table has been created");
}//创建表格
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash");
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER);
db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER);
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
}//重新创建上述定义的表格
private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues();
/**
* call record foler for call notes
*/
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
/**
* root folder which is default folder
*/
values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
/**
* temporary folder which is used for moving note
*/
values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
/**
* create trash folder
*/
values.clear();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}//创建系统文件夹
public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL);
reCreateDataTableTriggers(db);
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
Log.d(TAG, "data table has been created");
}//创建表格
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_update");
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete");
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_DELETE_TRIGGER);
}//创建表格
static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context);
}
return mInstance;
}//解决同一时刻只能有一个线程执行
@Override
public void onCreate(SQLiteDatabase db) {
createNoteTable(db);
createDataTable(db);
}//实现上面创建的两个表格
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean reCreateTriggers = false;
boolean skipV2 = false;
if (oldVersion == 1) {
upgradeToV2(db);
skipV2 = true; // this upgrade including the upgrade from v2 to v3
oldVersion++;
}
if (oldVersion == 2 && !skipV2) {
upgradeToV3(db);
reCreateTriggers = true;
oldVersion++;
}
if (oldVersion == 3) {
upgradeToV4(db);
oldVersion++;
}
if (reCreateTriggers) {
reCreateNoteTableTriggers(db);
reCreateDataTableTriggers(db);
}
if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails");
}
}//数据库版本的更新
private void upgradeToV2(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
createNoteTable(db);
createDataTable(db);
}//更新到V2版本
private void upgradeToV3(SQLiteDatabase db) {
// 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_delete");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
// add a column for gtask id
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''");
// add a trash system folder
ContentValues values = new ContentValues();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}//更新到V3版本
private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
}//更新到V4版本

@ -0,0 +1,306 @@
/*
* 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;
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import net.micode.notes.R;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
//访问、删除、插入、更新、扩展Notes的数据库
public class NotesProvider extends ContentProvider {
private static final UriMatcher mMatcher;
private NotesDatabaseHelper mHelper;
private static final String TAG = "NotesProvider";
private static final int URI_NOTE = 1;
private static final int URI_NOTE_ITEM = 2;
private static final int URI_DATA = 3;
private static final int URI_DATA_ITEM = 4;
private static final int URI_SEARCH = 5;
private static final int URI_SEARCH_SUGGEST = 6;//将以下这些变量放在static模块中只初始化一次提高运行速度以及减少空间浪费。将各个Uri与其代号关联在一起
static {
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH);
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST);
mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST);
}//注册完需要匹配的Uri后就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配
/**
* 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.
*/
private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + ","
+ 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_2 + ","
+ R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
+ "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
+ "'" + 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
+ " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
+ " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
+ " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
@Override
public boolean onCreate() {
mHelper = NotesDatabaseHelper.getInstance(getContext());
return true;
}//对mHelper进行实例化
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,//查询uri在数据库中对应的位置
String sortOrder) {
Cursor c = null;
SQLiteDatabase db = mHelper.getReadableDatabase();//获取可读数据库
String id = null;
switch (mMatcher.match(uri)) {//匹配查找uri
case URI_NOTE:
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder);
break;
case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);
c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
break;
case URI_DATA:
c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null,
sortOrder);
break;
case URI_DATA_ITEM:
id = uri.getPathSegments().get(1);
c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs, null, null, sortOrder);
break;
case URI_SEARCH:
case URI_SEARCH_SUGGEST://对于不同的匹配值,在数据库中查找相应的条目
if (sortOrder != null || projection != null) {
throw new IllegalArgumentException(
"do not specify sortOrder, selection, selectionArgs, or projection" + "with this query");
}//不合法的参数异常
String searchString = null;
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
if (uri.getPathSegments().size() > 1) {//getPathSegments()方法得到一个String的List
searchString = uri.getPathSegments().get(1);//在uri.getPathSegments().get(1)为第2个元素
}
} else {
searchString = uri.getQueryParameter("pattern");
}
if (TextUtils.isEmpty(searchString)) {
return null;
}
try {
searchString = String.format("%%%s%%", searchString);
c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY,
new String[] { searchString });
} catch (IllegalStateException ex) {
Log.e(TAG, "got exception: " + ex.toString());
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);//抛出异常
}
if (c != null) {
c.setNotificationUri(getContext().getContentResolver(), uri);
}
return c;
}
@Override
public Uri insert(Uri uri, ContentValues values) {//插入一个uri
SQLiteDatabase db = mHelper.getWritableDatabase();//获得可写的数据库
long dataId = 0, noteId = 0, insertedId = 0;
switch (mMatcher.match(uri)) {
case URI_NOTE://新增一个条目
insertedId = noteId = db.insert(TABLE.NOTE, null, values);
break;
case URI_DATA://如果存在查找NOTE_ID
if (values.containsKey(DataColumns.NOTE_ID)) {
noteId = values.getAsLong(DataColumns.NOTE_ID);
} else {
Log.d(TAG, "Wrong data format without note id:" + values.toString());
}
insertedId = dataId = db.insert(TABLE.DATA, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
// Notify the note uri
//notifyChange获得一个ContextResolver对象并且更新里面的内容
if (noteId > 0) {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
}
// Notify the data uri
if (dataId > 0) {
getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
}
return ContentUris.withAppendedId(uri, insertedId);//返回插入的uri的路径
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {//删除一个uri
int count = 0;
String id = null;
SQLiteDatabase db = mHelper.getWritableDatabase();//获得可写的数据库
boolean deleteData = false;
switch (mMatcher.match(uri)) {
case URI_NOTE:
selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 ";
count = db.delete(TABLE.NOTE, selection, selectionArgs);
break;
case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);
/**
* ID that smaller than 0 is system folder which is not allowed to
* trash
*/
long noteId = Long.valueOf(id);
if (noteId <= 0) {
break;
}
count = db.delete(TABLE.NOTE,
NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
break;
case URI_DATA:
count = db.delete(TABLE.DATA, selection, selectionArgs);
deleteData = true;
break;
case URI_DATA_ITEM:
id = uri.getPathSegments().get(1);
count = db.delete(TABLE.DATA,
DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs);
deleteData = true;
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (count > 0) {
if (deleteData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
}
getContext().getContentResolver().notifyChange(uri, null);
}
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {//更新一个uri
int count = 0;
String id = null;
SQLiteDatabase db = mHelper.getWritableDatabase();
boolean updateData = false;
switch (mMatcher.match(uri)) {
case URI_NOTE:
increaseNoteVersion(-1, selection, selectionArgs);
count = db.update(TABLE.NOTE, values, selection, selectionArgs);
break;
case URI_NOTE_ITEM:
id = uri.getPathSegments().get(1);
increaseNoteVersion(Long.valueOf(id), selection, selectionArgs);
count = db.update(TABLE.NOTE, values, NoteColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs);
break;
case URI_DATA:
count = db.update(TABLE.DATA, values, selection, selectionArgs);
updateData = true;
break;
case URI_DATA_ITEM:
id = uri.getPathSegments().get(1);
count = db.update(TABLE.DATA, values, DataColumns.ID + "=" + id
+ parseSelection(selection), selectionArgs);
updateData = true;
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (count > 0) {
if (updateData) {
getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null);
}
getContext().getContentResolver().notifyChange(uri, null);
}
return count;
}
private String parseSelection(String selection) {//将字符串解析成规定格式
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
}
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {//增加一个noteVersion
StringBuilder sql = new StringBuilder(120);
sql.append("UPDATE ");
sql.append(TABLE.NOTE);
sql.append(" SET ");
sql.append(NoteColumns.VERSION);
sql.append("=" + NoteColumns.VERSION + "+1 ");
if (id > 0 || !TextUtils.isEmpty(selection)) {
sql.append(" WHERE ");
}
if (id > 0) {
sql.append(NoteColumns.ID + "=" + String.valueOf(id));
}
if (!TextUtils.isEmpty(selection)) {
String selectString = id > 0 ? parseSelection(selection) : selection;
for (String args : selectionArgs) {
selectString = selectString.replaceFirst("\\?", args);
}
sql.append(selectString);
}
mHelper.getWritableDatabase().execSQL(sql.toString());//execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
}

@ -0,0 +1,802 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.gtask.remote;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.data.MetaData;
import net.micode.notes.gtask.data.Node;
import net.micode.notes.gtask.data.SqlNote;
import net.micode.notes.gtask.data.Task;
import net.micode.notes.gtask.data.TaskList;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.gtask.exception.NetworkFailureException;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
public class GTaskManager {//GTask管理类封装对GTask进行管理的方法
private static final String TAG = GTaskManager.class.getSimpleName();
public static final int STATE_SUCCESS = 0;
public static final int STATE_NETWORK_ERROR = 1;
public static final int STATE_INTERNAL_ERROR = 2;
public static final int STATE_SYNC_IN_PROGRESS = 3;
public static final int STATE_SYNC_CANCELLED = 4;
private static GTaskManager mInstance = null;
private Activity mActivity;
private Context mContext;
private ContentResolver mContentResolver;
private boolean mSyncing;
private boolean mCancelled;
private HashMap<String, TaskList> mGTaskListHashMap;
private HashMap<String, Node> mGTaskHashMap;
private HashMap<String, MetaData> mMetaHashMap;
private TaskList mMetaList;
private HashSet<Long> mLocalDeleteIdMap;
private HashMap<String, Long> mGidToNid;
private HashMap<Long, String> mNidToGid;
private GTaskManager() {//对象初始化函数
mSyncing = false;//正在同步,flase代表未执行
mCancelled = false;//全局标识flase代表可以执行
mGTaskListHashMap = new HashMap<String, TaskList>();//<>代表Java的泛型,就是创建一个用类型作为参数的类
mGTaskHashMap = new HashMap<String, Node>();//创建一个节点表
mMetaHashMap = new HashMap<String, MetaData>();//创建一个删除本地ID的map
mMetaList = null;//创建一个删除本地ID的map
mLocalDeleteIdMap = new HashSet<Long>();
mGidToNid = new HashMap<String, Long>();//建立一个google id到节点id的映射
mNidToGid = new HashMap<Long, String>();
}
public static synchronized GTaskManager getInstance() {//可能运行在多线程环境下,使用语言级同步--synchronized
if (mInstance == null) {
mInstance = new GTaskManager();
}
return mInstance;
}
public synchronized void setActivityContext(Activity activity) {//对类的当前实例进行加锁防止其他线程同时访问该类的该实例的所有synchronized块
// used for getting authtoken
mActivity = activity;
}
public int sync(Context context, GTaskASyncTask asyncTask) {//核心函数
if (mSyncing) {
Log.d(TAG, "Sync is in progress");//创建日志文件调试信息debug
return STATE_SYNC_IN_PROGRESS;
}
mContext = context;
mContentResolver = mContext.getContentResolver();
mSyncing = true;
mCancelled = false;
mGTaskListHashMap.clear();
mGTaskHashMap.clear();
mMetaHashMap.clear();
mLocalDeleteIdMap.clear();
mGidToNid.clear();
mNidToGid.clear();
try {
GTaskClient client = GTaskClient.getInstance();//getInstance即为创建一个实例,client--客户机
client.resetUpdateArray();//JSONArray类型reset即置为NULL
// login google task
if (!mCancelled) {
if (!client.login(mActivity)) {
throw new NetworkFailureException("login google task failed");
}
}
// get the task list from google
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list));
initGTaskList();//获取Google上的JSONtasklist转为本地TaskList
// do content sync work
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing));
syncContent();
} catch (NetworkFailureException e) {//分为两种异常,此类异常为网络异常
Log.e(TAG, e.toString());//创建日志文件调试信息error
return STATE_NETWORK_ERROR;
} catch (ActionFailureException e) {//此类异常为操作异常
Log.e(TAG, e.toString());
return STATE_INTERNAL_ERROR;
} catch (Exception e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return STATE_INTERNAL_ERROR;
} finally {
mGTaskListHashMap.clear();
mGTaskHashMap.clear();
mMetaHashMap.clear();
mLocalDeleteIdMap.clear();
mGidToNid.clear();
mNidToGid.clear();
mSyncing = false;
}
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
}//若在同步时操作未取消,则返回同步成功
private void initGTaskList() throws NetworkFailureException {
if (mCancelled)
return;
GTaskClient client = GTaskClient.getInstance();//getInstance即为创建一个实例client应指远端客户机
try {
//Json对象是Name Value对(即子元素)的无序集合相当于一个Map对象。JsonObject类是bantouyan-json库对Json对象的抽象提供操纵Json对象的各种方法。
//其格式为{"key1":value1,"key2",value2....};key 必须是字符串
//因为ajax请求不刷新页面但配合js可以实现局部刷新因此json常常被用来作为异步请求的返回对象使用
JSONArray jsTaskLists = client.getTaskLists();//原注释为get task list------lists
// init meta list first
mMetaList = null;//TaskList类型
for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i);//JSONObject与JSONArray一个为对象一个为数组。此处取出单个JASONObject
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);
if (name
.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {
mMetaList = new TaskList();//MetaList意为元表,Tasklist类型此处为初始化
mMetaList.setContentByRemoteJSON(object);//将JSON中部分数据复制到自己定义的对象中相对应的数据name->mname
// load meta data
JSONArray jsMetas = client.getTaskList(gid);
for (int j = 0; j < jsMetas.length(); j++) {
object = (JSONObject) jsMetas.getJSONObject(j);
MetaData metaData = new MetaData();//继承自Node
metaData.setContentByRemoteJSON(object);
if (metaData.isWorthSaving()) {//需要保存时,将子任务加入到主任务中
mMetaList.addChildTask(metaData);
if (metaData.getGid() != null) {//操作getGid取得组识别码函数
mMetaHashMap.put(metaData.getRelatedGid(), metaData);//把元数据放到哈希表中
}
}
}
}
}
// create meta list if not existed
if (mMetaList == null) {//代码块:若元数据列表不存在则创建一个
mMetaList = new TaskList();
mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX
+ GTaskStringUtils.FOLDER_META);
GTaskClient.getInstance().createTaskList(mMetaList);
}
// init task list
for (int i = 0; i < jsTaskLists.length(); i++) {//以下循环用于初始化任务列表
JSONObject object = jsTaskLists.getJSONObject(i);
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);
if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)
&& !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX
+ GTaskStringUtils.FOLDER_META)) {
TaskList tasklist = new TaskList();//继承自Node
tasklist.setContentByRemoteJSON(object);
mGTaskListHashMap.put(gid, tasklist);//对任务列表的内容进行设置
mGTaskHashMap.put(gid, tasklist);
// load tasks
JSONArray jsTasks = client.getTaskList(gid);//获取任务id号
for (int j = 0; j < jsTasks.length(); j++) {//任务id号
object = (JSONObject) jsTasks.getJSONObject(j);
gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
Task task = new Task();
task.setContentByRemoteJSON(object);
if (task.isWorthSaving()) {//判断该任务有无价值保存
task.setMetaInfo(mMetaHashMap.get(gid));
tasklist.addChildTask(task);
mGTaskHashMap.put(gid, task);
}
}
}
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("initGTaskList: handing JSONObject failed");//抛出异常,提交 JSONObject 失败
}
}
private void syncContent() throws NetworkFailureException {//本地内容同步操作
int syncType;
Cursor c = null;//数据库指针
String gid;
Node node;//Node包含Sync_Action的不同类型
mLocalDeleteIdMap.clear();//HashSet<Long>类型
if (mCancelled) {//对于要删除本地note的情况
return;
}
// for local deleted note
try {//对于删除本地便签的操作的同步
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,//定位要删除的节点位置
"(type<>? AND parent_id=?)", new String[] {
String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)
}, null);
if (c != null) {//若获取到的待删除便签不为空,则进行同步操作
while (c.moveToNext()) {//通过while用指针遍历所有结点
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);
if (node != null) {//节点非空则从哈希表里删除,并进行同步操作
mGTaskHashMap.remove(gid);
doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c);
}//在远程删除对应节点
mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN));//在本地删除记录中添加这一项记录
}
} else {//若c结点为空即寻找错误的时候报错
Log.w(TAG, "failed to query trash folder");
}
} finally {//最后把c关闭并重置
if (c != null) {//结束操作之后,将指针指向内容关闭并将指针置空
c.close();
c = null;
}//关闭cursor
}
// sync folder first
syncFolder();//对文件夹进行同步
// for note existing in database
try {//对于数据库中已经存在的便签,采取以下操作
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,//使c指针指向待操作的便签位置
"(type=? AND parent_id<>?)", new String[] {//c指针指向待操作的位置
String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.ID_TRASH_FOLER)
}, NoteColumns.TYPE + " DESC");
if (c != null) {//query语句的用法
while (c.moveToNext()) {//指针向后移动
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);
if (node != null) {//节点不为空则删除gid重新建立节点到gid的联系
mGTaskHashMap.remove(gid);
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));//建立google id到节点id的映射
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);//通过hashmap建立联系
syncType = node.getSyncAction(c);//更新此时的同步类型
} else {//若为空先判断sqlnote的trim是否为0是则确定同步方式为add_remote否则为del_local
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {//若本地增加了内容,则远程也要增加内容
// local add
syncType = Node.SYNC_ACTION_ADD_REMOTE;//远程增加内容
} else {//若本地删除了内容则远程也要删除内容应的gid
// remote delete
syncType = Node.SYNC_ACTION_DEL_LOCAL;//本地删除
}
}
doContentSync(syncType, node, c);//进行同步操作
}
} else {
Log.w(TAG, "failed to query existing note in database");//查询失败时在日志中写回错误信息
}
} finally {//在最后关闭c并重置
if (c != null) {//结束操作之后,将指针指向内容关闭并将指针置空
c.close();//关闭 cursor 所指文件
c = null;//cursor 置空
}
}
// go through remaining items
Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator();//扫描剩下的项目,逐个进行同步
while (iter.hasNext()) {//迭代
Map.Entry<String, Node> entry = iter.next();
node = entry.getValue();
doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null);
}//在本地增加些节点
// mCancelled can be set by another thread, so we neet to check one by
// one
// clear local delete table
if (!mCancelled) {//终止标识有可能被其他进程改变,因此需要一个个进行检查
if (!DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) {
throw new ActionFailureException("failed to batch-delete local deleted notes");//终止标识有可能被其他线程改变
}
}
// refresh local sync id
if (!mCancelled) {//更新同步表
GTaskClient.getInstance().commitUpdate();
refreshLocalSyncId();//更新同步的id
}
}
private void syncFolder() throws NetworkFailureException {//放在第一种情况之后是因为第一种情况不需要初始化文件夹
Cursor c = null;//同步文件夹
String gid;
Node node;
int syncType;
if (mCancelled) {//判断是否取消该操作
return;
}
// for root folder
try {//对根文件夹进行更新
c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI,
Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null);//使指针指向根文件夹的位置
if (c != null) {
c.moveToNext();
gid = c.getString(SqlNote.GTASK_ID_COLUMN);//获取指针指向内容对应的gid
node = mGTaskHashMap.get(gid);//获取该gid所代表的节点
if (node != null) {
mGTaskHashMap.remove(gid);
mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER);//将该节点的gid到nid的映射加入映射表
mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid);
// for system folder, only update remote name if necessary
if (!node.getName().equals(//添加MIUI文件前缀
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT))
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);
} else {
doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);//若非系统文件夹则在远程进行增加节点操作
}
} else {
Log.w(TAG, "failed to query root folder");
}
} finally {//结束操作之后,最后将指针关闭,并将指针置空。方法与之前相同
if (c != null) {//结束操作之后,将指针指向内容关闭并将指针置空
c.close();//关闭 cursor 所指文件
c = null;//cursor 置空
}
}
// for call-note folder
try {//对存放电话号码便签的文件夹的同步操作
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)",//使指针指向文件夹的位置
new String[] {
String.valueOf(Notes.ID_CALL_RECORD_FOLDER)//添加MIUI文件前缀
}, null);
if (c != null) {
if (c.moveToNext()) {
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);//获取指针指向内容对应的gid
if (node != null) {
mGTaskHashMap.remove(gid);
mGidToNid.put(gid, (long) Notes.ID_CALL_RECORD_FOLDER);//将该节点的gid到nid的映射加入映射表
mNidToGid.put((long) Notes.ID_CALL_RECORD_FOLDER, gid);
// for system folder, only update remote name if
// necessary
if (!node.getName().equals(//若当前访问的文件夹是系统文件夹则只需要更新
GTaskStringUtils.MIUI_FOLDER_PREFFIX//若当前访问的文件夹是系统文件夹则只需更新
+ GTaskStringUtils.FOLDER_CALL_NOTE))
doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c);
} else {
doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c);//若当前访问的文件夹是系统文件夹则只需更新
}
}
} else {
Log.w(TAG, "failed to query call note folder");//警告,询问通讯便签文件夹失败
}
} finally {
if (c != null) {//结束操作之后,将指针指向内容关闭并将指针置空
c.close();//关闭 cursor 所指文件
c = null;//cursor 置空
}
}
// for local existing folders
try {//对于本地已存在的文件的操作
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,//使指针指向第一个文件夹的位置
"(type=? AND parent_id<>?)", new String[] {//使指针指向第一个文件夹的位置
String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)
}, NoteColumns.TYPE + " DESC");
if (c != null) {
while (c.moveToNext()) {//使指针指向第一个文件夹的位置
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);
if (node != null) {
mGTaskHashMap.remove(gid);
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);//获取指针指向内容对应的gid
syncType = node.getSyncAction(c);
} else {//更新同步类型
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
// local add
syncType = Node.SYNC_ACTION_ADD_REMOTE;
} else {//若远程删除了内容,则本地也要删除内容
// remote delete
syncType = Node.SYNC_ACTION_DEL_LOCAL;//本地删除
}
}
doContentSync(syncType, node, c);//进行同步操作
}
} else {
Log.w(TAG, "failed to query existing folder");//警告,询问已创建的文件夹失败
}
} finally {
if (c != null) {//结束操作之后,将指针指向内容关闭并将指针置空
c.close();//关闭 cursor 所指文件
c = null;//cursor 置空
}
}
// for remote add folders
Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();//远程添加文件需要执行的操作
while (iter.hasNext()) {//使用迭代器对远程增添的内容进行遍历
Map.Entry<String, TaskList> entry = iter.next();
gid = entry.getKey();//获取对应的gid
node = entry.getValue();//获取gid对应的节点
if (mGTaskHashMap.containsKey(gid)) {//获取gid对应的节点
mGTaskHashMap.remove(gid);
doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null);//进行本地增添操作
}
}
if (!mCancelled)
GTaskClient.getInstance().commitUpdate();//如果没有取消在GTsk的客户端进行实例的提交更新
}
private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException {//内容同步,同步同步类型、节点以及数据库指针
if (mCancelled) {//如果已经取消同步,直接返回
return;
}
MetaData meta;
switch (syncType) {//根据同步类型选择操作
case Node.SYNC_ACTION_ADD_LOCAL://远程添加
addLocalNode(node);//本地添加
break;
case Node.SYNC_ACTION_ADD_REMOTE://代码块:远程增添
addRemoteNode(node, c);//本地删除
break;
case Node.SYNC_ACTION_DEL_LOCAL://远程删除
meta = mMetaHashMap.get(c.getString(SqlNote.GTASK_ID_COLUMN));
if (meta != null) {
GTaskClient.getInstance().deleteNode(meta);
}
mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN));
break;
case Node.SYNC_ACTION_DEL_REMOTE://更新本地数据
meta = mMetaHashMap.get(node.getGid());//更新本地数据
if (meta != null) {
GTaskClient.getInstance().deleteNode(meta);
}
GTaskClient.getInstance().deleteNode(node);
break;
case Node.SYNC_ACTION_UPDATE_LOCAL:
updateLocalNode(node, c);
break;
case Node.SYNC_ACTION_UPDATE_REMOTE://更新远程数据
updateRemoteNode(node, c);
break;
case Node.SYNC_ACTION_UPDATE_CONFLICT://更新时出现冲突
// merging both modifications maybe a good idea
// right now just use local update simply
updateRemoteNode(node, c);
break;
case Node.SYNC_ACTION_NONE://空操作
break;
case Node.SYNC_ACTION_ERROR://操作错误
default://同步类型不在规定的类型范围内
throw new ActionFailureException("unkown sync action type");//抛出异常,未知的同步行为类型
}
}
private void addLocalNode(Node node) throws NetworkFailureException {//增加本地节点的操作,传入参量为待增添的节点
if (mCancelled) {//添加本地结点参数node即为要添加的本地结点
return;
}
SqlNote sqlNote;
if (node instanceof TaskList) {//若待增添节点为任务列表中的节点,进一步操作
if (node.getName().equals(//在根目录中增加节点
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) {//指定页面存放的文件夹加上文件夹默认值判断node节点的名字是否是MIUI系统文件夹的默认文件夹
sqlNote = new SqlNote(mContext, Notes.ID_ROOT_FOLDER);
} else if (node.getName().equals(//在存放电话号码便签的文件夹中增加节点
GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) {
sqlNote = new SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER);
} else {//若没有存放的文件夹,则将其放在根文件夹中
sqlNote = new SqlNote(mContext);
sqlNote.setContent(node.getLocalJSONFromContent());//从本地任务列表中获取内容
sqlNote.setParentId(Notes.ID_ROOT_FOLDER);
}
} else {//若待增添节点不是任务列表中的节点,进一步操作
sqlNote = new SqlNote(mContext);
JSONObject js = node.getLocalJSONFromContent();//从待增添节点中获取jsonobject对象
try {//异常判断
if (js.has(GTaskStringUtils.META_HEAD_NOTE)) {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);//获取对应便签的jsonobject对象
if (note.has(NoteColumns.ID)) {//判断便签中是否有条目
long id = note.getLong(NoteColumns.ID);
if (DataUtils.existInNoteDatabase(mContentResolver, id)) {//若便签条目的id已无效在便签中将其删除
// the id is not available, have to create a new one
note.remove(NoteColumns.ID);
}
}
}
if (js.has(GTaskStringUtils.META_HEAD_DATA)) {//判断便签中的数据条目
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
for (int i = 0; i < dataArray.length(); i++) {//依次删除存在的data的ID
JSONObject data = dataArray.getJSONObject(i);//获取对应数据的jsonobject对象
if (data.has(DataColumns.ID)) {//判断数据中是否有条目
long dataId = data.getLong(DataColumns.ID);
if (DataUtils.existInDataDatabase(mContentResolver, dataId)) {//data id存在时删除已建立的对应ID
// the data id is not available, have to create
// a new one
data.remove(DataColumns.ID);
}
}
}
}
} catch (JSONException e) {//出现异常时,打印异常信息
Log.w(TAG, e.toString());//获取异常类型和异常详细消息
e.printStackTrace();
}
sqlNote.setContent(js);//将之前的操作获取到的js更新至该节点中
Long parentId = mGidToNid.get(((Task) node).getParent().getGid());//找到父任务的ID号并作为sqlNote的父任务的ID没有父任务则报错
if (parentId == null) {//当不能找到该任务上一级的id时报错
Log.e(TAG, "cannot find task's parent id locally");//本地无法找到父进程id
throw new ActionFailureException("cannot add local node");//报告无法添加本地节点
}
sqlNote.setParentId(parentId.longValue());
}
// create the local node
sqlNote.setGtaskId(node.getGid());//用getGid函数获取node节点的Gid用于设置本地Gtask的ID
sqlNote.commit(false);//更新本地便签
// update gid-nid mapping
mGidToNid.put(node.getGid(), sqlNote.getId());//更新gid与nid的映射表
mNidToGid.put(sqlNote.getId(), node.getGid());
// update meta
updateRemoteMeta(node.getGid(), sqlNote);//更新远程的数据
}
private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException {//更新本地节点,两个传入参数,一个是待更新的节点,一个是指向待增加位置的指针
if (mCancelled) {//如果正在取消同步,直接返回
return;
}
SqlNote sqlNote;//新建一个sql节点并将内容存储进Node中
// update the note locally
sqlNote = new SqlNote(mContext, c);//新建一个sql节点并将内容存储进Node中
sqlNote.setContent(node.getLocalJSONFromContent());//利用待更新节点中的内容对数据库节点进行设置
Long parentId = (node instanceof Task) ? mGidToNid.get(((Task) node).getParent().getGid())
: new Long(Notes.ID_ROOT_FOLDER);// 设置父任务的ID通过判断node是不是Task的实例
if (parentId == null) {//当不能找到该任务上一级的id时报错
Log.e(TAG, "cannot find task's parent id locally");//错误,不能在本地找到任务的父 id
throw new ActionFailureException("cannot update local node");//抛出异常,不能更新本地节点
}
sqlNote.setParentId(parentId.longValue());//设置该任务节点上一级的id
sqlNote.commit(true);//抛出异常,不能更新本地节点
// update meta info
updateRemoteMeta(node.getGid(), sqlNote);//升级meta
}
private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException {//添加远程节点
if (mCancelled) {//如果正在取消同步,直接返回
return;
}
SqlNote sqlNote = new SqlNote(mContext, c);//新建一个sql节点并将内容存储进Node中
Node n;
// update remotely
if (sqlNote.isNoteType()) {//若待增添的节点为任务节点,进一步操作
Task task = new Task();
task.setContentByLocalJSON(sqlNote.getContent());
String parentGid = mNidToGid.get(sqlNote.getParentId());//找不到parentID时报错
if (parentGid == null) {
Log.e(TAG, "cannot find task's parent tasklist");//错误,无法找到任务的父列表
throw new ActionFailureException("cannot add remote task");//抛出异常,无法添加云端任务
}
mGTaskListHashMap.get(parentGid).addChildTask(task);
GTaskClient.getInstance().createTask(task);
n = (Node) task;
// add meta
updateRemoteMeta(task.getGid(), sqlNote);
} else {
TaskList tasklist = null;
// we need to skip folder if it has already existed
String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX;//当文件夹已经存在则跳过处理,若不存在则创建新的文件夹
if (sqlNote.getId() == Notes.ID_ROOT_FOLDER)//按照文件夹的形式进行命名
folderName += GTaskStringUtils.FOLDER_DEFAULT;
else if (sqlNote.getId() == Notes.ID_CALL_RECORD_FOLDER)
folderName += GTaskStringUtils.FOLDER_CALL_NOTE;//若为电话号码便签文件夹则按电话号码便签命名
else
folderName += sqlNote.getSnippet();
Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();//使用iterator作为map接口对map进行遍历
while (iter.hasNext()) {//iterator迭代器通过统一的接口迭代所有的map元素
Map.Entry<String, TaskList> entry = iter.next();
String gid = entry.getKey();
TaskList list = entry.getValue();
if (list.getName().equals(folderName)) {//若寻找到的任务列表已存在,则直接在里面更新
tasklist = list;//找不到可以匹配的任务链
if (mGTaskHashMap.containsKey(gid)) {
mGTaskHashMap.remove(gid);
}
break;
}
}
// no match we can add now
if (tasklist == null) {//若找不到任务列表,则创建一个新的任务列表
tasklist = new TaskList();
tasklist.setContentByLocalJSON(sqlNote.getContent());
GTaskClient.getInstance().createTaskList(tasklist);
mGTaskListHashMap.put(tasklist.getGid(), tasklist);
}
n = (Node) tasklist;
}
// update local note
sqlNote.setGtaskId(n.getGid());//更新本地节点
sqlNote.commit(false);
sqlNote.resetLocalModified();
sqlNote.commit(true);
// gid-id mapping
mGidToNid.put(n.getGid(), sqlNote.getId());//更新gid与nid的映射表
mNidToGid.put(sqlNote.getId(), n.getGid());
}
private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException {//更新远程节点
if (mCancelled) {//如果正在取消同步,直接返回
return;
}
SqlNote sqlNote = new SqlNote(mContext, c);//在指针指向处创建一个新的节点
// update remotely
node.setContentByLocalJSON(sqlNote.getContent());
GTaskClient.getInstance().addUpdateNode(node);//对远程GTask的节点进行更新
// update meta
updateRemoteMeta(node.getGid(), sqlNote);//根据sqlNote和node的Gid更新远程的节点
// move task if necessary
if (sqlNote.isNoteType()) {//判断节点类型是否符合要求
Task task = (Task) node;//新建一个task节点
TaskList preParentList = task.getParent();//找到当前任务列表的父节点google id和之前父任务链
String curParentGid = mNidToGid.get(sqlNote.getParentId());//获取上一级任务列表的gid
if (curParentGid == null) {//找不到当前任务的上一级任务列表,报错
Log.e(TAG, "cannot find task's parent tasklist");//错误,无法找到任务的父列表
throw new ActionFailureException("cannot update remote task");//抛出异常,无法添加云端任务
}
TaskList curParentList = mGTaskListHashMap.get(curParentGid);//通过HashMap找到对应Gid的TaskList
if (preParentList != curParentList) {//若两个上一级任务列表不一致,进行任务的移动,从之前的任务列表中移动到该列表中
preParentList.removeChildTask(task);
curParentList.addChildTask(task);
GTaskClient.getInstance().moveTask(task, preParentList, curParentList);
}
}
// clear local modified flag
sqlNote.resetLocalModified();//清除本地的modified flag
sqlNote.commit(true);//commit 到本地数据库
}
private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException {//更新远程元数组的google id和数据库节点
if (sqlNote != null && sqlNote.isNoteType()) {//判断节点类型是否符合,类型符合时才进行更新操作
MetaData metaData = mMetaHashMap.get(gid);//从google id获取任务列表
if (metaData != null) {//若元数据组为空,则创建一个新的元数据组
metaData.setMeta(gid, sqlNote.getContent());//通过gid获取元数据
GTaskClient.getInstance().addUpdateNode(metaData);
} else {//若元数据组不为空,则进行更新
metaData = new MetaData();
metaData.setMeta(gid, sqlNote.getContent());
mMetaList.addChildTask(metaData);
mMetaHashMap.put(gid, metaData);
GTaskClient.getInstance().createTask(metaData);
}
}
}
private void refreshLocalSyncId() throws NetworkFailureException {//刷新本地便签id从远程同步
if (mCancelled) {
return;
}//获取最近的gtask list
// get the latest gtask list
mGTaskHashMap.clear();//否则初始化hash表
mGTaskListHashMap.clear();
mMetaHashMap.clear();
initGTaskList();
Cursor c = null;
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,//使指针指向列表中需要更新的任务
"(type<>? AND parent_id<>?)", new String[] {
String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)
}, NoteColumns.TYPE + " DESC");//按类型递减顺序返回查询结果
if (c != null) {
while (c.moveToNext()) {//获取最新的GTask列表
String gid = c.getString(SqlNote.GTASK_ID_COLUMN);
Node node = mGTaskHashMap.get(gid);
if (node != null) {
mGTaskHashMap.remove(gid);
ContentValues values = new ContentValues();
values.put(NoteColumns.SYNC_ID, node.getLastModified());//在ContentValues中创建键值对。准备通过contentResolver写入数据
mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI,
c.getLong(SqlNote.ID_COLUMN)), values, null, null);//进行批量更改选择参数为NULL应该可以用insert替换参数分别为表名和需要更新的value对象。
} else {//若发现节点为空则报错
Log.e(TAG, "something is missed");//错误,部分内容丢失
throw new ActionFailureException(
"some local items don't have gid after sync");//抛出异常,部分本地项目在同步后没有 gid
}
}
} else {//若发现列表为空则报错
Log.w(TAG, "failed to query local note to refresh sync id");//警告,询问本地待同步更新的便签 id 失败
}
} finally {//结束操作之后,将指针指向内容关闭并将指针置空
if (c != null) {
c.close();//关闭 cursor 所指文件
c = null;//cursor 置空
}
}
}
public String getSyncAccount() {return GTaskClient.getInstance().getSyncAccount().name;}//获取同步账户,通过客户端调用函数获取名字作为信息返回
public void cancelSync() {
mCancelled = true;
}//若需要取消同步则将mCancelled值设置为真
}

@ -0,0 +1,128 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.gtask.remote;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
public class GTaskSyncService extends Service {//提供GTask的同步服务
public final static String ACTION_STRING_NAME = "sync_action_type";//定义一系列静态变量用来表示同步操作的状态
public final static int ACTION_START_SYNC = 0;
public final static int ACTION_CANCEL_SYNC = 1;
public final static int ACTION_INVALID = 2;
//用数字0、1、2分别表示开始同步、取消同步、同步无效
public final static String GTASK_SERVICE_BROADCAST_NAME = "net.micode.notes.gtask.remote.gtask_sync_service";//服务广播的名称
public final static String GTASK_SERVICE_BROADCAST_IS_SYNCING = "isSyncing";//表示广播正在同步
public final static String GTASK_SERVICE_BROADCAST_PROGRESS_MSG = "progressMsg";//GTask广播服务进程消息
private static GTaskASyncTask mSyncTask = null;
private static String mSyncProgress = "";
private void startSync() {//开始同步的操作
if (mSyncTask == null) {//若当前没有同步工作申请一个task并把指针指向新任务广播后执行
mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
public void onComplete() {//实现了在GTaskASyncTask类中定义的接口onComplete( )
mSyncTask = null;
sendBroadcast("");//发布广播消息
stopSelf();//完成功能后将service停掉
}
});//执行同步任务
sendBroadcast("");
mSyncTask.execute();//调用同步执行的函数
}//让任务是以单线程队列方式或线程池队列方式运行
}
private void cancelSync() {//取消同步
if (mSyncTask != null) {//同步的任务非空
mSyncTask.cancelSync();//取消同步任务
}
}
@Override
public void onCreate() {
mSyncTask = null;
}//初始化一个service
@Override
public int onStartCommand(Intent intent, int flags, int startId) {//告诉系统如何重启服务,如判断是否异常终止后重新启动,在何种情况下异常终止等
Bundle bundle = intent.getExtras();//Bundle类可携带数据用于存放key-value明值对应形式的值
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {//判断当前的同步状态,根据开始或取消,执行对应操作
switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {//判断当前同步状态,启动或取消
case ACTION_START_SYNC:
startSync();//启动同步
break;
case ACTION_CANCEL_SYNC:
cancelSync();//取消同步
break;
default:
break;
}
return START_STICKY;//等待新的intent来是这个service继续运行
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onLowMemory() {//内存不足时的处理函数
if (mSyncTask != null) {
mSyncTask.cancelSync();
}
}
public IBinder onBind(Intent intent) {
return null;
}//用于绑定操作的函数
public void sendBroadcast(String msg) {//执行发送广播内容的操作
mSyncProgress = msg;
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);//创建一个新的Intent
intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null);//附加INTENT中的相应参数的值
intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg);
sendBroadcast(intent);//发送这个通知
}
public static void startSync(Activity activity) {//开始同步
GTaskManager.getInstance().setActivityContext(activity);//任务管理器获取活动的内容
Intent intent = new Intent(activity, GTaskSyncService.class);//创建新intent
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC);//将之前初始化的各种字符串加入intent
activity.startService(intent);//开始同步服务
}
public static void cancelSync(Context context) {//取消同步
Intent intent = new Intent(context, GTaskSyncService.class);//显式构建intent以函数参数context作为第一个参数以自己GTaskSyncService.class作为目标活动
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC);
context.startService(intent);//使用startService执行intent在本活动基础上打开GTaskSyncService活动
}
public static boolean isSyncing() {
return mSyncTask != null;
}//判断当前是否处于同步状态
public static String getProgressString() {
return mSyncProgress;
}//返回当前同步状态
}

@ -0,0 +1,2 @@
#Fri Jun 02 20:44:46 CST 2023
gradle.version=7.5.1

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\Lenovo\.android\avd\Pixel_2_API_31.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-06-03T06:17:35.933818500Z" />
</component>
</project>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$USER_HOME$/.gradle/wrapper/dists/gradle-7.5.1-bin/7jzzequgds1hbszbhq3npc5ng/gradle-7.5.1" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
</component>
</project>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

@ -0,0 +1,19 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion '30.0.2'
defaultConfig {
applicationId "net.micode.notes"
minSdkVersion 21
targetSdkVersion 8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}

@ -0,0 +1,12 @@
/**
* Automatically generated file. DO NOT MODIFY
*/
package net.micode.notes;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "net.micode.notes";
public static final String BUILD_TYPE = "debug";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "0.1";
}

@ -0,0 +1,10 @@
{
"version": 2,
"artifactType": {
"type": "COMPATIBLE_SCREEN_MANIFEST",
"kind": "Directory"
},
"applicationId": "net.micode.notes",
"variantName": "debug",
"elements": []
}

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="D:\xiaominotes\Finalnotes\MiNotes\app\src\main\assets"/><source path="D:\xiaominotes\Finalnotes\MiNotes\app\build\intermediates\shader_assets\debug\out"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="D:\xiaominotes\Finalnotes\MiNotes\app\src\debug\assets"/></dataSet></merger>

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="D:\xiaominotes\Finalnotes\MiNotes\app\src\main\jniLibs"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="D:\xiaominotes\Finalnotes\MiNotes\app\src\debug\jniLibs"/></dataSet></merger>

@ -0,0 +1,99 @@
#Sun Jun 18 20:10:29 CST 2023
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_4x_red.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_4x_red.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_red_up.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_red_up.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_red_middle.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_red_middle.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\note_list_footer.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_note_list_footer.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\menu\\note_list.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\menu_note_list.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\dialog_edit_text.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_dialog_edit_text.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_yellow_down.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_yellow_down.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\imaginsert.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_imaginsert.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_green_single.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_green_single.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\menu\\note_edit.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\menu_note_edit.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\selected.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_selected.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\font_large.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_font_large.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\dropdown_icon.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_dropdown_icon.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_blue_single.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_blue_single.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_2x_green.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_2x_green.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_4x_blue.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_4x_blue.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_white_single.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_white_single.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\xml\\searchable.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\xml_searchable.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_green.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_green.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_blue.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_blue.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\bg_color_btn_mask.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_bg_color_btn_mask.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\menu\\call_note_edit.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\menu_call_note_edit.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\note_edit_list_item.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_note_edit_list_item.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_yellow_middle.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_yellow_middle.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\new_note_pressed.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_new_note_pressed.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_green_down.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_green_down.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_title_green.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_title_green.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_4x_green.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_4x_green.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_title_white.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_title_white.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\widget_4x.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_widget_4x.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\settings_header.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_settings_header.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_4x_white.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_4x_white.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_footer_bg.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_footer_bg.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\call_record.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_call_record.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\raw\\introduction=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\raw_introduction.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\menu\\sub_folder.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\menu_sub_folder.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_yellow_up.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_yellow_up.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\font_size_selector_bg.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_font_size_selector_bg.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_folder.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_folder.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_red_down.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_red_down.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\insert.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_insert.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\note_edit_color_selector_panel.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_note_edit_color_selector_panel.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_title_blue.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_title_blue.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\note_item.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_note_item.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_2x_white.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_2x_white.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_background.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_background.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\menu\\call_record_folder.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\menu_call_record_folder.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_blue_up.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_blue_up.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\icon_app.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_icon_app.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\raw-zh-rCN\\introduction=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\raw-zh-rCN_introduction.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\note_list.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_note_list.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\folder_list_item.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_folder_list_item.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\title_alert.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_title_alert.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\add_account_text.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_add_account_text.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\xml\\widget_2x_info.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\xml_widget_2x_info.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_white_up.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_white_up.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_green_middle.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_green_middle.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_blue_down.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_blue_down.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_white_down.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_white_down.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\search_result.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_search_result.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\font_small.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_font_small.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\note_edit.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_note_edit.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\note_list_dropdown_menu.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_note_list_dropdown_menu.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_yellow.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_yellow.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\clock.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_clock.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_title_yellow.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_title_yellow.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\menu\\note_list_options.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\menu_note_list_options.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\widget_2x.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_widget_2x.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_red_single.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_red_single.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\insertimage.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_insertimage.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\title_bar_bg.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_title_bar_bg.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\menu\\note_list_dropdown.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\menu_note_list_dropdown.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\xml\\widget_4x_info.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\xml_widget_4x_info.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\new_note_normal.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_new_note_normal.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\color\\primary_text_dark.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\color_primary_text_dark.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_title_red.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_title_red.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\datetime_picker.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_datetime_picker.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable\\new_note.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable_new_note.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\font_normal.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_font_normal.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_2x_yellow.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_2x_yellow.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_2x_red.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_2x_red.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\menu_move.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_menu_move.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_4x_yellow.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_4x_yellow.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_green_up.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_green_up.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_blue_middle.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_blue_middle.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_red.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_red.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\notification.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_notification.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\menu_delete.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_menu_delete.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\delete.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_delete.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\font_super.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_font_super.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\color\\secondary_text_dark.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\color_secondary_text_dark.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\xml\\preferences.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\xml_preferences.xml.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\bg_btn_set_color.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_bg_btn_set_color.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\widget_2x_blue.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_widget_2x_blue.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_yellow_single.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_yellow_single.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\edit_white.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_edit_white.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\drawable-hdpi\\list_white_middle.9.png=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\drawable-hdpi_list_white_middle.9.png.flat
D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\src\\main\\res\\layout\\account_dialog_title.xml=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\res\\merged\\debug\\layout_account_dialog_title.xml.flat

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:ns1="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="format_for_exported_note">
<item>-%s</item>
<item>--%s</item>
<item>--%s</item>
<item>--%s</item>
</string-array>
<string-array name="menu_share_ways">
<item>Messaging</item>
<item>Email</item>
</string-array>
<color name="edit_text_color">#E91E63</color>
<color name="user_query_highlight">#E91E63</color>
<dimen name="text_font_size_large">26sp</dimen>
<dimen name="text_font_size_medium">20sp</dimen>
<dimen name="text_font_size_normal">17sp</dimen>
<dimen name="text_font_size_small">14sp</dimen>
<dimen name="text_font_size_super">33sp</dimen>
<plurals name="search_results_title">
<item quantity="one"><ns1:g example="1" id="number">%1$s</ns1:g> result for \"<ns1:g example="???" id="search">%2$s</ns1:g>\"</item>
<item quantity="other"><ns1:g example="15" id="number">%1$s</ns1:g> results for \"<ns1:g example="???" id="search">%2$s</ns1:g>\"</item>
</plurals>
<string name="alert_message_delete_folder">Confirm to delete folder and its notes?</string>
<string name="alert_message_delete_note">Confirm to delete this note?</string>
<string name="alert_message_delete_notes">Confirm to delete the selected %d notes?</string>
<string name="alert_title_delete">Delete selected notes</string>
<string name="app_name">Notes</string>
<string name="app_widget2x2">Notes 2x2</string>
<string name="app_widget4x4">Notes 4x4</string>
<string name="button_delete">Delete</string>
<string name="call_record_folder_name">Call notes</string>
<string name="datetime_dialog_cancel">cancel</string>
<string name="datetime_dialog_ok">set</string>
<string name="delete_remind_time_message">Delete reminder successfully</string>
<string name="error_note_empty_for_clock">Sorry, can not set clock on empty note</string>
<string name="error_note_empty_for_send_to_desktop">Sorry, can not send and empty note to home</string>
<string name="error_note_not_exist">The note is not exist</string>
<string name="error_sdcard_export">Export failed, please check SD card</string>
<string name="error_sdcard_unmounted">SD card busy, not available now</string>
<string name="error_sync_cancelled">Sync is canceled</string>
<string name="error_sync_internal">Sync failed, internal error occurs</string>
<string name="error_sync_network">Sync failed, please check network and account settings</string>
<string name="failed_sdcard_export">Export fail</string>
<string name="file_name_txt_format">notes_%s.txt</string>
<string name="file_path">/MIUI/notes/</string>
<string name="folder_exist">The folder %1$s exist, please rename</string>
<string name="format_date_ymd">yyyyMMdd</string>
<string name="format_datetime_mdhm">MMMd kk:mm</string>
<string name="format_exported_file_location">Export text file (%1$s) to SD (%2$s) directory</string>
<string name="format_folder_files_count">(%d)</string>
<string name="format_move_notes_to_folder">Have moved selected %1$d notes to %2$s folder</string>
<string name="hint_foler_name">Input name</string>
<string name="info_note_enter_desktop">Note added to home</string>
<string name="menu_alert">Remind me</string>
<string name="menu_create_folder">New Folder</string>
<string name="menu_delete">Delete</string>
<string name="menu_deselect_all">Deselect all</string>
<string name="menu_export_text">Export text</string>
<string name="menu_folder_change_name">Change folder name</string>
<string name="menu_folder_delete">Delete folder</string>
<string name="menu_folder_view">View folder</string>
<string name="menu_font_large">Large</string>
<string name="menu_font_normal">Medium</string>
<string name="menu_font_size">Font size</string>
<string name="menu_font_small">Small</string>
<string name="menu_font_super">Super</string>
<string name="menu_list_mode">Enter check list</string>
<string name="menu_move">Move to folder</string>
<string name="menu_move_parent_folder">Parent folder</string>
<string name="menu_normal_mode">Leave check list</string>
<string name="menu_remove_remind">Delete reminder</string>
<string name="menu_search">Search</string>
<string name="menu_select_all">Select all</string>
<string name="menu_select_none">Nothing selected, the operation is invalid</string>
<string name="menu_select_title">%d selected</string>
<string name="menu_send_to_desktop">Send to home</string>
<string name="menu_setting">Settings</string>
<string name="menu_share">Share</string>
<string name="menu_sync">Sync</string>
<string name="menu_sync_cancel">Cancel syncing</string>
<string name="menu_title_select_folder">Select folder</string>
<string name="note_alert_expired">Expired</string>
<string name="note_link_email">Send email</string>
<string name="note_link_other">Open map</string>
<string name="note_link_tel">Call</string>
<string name="note_link_web">Browse web</string>
<string name="notealert_enter">Take a look</string>
<string name="notealert_ok">Got it</string>
<string name="notelist_menu_new">Add note</string>
<string name="notelist_string_info">...</string>
<string name="preferences_account_summary">Sync notes with google task</string>
<string name="preferences_account_title">Sync account</string>
<string name="preferences_add_account">Add account</string>
<string name="preferences_bg_random_appear_title">New note background color random</string>
<string name="preferences_button_sync_cancel">Cancel syncing</string>
<string name="preferences_button_sync_immediately">Sync immediately</string>
<string name="preferences_dialog_change_account_title">Current account %1$s</string>
<string name="preferences_dialog_change_account_warn_msg">All sync related information will be deleted, which may result in duplicated items sometime</string>
<string name="preferences_dialog_select_account_tips">Please select a google account. Local notes will be synced with google task.</string>
<string name="preferences_dialog_select_account_title">Sync notes</string>
<string name="preferences_last_sync_time">Last sync time %1$s</string>
<string name="preferences_last_sync_time_format">yyyy-MM-dd hh:mm:ss</string>
<string name="preferences_menu_cancel">Cancel</string>
<string name="preferences_menu_change_account">Change sync account</string>
<string name="preferences_menu_remove_account">Remove sync account</string>
<string name="preferences_title">Settings</string>
<string name="preferences_toast_cannot_change_account">Cannot change the account because sync is in progress</string>
<string name="preferences_toast_success_set_accout">%1$s has been set as the sync account</string>
<string name="search">Notes</string>
<string name="search_hint">Search notes</string>
<string name="search_label">Searching Notes</string>
<string name="search_setting_description">Text in your notes</string>
<string name="set_remind_time_message">Set reminder</string>
<string name="success_sdcard_export">Export successful</string>
<string name="success_sync_account">Sync is successful with account %1$s</string>
<string name="sync_progress_init_list">Getting remote note list...</string>
<string name="sync_progress_login">Logging into %1$s...</string>
<string name="sync_progress_syncing">Synchronize local notes with Google Task...</string>
<string name="ticker_cancel">Sync is canceled</string>
<string name="ticker_fail">Sync is failed</string>
<string name="ticker_success">Sync is successful</string>
<string name="ticker_syncing">Syncing notes...</string>
<string name="widget_havenot_content">No associated note found, click to create associated note.</string>
<string name="widget_under_visit_mode">Privacy modecan not see note content</string>
<style name="HighlightTextAppearancePrimary">
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textColor">@color/primary_text_dark</item>
</style>
<style name="HighlightTextAppearanceSecondary">
<item name="android:textSize">@dimen/text_font_size_small</item>
<item name="android:textColor">@color/secondary_text_dark</item>
</style>
<style name="NoteActionBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
<item name="android:displayOptions"/>
<item name="android:visibility">gone</item>
</style>
<style name="NoteTheme" parent="@android:style/Theme.Holo.Light">
<item name="android:actionBarStyle">@style/NoteActionBarStyle</item>
</style>
<style name="TextAppearanceLarge">
<item name="android:textSize">@dimen/text_font_size_large</item>
<item name="android:textColorLink">#0000ff</item>
</style>
<style name="TextAppearanceMedium">
<item name="android:textSize">@dimen/text_font_size_medium</item>
<item name="android:textColorLink">#0000ff</item>
</style>
<style name="TextAppearanceNormal">
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textColorLink">#0000ff</item>
</style>
<style name="TextAppearancePrimaryItem">
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textColor">@color/primary_text_dark</item>
</style>
<style name="TextAppearanceSecondaryItem">
<item name="android:textSize">@dimen/text_font_size_small</item>
<item name="android:textColor">@color/secondary_text_dark</item>
</style>
<style name="TextAppearanceSuper">
<item name="android:textSize">@dimen/text_font_size_super</item>
<item name="android:textColorLink">#0000ff</item>
</style>
<style name="TextAppearanceUnderMenuIcon">
<item name="android:textSize">@dimen/text_font_size_normal</item>
<item name="android:textColor">@android:color/black</item>
</style>
</resources>

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="D:\xiaominotes\Finalnotes\MiNotes\app\src\main\shaders"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:&lt;dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="D:\xiaominotes\Finalnotes\MiNotes\app\src\debug\shaders"/></dataSet></merger>

@ -0,0 +1,4 @@
#Sun Jun 18 20:10:30 CST 2023
base.0=D\:\\xiaominotes\\Finalnotes\\MiNotes\\app\\build\\intermediates\\dex\\debug\\mergeProjectDexDebug\\classes.dex
renamed.0=classes.dex
path.0=classes.dex

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save