Compare commits

...

No commits in common. 'master' and 'zz' have entirely different histories.
master ... zz

1
.gitignore vendored

@ -7,3 +7,4 @@ project.properties
.settings/ .settings/
.classpath .classpath
.project .project
/.idea/

@ -1,22 +1,7 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.data; package net.micode.notes.data;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Data;
@ -24,29 +9,35 @@ import android.telephony.PhoneNumberUtils;
import android.util.Log; import android.util.Log;
import java.util.HashMap; import java.util.HashMap;
//change
public class Contact { public class Contact { //联系人
private static HashMap<String, String> sContactCache; private static HashMap<String, String> sContactCache;
private static final String TAG = "Contact"; private static final String TAG = "Contact";
private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER // 定义字符串CALLER_ID_SELECTION
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL("
+ " AND " + Data.RAW_CONTACT_ID + " IN "
+ Phone.NUMBER
+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'"
+ " AND " + Data.RAW_CONTACT_ID + " IN "
+ "(SELECT raw_contact_id " + "(SELECT raw_contact_id "
+ " FROM phone_lookup" + " FROM phone_lookup"
+ " WHERE min_match = '+')"; + " WHERE min_match = '+')";
// 获取联系人
public static String getContact(Context context, String phoneNumber) { public static String getContact(Context context, String phoneNumber) {
if(sContactCache == null) { if(sContactCache == null) {
sContactCache = new HashMap<String, String>(); sContactCache = new HashMap<String, String>();
} }
// 查找HashMap中是否已有phoneNumber信息
if(sContactCache.containsKey(phoneNumber)) { if(sContactCache.containsKey(phoneNumber)) {
return sContactCache.get(phoneNumber); return sContactCache.get(phoneNumber);
} }
String selection = CALLER_ID_SELECTION.replace("+", String selection = CALLER_ID_SELECTION.replace("+",
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));
// 查找数据库中phoneNumber的信息
Cursor cursor = context.getContentResolver().query( Cursor cursor = context.getContentResolver().query(
Data.CONTENT_URI, Data.CONTENT_URI,
new String [] { Phone.DISPLAY_NAME }, new String [] { Phone.DISPLAY_NAME },
@ -54,17 +45,22 @@ public class Contact {
new String[] { phoneNumber }, new String[] { phoneNumber },
null); null);
// 判定查询结果
// moveToFirst()返回第一条
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
try { try {
// 找到相关信息
String name = cursor.getString(0); String name = cursor.getString(0);
sContactCache.put(phoneNumber, name); sContactCache.put(phoneNumber, name);
return name; return name;
// 异常
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
Log.e(TAG, " Cursor get string error " + e.toString()); Log.e(TAG, " Cursor get string error " + e.toString());
return null; return null;
} finally { } finally {
cursor.close(); cursor.close();
} }
// 未找到相关信息
} else { } else {
Log.d(TAG, "No contact matched with number:" + phoneNumber); Log.d(TAG, "No contact matched with number:" + phoneNumber);
return null; return null;

@ -16,10 +16,14 @@
package net.micode.notes.data; package net.micode.notes.data;
import android.content.ContentUris;
import android.net.Uri; import android.net.Uri;
// Notes 类中定义了很多常量这些常量大多是int型和string型
public class Notes { public class Notes {
public static final String AUTHORITY = "micode_notes"; public static final String AUTHORITY = "micode_notes";
public static final String TAG = "Notes"; public static final String TAG = "Notes";
//以下三个常量对NoteColumns.TYPE的值进行设置时会用到
public static final int TYPE_NOTE = 0; public static final int TYPE_NOTE = 0;
public static final int TYPE_FOLDER = 1; public static final int TYPE_FOLDER = 1;
public static final int TYPE_SYSTEM = 2; public static final int TYPE_SYSTEM = 2;
@ -35,12 +39,24 @@ public class Notes {
public static final int ID_CALL_RECORD_FOLDER = -2; public static final int ID_CALL_RECORD_FOLDER = -2;
public static final int ID_TRASH_FOLER = -3; public static final int ID_TRASH_FOLER = -3;
public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.alert_date"; public static final String INTENT_EXTRA_ALERT_DATE =
public static final String INTENT_EXTRA_BACKGROUND_ID = "net.micode.notes.background_color_id";
public static final String INTENT_EXTRA_WIDGET_ID = "net.micode.notes.widget_id"; "net.micode.notes.alert_date";
public static final String INTENT_EXTRA_WIDGET_TYPE = "net.micode.notes.widget_type"; public static final String INTENT_EXTRA_BACKGROUND_ID =
public static final String INTENT_EXTRA_FOLDER_ID = "net.micode.notes.folder_id";
public static final String INTENT_EXTRA_CALL_DATE = "net.micode.notes.call_date"; "net.micode.notes.background_color_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";
public static final String INTENT_EXTRA_CALL_DATE =
"net.micode.notes.call_date";
public static final int TYPE_WIDGET_INVALIDE = -1; public static final int TYPE_WIDGET_INVALIDE = -1;
public static final int TYPE_WIDGET_2X = 0; public static final int TYPE_WIDGET_2X = 0;
@ -54,13 +70,20 @@ public class Notes {
/** /**
* Uri to query all notes and folders * Uri to query all notes and folders
*/ */
public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" +
AUTHORITY + "/note");//定义查询便签和文件夹的指针。
// public static final Uri my_URI = ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI , 10);
/** /**
* Uri to query data * Uri to query data
*/ */
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); public static final Uri CONTENT_DATA_URI = Uri.parse("content://" +
AUTHORITY + "/data");//定义查找数据的指针。
// 定义NoteColumns的常量,用于后面创建数据库的表头
public interface NoteColumns { public interface NoteColumns {
/** /**
* The unique ID for a row * The unique ID for a row
@ -72,7 +95,7 @@ public class Notes {
* The parent's id for note or folder * The parent's id for note or folder
* <P> Type: INTEGER (long) </P> * <P> Type: INTEGER (long) </P>
*/ */
public static final String PARENT_ID = "parent_id"; public static final String PARENT_ID = "parent_id";//为什么会有parent_id
/** /**
* Created data for note or folder * Created data for note or folder
@ -140,7 +163,7 @@ public class Notes {
* The last sync id * The last sync id
* <P> Type: INTEGER (long) </P> * <P> Type: INTEGER (long) </P>
*/ */
public static final String SYNC_ID = "sync_id"; public static final String SYNC_ID = "sync_id";//同步
/** /**
* Sign to indicate local modified or not * Sign to indicate local modified or not
@ -165,8 +188,9 @@ public class Notes {
* <P> Type : INTEGER (long) </P> * <P> Type : INTEGER (long) </P>
*/ */
public static final String VERSION = "version"; public static final String VERSION = "version";
} }//这些常量主要是定义便签的属性的。
// 定义DataColumns的常量,用于后面创建数据库的表头
public interface DataColumns { public interface DataColumns {
/** /**
* The unique ID for a row * The unique ID for a row
@ -206,41 +230,45 @@ public class Notes {
/** /**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for * Generic data column, the meaning is {@link #MIMETYPE} specific,
used for
* integer data type * integer data type
* <P> Type: INTEGER </P> * <P> Type: INTEGER </P>
*/ */
public static final String DATA1 = "data1"; public static final String DATA1 = "data1";
/** /**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for * Generic data column, the meaning is {@link #MIMETYPE} specific,
used for
* integer data type * integer data type
* <P> Type: INTEGER </P> * <P> Type: INTEGER </P>
*/ */
public static final String DATA2 = "data2"; public static final String DATA2 = "data2";
/** /**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for * Generic data column, the meaning is {@link #MIMETYPE} specific,
used for
* TEXT data type * TEXT data type
* <P> Type: TEXT </P> * <P> Type: TEXT </P>
*/ */
public static final String DATA3 = "data3"; public static final String DATA3 = "data3";
/** /**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for * Generic data column, the meaning is {@link #MIMETYPE} specific,
used for
* TEXT data type * TEXT data type
* <P> Type: TEXT </P> * <P> Type: TEXT </P>
*/ */
public static final String DATA4 = "data4"; public static final String DATA4 = "data4";
/** /**
* Generic data column, the meaning is {@link #MIMETYPE} specific, used for * Generic data column, the meaning is {@link #MIMETYPE} specific,
used for
* TEXT data type * TEXT data type
* <P> Type: TEXT </P> * <P> Type: TEXT </P>
*/ */
public static final String DATA5 = "data5"; public static final String DATA5 = "data5";
} }//主要是定义存储便签内容数据的
public static final class TextNote implements DataColumns { public static final class TextNote implements DataColumns {
/** /**
* Mode to indicate the text in check list mode or not * Mode to indicate the text in check list mode or not
@ -250,12 +278,18 @@ public class Notes {
public static final int MODE_CHECK_LIST = 1; public static final int MODE_CHECK_LIST = 1;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; public static final String CONTENT_TYPE =
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; "vnd.android.cursor.dir/text_note";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/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 { public static final class CallNote implements DataColumns {
/** /**
@ -270,10 +304,16 @@ public class Notes {
*/ */
public static final String PHONE_NUMBER = DATA3; public static final String PHONE_NUMBER = DATA3;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; public static final String CONTENT_TYPE =
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; "vnd.android.cursor.dir/call_note";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); public static final String CONTENT_ITEM_TYPE =
}
"vnd.android.cursor.item/call_note";
public static final Uri CONTENT_URI = Uri.parse("content://" +
AUTHORITY + "/call_note");
}//电话内容的数据结构
} }

@ -16,23 +16,23 @@
package net.micode.notes.data; package net.micode.notes.data;
import android.content.ContentValues; import android.content.ContentValues;//就是用于保存一些数据string boolean byte double float int long short ...)信息,这些信息可以被数据库操作时使用。
import android.content.Context; import android.content.Context;//加载和访问资源。android中主要是这两个功能但是这里具体不清楚
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;//主要提供了对应于添加、删除、更新、查询的操作方法: insert()、delete()、update()和query()。配合content.values
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;//用来管理数据的创建和版本更新
import android.util.Log; import android.util.Log;
import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
//数据库操作用SQLOpenhelper,对一些note和文件进行数据库的操作比如删除文件后将文件里的note也相应删除
public class NotesDatabaseHelper extends SQLiteOpenHelper { public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "note.db"; private static final String DB_NAME = "note.db";
private static final int DB_VERSION = 4; private static final int DB_VERSION = 4;
public interface TABLE { public interface TABLE { //接口分成note和data在后面的程序里分别使用过
public static final String NOTE = "note"; public static final String NOTE = "note";
public static final String DATA = "data"; public static final String DATA = "data";
@ -43,179 +43,179 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static NotesDatabaseHelper mInstance; private static NotesDatabaseHelper mInstance;
private static final String CREATE_NOTE_TABLE_SQL = private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" + "CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," + NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " 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.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")"; ")";//数据库中需要存储的项目的名称,就相当于创建一个表格的表头的内容。
private static final String CREATE_DATA_TABLE_SQL = private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" + "CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," + DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," + DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_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.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," + DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," + DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")"; ")";//和上面的功能一样,主要是存储的项目不同
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL = private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " + "CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");"; TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";//存储便签编号的一个数据表格
/** /**
* Increase folder's note count when move note to the folder * Increase folder's note count when move note to the folder
*/ */
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+ "CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " + " BEGIN " +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END"; " END";//在文件夹中移入一个Note之后需要更改的数据的表格。
/** /**
* Decrease folder's note count when move note from folder * Decrease folder's note count when move note from folder
*/ */
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " + "CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " + " BEGIN " +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID + " WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" + " AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END"; " END";//在文件夹中移出一个Note之后需要更改的数据的表格。
/** /**
* Increase folder's note count when insert new note to the folder * Increase folder's note count when insert new note to the folder
*/ */
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " + "CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE + " AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " + " BEGIN " +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END"; " END";//在文件夹中插入一个Note之后需要更改的数据的表格。
/** /**
* Decrease folder's note count when delete note from the folder * Decrease folder's note count when delete note from the folder
*/ */
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " + "CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + " AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " + " BEGIN " +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID + " WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" + " AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END"; " END";//在文件夹中删除一个Note之后需要更改的数据的表格。
/** /**
* Update note's content when insert data with type {@link DataConstants#NOTE} * Update note's content when insert data with type {@link DataConstants#NOTE}
*/ */
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER = private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " + "CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA + " AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + " WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" + " BEGIN" +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END"; " END";//在文件夹中对一个Note导入新的数据之后需要更改的数据的表格。
/** /**
* Update note's content when data with {@link DataConstants#NOTE} type has changed * Update note's content when data with {@link DataConstants#NOTE} type has changed
*/ */
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER = private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " + "CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA + " AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + " WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" + " BEGIN" +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END"; " END";//Note数据被修改后需要更改的数据的表格。
/** /**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted * Update note's content when data with {@link DataConstants#NOTE} type has deleted
*/ */
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER = private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " + "CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA + " AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + " WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" + " BEGIN" +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" + " SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" + " WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END"; " END";//Note数据被删除后需要更改的数据的表格。
/** /**
* Delete datas belong to note which has been deleted * Delete datas belong to note which has been deleted
*/ */
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER = private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " + "CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + " AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" + " BEGIN" +
" DELETE FROM " + TABLE.DATA + " DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";//删除已删除的便签的数据后需要更改的数据的表格。
/** /**
* Delete notes belong to folder which has been deleted * Delete notes belong to folder which has been deleted
*/ */
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER = private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " + "CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE + " AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" + " BEGIN" +
" DELETE FROM " + TABLE.NOTE + " DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";//删除已删除的文件夹的便签后需要更改的数据的表格。
/** /**
* Move notes belong to folder which has been moved to trash folder * Move notes belong to folder which has been moved to trash folder
*/ */
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER = private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " + "CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE + " AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + " WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" + " BEGIN" +
" UPDATE " + TABLE.NOTE + " UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + " SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END"; " END";//还原垃圾桶中便签后需要更改的数据的表格。
public NotesDatabaseHelper(Context context) { public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION); super(context, DB_NAME, null, DB_VERSION);
} }//构造函数,传入数据库的名称和版本
public void createNoteTable(SQLiteDatabase db) { public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL); db.execSQL(CREATE_NOTE_TABLE_SQL);
reCreateNoteTableTriggers(db); reCreateNoteTableTriggers(db);
createSystemFolder(db); createSystemFolder(db);
Log.d(TAG, "note table has been created"); Log.d(TAG, "note table has been created");
} }//创建表格(用来存储标签属性)
private void reCreateNoteTableTriggers(SQLiteDatabase db) { private void reCreateNoteTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
@ -233,7 +233,8 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER); db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER); db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER); db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
} }//execSQL是数据库操作的API主要是更改行为的SQL语句。
//在这里主要是用来重新创建上述定义的表格用的,先删除原来有的数据库的触发器再重新创建新的数据库
private void createSystemFolder(SQLiteDatabase db) { private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
@ -268,14 +269,14 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values);
} }//创建几个系统文件夹
public void createDataTable(SQLiteDatabase db) { public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL); db.execSQL(CREATE_DATA_TABLE_SQL);
reCreateDataTableTriggers(db); reCreateDataTableTriggers(db);
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
Log.d(TAG, "data table has been created"); Log.d(TAG, "data table has been created");
} }//创建表格(用来存储标签内容)
private void reCreateDataTableTriggers(SQLiteDatabase db) { private void reCreateDataTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
@ -285,20 +286,22 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
} }//同上面的execSQL
static synchronized NotesDatabaseHelper getInstance(Context context) { static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) { if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context); mInstance = new NotesDatabaseHelper(context);
} }
return mInstance; return mInstance;
} }//上网查是为解决同一时刻只能有一个线程执行.
//在写程序库代码时,有时有一个类需要被所有的其它类使用,
//但又要求这个类只能被实例化一次,是个服务类,定义一次,其它类使用同一个这个类的实例
@Override @Override
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {
createNoteTable(db); createNoteTable(db);
createDataTable(db); createDataTable(db);
} }//实现两个表格(上面创建的两个表格)
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
@ -331,14 +334,14 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
throw new IllegalStateException("Upgrade notes database to version " + newVersion throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails"); + "fails");
} }
} }//数据库版本的更新(数据库内容的更改)
private void upgradeToV2(SQLiteDatabase db) { private void upgradeToV2(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
createNoteTable(db); createNoteTable(db);
createDataTable(db); createDataTable(db);
} }//更新到V2版本
private void upgradeToV3(SQLiteDatabase db) { private void upgradeToV3(SQLiteDatabase db) {
// drop unused triggers // drop unused triggers
@ -353,10 +356,10 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values); db.insert(TABLE.NOTE, null, values);
} }//更新到V3版本
private void upgradeToV4(SQLiteDatabase db) { private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0"); + " INTEGER NOT NULL DEFAULT 0");
} }//更新到V4版本,但是不知道V2、V3、V4是什么意思
} }

@ -16,7 +16,6 @@
package net.micode.notes.data; package net.micode.notes.data;
import android.app.SearchManager; import android.app.SearchManager;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.ContentUris; import android.content.ContentUris;
@ -33,9 +32,15 @@ import net.micode.notes.R;
import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE; import net.micode.notes.data.NotesDatabaseHelper.TABLE;
//为存储和获取数据提供接口。可以在不同的应用程序之间共享数据
//ContentProvider提供的方法
//query查询
//insert插入
//update更新
//delete删除
//getType得到数据类型
public class NotesProvider extends ContentProvider { public class NotesProvider extends ContentProvider {
// UriMatcher用于匹配Uri
private static final UriMatcher mMatcher; private static final UriMatcher mMatcher;
private NotesDatabaseHelper mHelper; private NotesDatabaseHelper mHelper;
@ -51,7 +56,9 @@ public class NotesProvider extends ContentProvider {
private static final int URI_SEARCH_SUGGEST = 6; private static final int URI_SEARCH_SUGGEST = 6;
static { static {
// 创建UriMatcher时调用UriMatcher(UriMatcher.NO_MATCH)表示不匹配任何路径的返回码
mMatcher = new UriMatcher(UriMatcher.NO_MATCH); mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 把需要匹配Uri路径全部给注册上
mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE);
mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM);
mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA);
@ -65,33 +72,40 @@ public class NotesProvider extends ContentProvider {
* x'0A' represents the '\n' character in sqlite. For title and content in the search result, * x'0A' represents the '\n' character in sqlite. For title and content in the search result,
* we will trim '\n' and white space in order to show more information. * we will trim '\n' and white space in order to show more information.
*/ */
// 声明 NOTES_SEARCH_PROJECTION
private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + ","
+ NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + ","
+ "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + ","
+ R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + ","
+ "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + ","
+ "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA;
// 声明NOTES_SNIPPET_SEARCH_QUERY
private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION
+ " FROM " + TABLE.NOTE + " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.SNIPPET + " LIKE ?" + " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
+ " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
+ " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
@Override @Override
// Context只有在onCreate()中才被初始化
// 对mHelper进行实例化
public boolean onCreate() { public boolean onCreate() {
mHelper = NotesDatabaseHelper.getInstance(getContext()); mHelper = NotesDatabaseHelper.getInstance(getContext());
return true; return true;
} }
@Override @Override
// 查询uri在数据库中对应的位置
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) { String sortOrder) {
Cursor c = null; Cursor c = null;
// 获取可读数据库
SQLiteDatabase db = mHelper.getReadableDatabase(); SQLiteDatabase db = mHelper.getReadableDatabase();
String id = null; String id = null;
// 匹配查找uri
switch (mMatcher.match(uri)) { switch (mMatcher.match(uri)) {
// 对于不同的匹配值,在数据库中查找相应的条目
case URI_NOTE: case URI_NOTE:
c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null,
sortOrder); sortOrder);
@ -113,6 +127,7 @@ public class NotesProvider extends ContentProvider {
case URI_SEARCH: case URI_SEARCH:
case URI_SEARCH_SUGGEST: case URI_SEARCH_SUGGEST:
if (sortOrder != null || projection != null) { if (sortOrder != null || projection != null) {
// 不合法的参数异常
throw new IllegalArgumentException( throw new IllegalArgumentException(
"do not specify sortOrder, selection, selectionArgs, or projection" + "with this query"); "do not specify sortOrder, selection, selectionArgs, or projection" + "with this query");
} }
@ -120,6 +135,8 @@ public class NotesProvider extends ContentProvider {
String searchString = null; String searchString = null;
if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) { if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {
if (uri.getPathSegments().size() > 1) { if (uri.getPathSegments().size() > 1) {
// getPathSegments()方法得到一个String的List
// 在uri.getPathSegments().get(1)为第2个元素
searchString = uri.getPathSegments().get(1); searchString = uri.getPathSegments().get(1);
} }
} else { } else {
@ -139,6 +156,7 @@ public class NotesProvider extends ContentProvider {
} }
break; break;
default: default:
// 抛出异常
throw new IllegalArgumentException("Unknown URI " + uri); throw new IllegalArgumentException("Unknown URI " + uri);
} }
if (c != null) { if (c != null) {
@ -148,13 +166,17 @@ public class NotesProvider extends ContentProvider {
} }
@Override @Override
// 插入一个uri
public Uri insert(Uri uri, ContentValues values) { public Uri insert(Uri uri, ContentValues values) {
// 获得可写的数据库
SQLiteDatabase db = mHelper.getWritableDatabase(); SQLiteDatabase db = mHelper.getWritableDatabase();
long dataId = 0, noteId = 0, insertedId = 0; long dataId = 0, noteId = 0, insertedId = 0;
switch (mMatcher.match(uri)) { switch (mMatcher.match(uri)) {
// 新增一个条目
case URI_NOTE: case URI_NOTE:
insertedId = noteId = db.insert(TABLE.NOTE, null, values); insertedId = noteId = db.insert(TABLE.NOTE, null, values);
break; break;
// 如果存在查找NOTE_ID
case URI_DATA: case URI_DATA:
if (values.containsKey(DataColumns.NOTE_ID)) { if (values.containsKey(DataColumns.NOTE_ID)) {
noteId = values.getAsLong(DataColumns.NOTE_ID); noteId = values.getAsLong(DataColumns.NOTE_ID);
@ -167,6 +189,7 @@ public class NotesProvider extends ContentProvider {
throw new IllegalArgumentException("Unknown URI " + uri); throw new IllegalArgumentException("Unknown URI " + uri);
} }
// Notify the note uri // Notify the note uri
// notifyChange获得一个ContextResolver对象并且更新里面的内容
if (noteId > 0) { if (noteId > 0) {
getContext().getContentResolver().notifyChange( getContext().getContentResolver().notifyChange(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null); ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null);
@ -178,13 +201,17 @@ public class NotesProvider extends ContentProvider {
ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null); ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null);
} }
// 返回插入的uri的路径
return ContentUris.withAppendedId(uri, insertedId); return ContentUris.withAppendedId(uri, insertedId);
} }
@Override @Override
// 删除一个uri
public int delete(Uri uri, String selection, String[] selectionArgs) { public int delete(Uri uri, String selection, String[] selectionArgs) {
//Uri代表要操作的数据Android上可用的每种资源 -包括 图像、视频片段、音频资源等都可以用Uri来表示。
int count = 0; int count = 0;
String id = null; String id = null;
// 获得可写的数据库
SQLiteDatabase db = mHelper.getWritableDatabase(); SQLiteDatabase db = mHelper.getWritableDatabase();
boolean deleteData = false; boolean deleteData = false;
switch (mMatcher.match(uri)) { switch (mMatcher.match(uri)) {
@ -228,6 +255,7 @@ public class NotesProvider extends ContentProvider {
} }
@Override @Override
// 更新一个uri
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0; int count = 0;
String id = null; String id = null;
@ -267,10 +295,12 @@ public class NotesProvider extends ContentProvider {
return count; return count;
} }
// 将字符串解析成规定格式
private String parseSelection(String selection) { private String parseSelection(String selection) {
return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
} }
//增加一个noteVersion
private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { private void increaseNoteVersion(long id, String selection, String[] selectionArgs) {
StringBuilder sql = new StringBuilder(120); StringBuilder sql = new StringBuilder(120);
sql.append("UPDATE "); sql.append("UPDATE ");
@ -293,6 +323,7 @@ public class NotesProvider extends ContentProvider {
sql.append(selectString); sql.append(selectString);
} }
// execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句
mHelper.getWritableDatabase().execSQL(sql.toString()); mHelper.getWritableDatabase().execSQL(sql.toString());
} }

@ -1,54 +1,53 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
import android.database.Cursor;
import android.util.Log;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
public class MetaData extends Task { public class MetaData extends Task {
/*
* TAG
* getSimpleName ()
*/
private final static String TAG = MetaData.class.getSimpleName(); private final static String TAG = MetaData.class.getSimpleName();
private String mRelatedGid = null; private String mRelatedGid = null;
/*
public void setMeta(String gid, JSONObject metaInfo) { *
* JSONObjectput ()TasksetNotes ()setName ()
*
*/
public void setMeta(String gid, JSONObject metaInfo)
{
//对函数块进行注释
try { try {
metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); metaInfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid);
/*
* metaInfojsonobject
*/
} catch (JSONException e) { } catch (JSONException e) {
Log.e(TAG, "failed to put related gid"); Log.e(TAG, "failed to put related gid");
/*
*
*/
} }
setNotes(metaInfo.toString()); setNotes(metaInfo.toString());
setName(GTaskStringUtils.META_NOTE_NAME); setName(GTaskStringUtils.META_NOTE_NAME);
} }
/*
* Gid
*/
public String getRelatedGid() { public String getRelatedGid() {
return mRelatedGid; return mRelatedGid;
} }
/*
*
* Made By CuiCan
*/
@Override @Override
public boolean isWorthSaving() { public boolean isWorthSaving() {
return getNotes() != null; return getNotes() != null;
} }
/*
* 使json
* TasksetContentByRemoteJSON ()
*
*/
@Override @Override
public void setContentByRemoteJSON(JSONObject js) { public void setContentByRemoteJSON(JSONObject js) {
super.setContentByRemoteJSON(js); super.setContentByRemoteJSON(js);
@ -58,25 +57,48 @@ public class MetaData extends Task {
mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID);
} catch (JSONException e) { } catch (JSONException e) {
Log.w(TAG, "failed to get related gid"); Log.w(TAG, "failed to get related gid");
/*
*
*/
mRelatedGid = null; mRelatedGid = null;
} }
} }
} }
/*
* 使json
* Made By CuiCan
*/
@Override @Override
public void setContentByLocalJSON(JSONObject js) { public void setContentByLocalJSON(JSONObject js) {
// this function should not be called // this function should not be called
throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called");
/*
*
*/
} }
/*
* json
* Made By CuiCan
*/
@Override @Override
public JSONObject getLocalJSONFromContent() { public JSONObject getLocalJSONFromContent() {
throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called");
/*
*
* Made By Cui Can
*/
} }
/*
*
* Made By CuiCan
*/
@Override @Override
public int getSyncAction(Cursor c) { public int getSyncAction(Cursor c) {
throw new IllegalAccessError("MetaData:getSyncAction should not be called"); throw new IllegalAccessError("MetaData:getSyncAction should not be called");
/*
*
* Made By Cui Can
*/
} }
} }

@ -1,51 +1,40 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
import android.database.Cursor; import android.database.Cursor;
import org.json.JSONObject; import org.json.JSONObject;
/**
*
* abstract
*/
public abstract class Node { public abstract class Node {
public static final int SYNC_ACTION_NONE = 0; //定义了各种用于表征同步状态的常量
public static final int SYNC_ACTION_NONE = 0;// 本地和云端都无可更新内容(即本地和云端内容一致)
public static final int SYNC_ACTION_ADD_REMOTE = 1; public static final int SYNC_ACTION_ADD_REMOTE = 1;// 需要在远程云端增加内容
public static final int SYNC_ACTION_ADD_LOCAL = 2; public static final int SYNC_ACTION_ADD_LOCAL = 2;// 需要在本地增加内容
public static final int SYNC_ACTION_DEL_REMOTE = 3; public static final int SYNC_ACTION_DEL_REMOTE = 3;// 需要在远程云端删除内容
public static final int SYNC_ACTION_DEL_LOCAL = 4; public static final int SYNC_ACTION_DEL_LOCAL = 4;// 需要在本地删除内容
public static final int SYNC_ACTION_UPDATE_REMOTE = 5; public static final int SYNC_ACTION_UPDATE_REMOTE = 5;// 需要将本地内容更新到远程云端
public static final int SYNC_ACTION_UPDATE_LOCAL = 6; public static final int SYNC_ACTION_UPDATE_LOCAL = 6;// 需要将远程云端内容更新到本地
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7; public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;// 同步出现冲突
public static final int SYNC_ACTION_ERROR = 8; public static final int SYNC_ACTION_ERROR = 8;// 同步出现错误
private String mGid; private String mGid;
private String mName; private String mName;
private long mLastModified; private long mLastModified;//记录最后一次修改时间
private boolean mDeleted; private boolean mDeleted;//表征是否被删除
public Node() { public Node() {
mGid = null; mGid = null;
@ -98,4 +87,4 @@ public abstract class Node {
return this.mDeleted; return this.mDeleted;
} }
} }

@ -1,50 +1,40 @@
/* /*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * Description便sqlnotedatanote
* * SqlData
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
/*
import android.content.ContentResolver; *
import android.content.ContentUris; *
import android.content.ContentValues; *
import android.content.Context; * Made By CuiCan
import android.database.Cursor; */
import android.net.Uri;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.NotesDatabaseHelper.TABLE;
import net.micode.notes.gtask.exception.ActionFailureException;
import org.json.JSONException;
import org.json.JSONObject;
public class SqlData { public class SqlData {
/*
* TAG
* getSimpleName ()
* Made By CuiCan
*/
private static final String TAG = SqlData.class.getSimpleName(); private static final String TAG = SqlData.class.getSimpleName();
private static final int INVALID_ID = -99999; private static final int INVALID_ID = -99999;//为mDataId置初始值-99999
/**
* NotesDataColumn
*/
// 集合了interface DataColumns中所有SF常量
public static final String[] PROJECTION_DATA = new String[] { public static final String[] PROJECTION_DATA = new String[] {
DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1, DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1,
DataColumns.DATA3 DataColumns.DATA3
}; };
/**
* sql5
*/
public static final int DATA_ID_COLUMN = 0; public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1; public static final int DATA_MIME_TYPE_COLUMN = 1;
@ -56,7 +46,7 @@ public class SqlData {
public static final int DATA_CONTENT_DATA_3_COLUMN = 4; public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
//判断是否直接用Content生成是为true否则为false
private boolean mIsCreate; private boolean mIsCreate;
private long mDataId; private long mDataId;
@ -71,10 +61,17 @@ public class SqlData {
private ContentValues mDiffDataValues; private ContentValues mDiffDataValues;
/*
*
* mContentResolverContentProvider
* mIsCreate
*
* Made By CuiCan
*/
public SqlData(Context context) { public SqlData(Context context) {
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = true; mIsCreate = true;
mDataId = INVALID_ID; mDataId = INVALID_ID;//mDataId置初始值-99999
mDataMimeType = DataConstants.NOTE; mDataMimeType = DataConstants.NOTE;
mDataContent = ""; mDataContent = "";
mDataContentData1 = 0; mDataContentData1 = 0;
@ -82,6 +79,14 @@ public class SqlData {
mDiffDataValues = new ContentValues(); mDiffDataValues = new ContentValues();
} }
/*
*
* mContentResolverContentProvider
* mIsCreate
*
* Made By CuiCan
*/
public SqlData(Context context, Cursor c) { public SqlData(Context context, Cursor c) {
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = false; mIsCreate = false;
@ -89,6 +94,11 @@ public class SqlData {
mDiffDataValues = new ContentValues(); mDiffDataValues = new ContentValues();
} }
/*
*
*
* Made By CuiCan
*/
private void loadFromCursor(Cursor c) { private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN); mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN); mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
@ -97,7 +107,14 @@ public class SqlData {
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN); mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
} }
/*
*
*
* Made By CuiCan
*/
public void setContent(JSONObject js) throws JSONException { public void setContent(JSONObject js) throws JSONException {
//如果传入的JSONObject对象中有DataColumns.ID这一项则设置否则设为INVALID_ID
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID; long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId != dataId) { if (mIsCreate || mDataId != dataId) {
mDiffDataValues.put(DataColumns.ID, dataId); mDiffDataValues.put(DataColumns.ID, dataId);
@ -130,11 +147,18 @@ public class SqlData {
mDataContentData3 = dataContentData3; mDataContentData3 = dataContentData3;
} }
/*
*
*
* Made By CuiCan
*/
public JSONObject getContent() throws JSONException { public JSONObject getContent() throws JSONException {
if (mIsCreate) { if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet"); Log.e(TAG, "it seems that we haven't created this in database yet");
return null; return null;
} }
//创建JSONObject对象。并将相关数据放入其中并返回。
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
js.put(DataColumns.ID, mDataId); js.put(DataColumns.ID, mDataId);
js.put(DataColumns.MIME_TYPE, mDataMimeType); js.put(DataColumns.MIME_TYPE, mDataMimeType);
@ -144,6 +168,11 @@ public class SqlData {
return js; return js;
} }
/*
* commit
*
* Made By CuiCan
*/
public void commit(long noteId, boolean validateVersion, long version) { public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) { if (mIsCreate) {
@ -167,7 +196,7 @@ public class SqlData {
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null); Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null);
} else { } else {
result = mContentResolver.update(ContentUris.withAppendedId( result = mContentResolver.update(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues,
" ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE " ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.VERSION + "=?)", new String[] { + " WHERE " + NoteColumns.VERSION + "=?)", new String[] {
String.valueOf(noteId), String.valueOf(version) String.valueOf(noteId), String.valueOf(version)
@ -183,7 +212,13 @@ public class SqlData {
mIsCreate = false; mIsCreate = false;
} }
/*
* id
*
*
* Made By CuiCan
*/
public long getId() { public long getId() {
return mDataId; return mDataId;
} }
} }

@ -1,48 +1,26 @@
/* /*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * Description便sqldatanotedata
* * SqlDataSqlNote
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
/*
import android.appwidget.AppWidgetManager; *
import android.content.ContentResolver; *
import android.content.ContentValues; *
import android.content.Context; * Made By CuiCan
import android.database.Cursor; */
import android.net.Uri;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import net.micode.notes.tool.ResourceParser;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class SqlNote { public class SqlNote {
/*
* TAG
* getSimpleName ()
* Made By CuiCan
*/
private static final String TAG = SqlNote.class.getSimpleName(); private static final String TAG = SqlNote.class.getSimpleName();
private static final int INVALID_ID = -99999; private static final int INVALID_ID = -99999;
// 集合了interface NoteColumns中所有SF常量17个
public static final String[] PROJECTION_NOTE = new String[] { public static final String[] PROJECTION_NOTE = new String[] {
NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID, NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE, NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE,
@ -52,6 +30,7 @@ public class SqlNote {
NoteColumns.VERSION NoteColumns.VERSION
}; };
//以下设置17个列的编号
public static final int ID_COLUMN = 0; public static final int ID_COLUMN = 0;
public static final int ALERTED_DATE_COLUMN = 1; public static final int ALERTED_DATE_COLUMN = 1;
@ -86,6 +65,7 @@ public class SqlNote {
public static final int VERSION_COLUMN = 16; public static final int VERSION_COLUMN = 16;
//一下定义了17个内部的变量其中12个可以由content中获得5个需要初始化为0或者new
private Context mContext; private Context mContext;
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
@ -122,6 +102,13 @@ public class SqlNote {
private ArrayList<SqlData> mDataList; private ArrayList<SqlData> mDataList;
/*
*
* mIsCreate
*
* Made By CuiCan
*/
//构造函数只有context对所有的变量进行初始化
public SqlNote(Context context) { public SqlNote(Context context) {
mContext = context; mContext = context;
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
@ -129,9 +116,9 @@ public class SqlNote {
mId = INVALID_ID; mId = INVALID_ID;
mAlertDate = 0; mAlertDate = 0;
mBgColorId = ResourceParser.getDefaultBgId(context); mBgColorId = ResourceParser.getDefaultBgId(context);
mCreatedDate = System.currentTimeMillis(); mCreatedDate = System.currentTimeMillis();//调用系统函数获得创建时间
mHasAttachment = 0; mHasAttachment = 0;
mModifiedDate = System.currentTimeMillis(); mModifiedDate = System.currentTimeMillis();//最后一次修改时间初始化为创建时间
mParentId = 0; mParentId = 0;
mSnippet = ""; mSnippet = "";
mType = Notes.TYPE_NOTE; mType = Notes.TYPE_NOTE;
@ -143,17 +130,33 @@ public class SqlNote {
mDataList = new ArrayList<SqlData>(); mDataList = new ArrayList<SqlData>();
} }
/*
*
* mIsCreate
*
* Made By CuiCan
*/
//构造函数有context和一个数据库的cursor多数变量通过cursor指向的一条记录直接进行初始化
public SqlNote(Context context, Cursor c) { public SqlNote(Context context, Cursor c) {
mContext = context; mContext = context;
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
mIsCreate = false; mIsCreate = false;
loadFromCursor(c); loadFromCursor(c);
mDataList = new ArrayList<SqlData>(); mDataList = new ArrayList<SqlData>();
//
if (mType == Notes.TYPE_NOTE) if (mType == Notes.TYPE_NOTE)
loadDataContent(); loadDataContent();
mDiffNoteValues = new ContentValues(); mDiffNoteValues = new ContentValues();
} }
/*
*
* mIsCreate
*
* Made By CuiCan
*/
public SqlNote(Context context, long id) { public SqlNote(Context context, long id) {
mContext = context; mContext = context;
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();
@ -166,16 +169,21 @@ public class SqlNote {
} }
/*
* id
* Made By CuiCan
*/
private void loadFromCursor(long id) { private void loadFromCursor(long id) {
Cursor c = null; Cursor c = null;
try { try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)", c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] { new String[] {
String.valueOf(id) String.valueOf(id)
}, null); }, null);//通过id获得对应的ContentResolver中的cursor
if (c != null) { if (c != null) {
c.moveToNext(); c.moveToNext();
loadFromCursor(c); loadFromCursor(c);//然后加载数据进行初始化,这样函数
//SqlNote(Context context, long id)与SqlNote(Context context, long id)的实现方式基本相同
} else { } else {
Log.w(TAG, "loadFromCursor: cursor = null"); Log.w(TAG, "loadFromCursor: cursor = null");
} }
@ -185,7 +193,12 @@ public class SqlNote {
} }
} }
/*
*
* Made By CuiCan
*/
private void loadFromCursor(Cursor c) { private void loadFromCursor(Cursor c) {
//直接从一条记录中的获得以下变量的初始值
mId = c.getLong(ID_COLUMN); mId = c.getLong(ID_COLUMN);
mAlertDate = c.getLong(ALERTED_DATE_COLUMN); mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
mBgColorId = c.getInt(BG_COLOR_ID_COLUMN); mBgColorId = c.getInt(BG_COLOR_ID_COLUMN);
@ -200,13 +213,18 @@ public class SqlNote {
mVersion = c.getLong(VERSION_COLUMN); mVersion = c.getLong(VERSION_COLUMN);
} }
/*
* content
*
* Made By CuiCan
*/
private void loadDataContent() { private void loadDataContent() {
Cursor c = null; Cursor c = null;
mDataList.clear(); mDataList.clear();
try { try {
c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA, c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA,
"(note_id=?)", new String[] { "(note_id=?)", new String[] {
String.valueOf(mId) String.valueOf(mId)
}, null); }, null);
if (c != null) { if (c != null) {
if (c.getCount() == 0) { if (c.getCount() == 0) {
@ -226,6 +244,11 @@ public class SqlNote {
} }
} }
/*
* content
*
* Made By CuiCan
*/
public boolean setContent(JSONObject js) { public boolean setContent(JSONObject js) {
try { try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
@ -267,7 +290,6 @@ public class SqlNote {
mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId); mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId);
} }
mBgColorId = bgColorId; mBgColorId = bgColorId;
long createDate = note.has(NoteColumns.CREATED_DATE) ? note long createDate = note.has(NoteColumns.CREATED_DATE) ? note
.getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis(); .getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis();
if (mIsCreate || mCreatedDate != createDate) { if (mIsCreate || mCreatedDate != createDate) {
@ -359,6 +381,11 @@ public class SqlNote {
return true; return true;
} }
/*
* contentnote
*
* Made By CuiCan
*/
public JSONObject getContent() { public JSONObject getContent() {
try { try {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
@ -369,7 +396,7 @@ public class SqlNote {
} }
JSONObject note = new JSONObject(); JSONObject note = new JSONObject();
if (mType == Notes.TYPE_NOTE) { if (mType == Notes.TYPE_NOTE) {//类型为note时
note.put(NoteColumns.ID, mId); note.put(NoteColumns.ID, mId);
note.put(NoteColumns.ALERTED_DATE, mAlertDate); note.put(NoteColumns.ALERTED_DATE, mAlertDate);
note.put(NoteColumns.BG_COLOR_ID, mBgColorId); note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
@ -392,7 +419,7 @@ public class SqlNote {
} }
} }
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
} else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) { } else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) {//类型为文件夹或者
note.put(NoteColumns.ID, mId); note.put(NoteColumns.ID, mId);
note.put(NoteColumns.TYPE, mType); note.put(NoteColumns.TYPE, mType);
note.put(NoteColumns.SNIPPET, mSnippet); note.put(NoteColumns.SNIPPET, mSnippet);
@ -407,39 +434,84 @@ public class SqlNote {
return null; return null;
} }
/*
* idid
*
* Made By CuiCan
*/
public void setParentId(long id) { public void setParentId(long id) {
mParentId = id; mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id); mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
} }
/*
* idGtaskid
*
* Made By CuiCan
*/
public void setGtaskId(String gid) { public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
} }
/*
* idid
*
* Made By CuiCan
*/
public void setSyncId(long syncId) { public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId); mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
} }
/*
*
*
* Made By CuiCan
*/
public void resetLocalModified() { public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0); mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
} }
/*
* id
*
* Made By CuiCan
*/
public long getId() { public long getId() {
return mId; return mId;
} }
/*
* idid
*
* Made By CuiCan
*/
public long getParentId() { public long getParentId() {
return mParentId; return mParentId;
} }
/*
* 便
*
* Made By CuiCan
*/
public String getSnippet() { public String getSnippet() {
return mSnippet; return mSnippet;
} }
/*
* 便
*
* Made By CuiCan
*/
public boolean isNoteType() { public boolean isNoteType() {
return mType == Notes.TYPE_NOTE; return mType == Notes.TYPE_NOTE;
} }
/*
* commit
*
* Made By CuiCan
*/
public void commit(boolean validateVersion) { public void commit(boolean validateVersion) {
if (mIsCreate) { if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) { if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
@ -458,7 +530,7 @@ public class SqlNote {
} }
if (mType == Notes.TYPE_NOTE) { if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) { for (SqlData sqlData : mDataList) {//直接使用sqldata中的实现
sqlData.commit(mId, false, -1); sqlData.commit(mId, false, -1);
} }
} }
@ -470,14 +542,14 @@ public class SqlNote {
if (mDiffNoteValues.size() > 0) { if (mDiffNoteValues.size() > 0) {
mVersion ++; mVersion ++;
int result = 0; int result = 0;
if (!validateVersion) { if (!validateVersion) {//构造字符串
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?)", new String[] { + NoteColumns.ID + "=?)", new String[] {
String.valueOf(mId) String.valueOf(mId)
}); });
} else { } else {
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)", + NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)",
new String[] { new String[] {
String.valueOf(mId), String.valueOf(mVersion) String.valueOf(mId), String.valueOf(mVersion)
}); });
@ -502,4 +574,4 @@ public class SqlNote {
mDiffNoteValues.clear(); mDiffNoteValues.clear();
mIsCreate = false; mIsCreate = false;
} }
} }

@ -1,56 +1,24 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Task extends Node { public class Task extends Node {
private static final String TAG = Task.class.getSimpleName(); private static final String TAG = Task.class.getSimpleName();
private boolean mCompleted; private boolean mCompleted;//是否完成
private String mNotes; private String mNotes;
private JSONObject mMetaInfo; private JSONObject mMetaInfo;//将在实例中存储数据的类型
private Task mPriorSibling; private Task mPriorSibling;//对应的优先兄弟Task的指针待完善
private TaskList mParent; private TaskList mParent;//所在的任务列表的指针
public Task() { public Task() {
super(); super();
mCompleted = false; mCompleted = false;
mNotes = null; mNotes = null;
mPriorSibling = null; mPriorSibling = null;//TaskList中当前Task前面的Task的指针
mParent = null; mParent = null;//当前Task所在的TaskList
mMetaInfo = null; mMetaInfo = null;
} }
@ -80,14 +48,18 @@ public class Task extends Node {
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
// parent_id // parent_id
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid()); if (mParent!= null) {
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
}
// dest_parent_type // dest_parent_type
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE, js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP); GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
// list_id // list_id
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid()); if (mParent!= null) {
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
}
// prior_sibling_id // prior_sibling_id
if (mPriorSibling != null) { if (mPriorSibling != null) {
@ -175,7 +147,7 @@ public class Task extends Node {
} }
} }
public void setContentByLocalJSON(JSONObject js) { public void setContentByLocalJSON(JSONObject js) { //<2F><>metadata<74><61><EFBFBD><EFBFBD>ʵʩ
if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE) if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)
|| !js.has(GTaskStringUtils.META_HEAD_DATA)) { || !js.has(GTaskStringUtils.META_HEAD_DATA)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
@ -348,4 +320,4 @@ public class Task extends Node {
return this.mParent; return this.mParent;
} }
} }

@ -1,41 +1,11 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.gtask.data; package net.micode.notes.gtask.data;
import android.database.Cursor;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class TaskList extends Node { public class TaskList extends Node {
private static final String TAG = TaskList.class.getSimpleName(); private static final String TAG = TaskList.class.getSimpleName();//tag标记
private int mIndex; private int mIndex;//当前TaskList的指针
private ArrayList<Task> mChildren; private ArrayList<Task> mChildren;//类中主要的保存数据的单元用来实现一个以Task为元素的ArrayList
public TaskList() { public TaskList() {
super(); super();
@ -43,6 +13,10 @@ public class TaskList extends Node {
mIndex = 1; mIndex = 1;
} }
/* (non-Javadoc)
* @see net.micode.notes.gtask.data.Node#getCreateAction(int)
* JSONObject
*/
public JSONObject getCreateAction(int actionId) { public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
@ -58,7 +32,7 @@ public class TaskList extends Node {
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// entity_delta // entity_delta
JSONObject entity = new JSONObject(); JSONObject entity = new JSONObject();//entity实体
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
@ -74,6 +48,10 @@ public class TaskList extends Node {
return js; return js;
} }
/* (non-Javadoc)
* @see net.micode.notes.gtask.data.Node#getUpdateAction(int)
* JSONObject
*/
public JSONObject getUpdateAction(int actionId) { public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject(); JSONObject js = new JSONObject();
@ -216,10 +194,19 @@ public class TaskList extends Node {
return SYNC_ACTION_ERROR; return SYNC_ACTION_ERROR;
} }
/**
* @return
* TaskListmChildren
*/
public int getChildTaskCount() { public int getChildTaskCount() {
return mChildren.size(); return mChildren.size();
} }
/**
* @param task
* @return
*
*/
public boolean addChildTask(Task task) { public boolean addChildTask(Task task) {
boolean ret = false; boolean ret = false;
if (task != null && !mChildren.contains(task)) { if (task != null && !mChildren.contains(task)) {
@ -229,11 +216,19 @@ public class TaskList extends Node {
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren task.setPriorSibling(mChildren.isEmpty() ? null : mChildren
.get(mChildren.size() - 1)); .get(mChildren.size() - 1));
task.setParent(this); task.setParent(this);
//注意每一次ArrayList的变化都要紧跟相关Task中PriorSibling的更改
//,接下来几个函数都有相关操作
} }
} }
return ret; return ret;
} }
/**
* @param task
* @param index
* @return
*
*/
public boolean addChildTask(Task task, int index) { public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) { if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index"); Log.e(TAG, "add child task: invalid index");
@ -260,6 +255,11 @@ public class TaskList extends Node {
return true; return true;
} }
/**
* @param task
* @return
* TaskListTask
*/
public boolean removeChildTask(Task task) { public boolean removeChildTask(Task task) {
boolean ret = false; boolean ret = false;
int index = mChildren.indexOf(task); int index = mChildren.indexOf(task);
@ -281,6 +281,12 @@ public class TaskList extends Node {
return ret; return ret;
} }
/**
* @param task
* @param index
* @return
* TaskListTaskindex
*/
public boolean moveChildTask(Task task, int index) { public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) { if (index < 0 || index >= mChildren.size()) {
@ -297,8 +303,14 @@ public class TaskList extends Node {
if (pos == index) if (pos == index)
return true; return true;
return (removeChildTask(task) && addChildTask(task, index)); return (removeChildTask(task) && addChildTask(task, index));
//利用已实现好的功能完成当下功能;
} }
/**
* @param gid
* @return
* gidTask
*/
public Task findChildTaskByGid(String gid) { public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) { for (int i = 0; i < mChildren.size(); i++) {
Task t = mChildren.get(i); Task t = mChildren.get(i);
@ -309,10 +321,20 @@ public class TaskList extends Node {
return null; return null;
} }
/**
* @param task
* @return
* Taskindex
*/
public int getChildTaskIndex(Task task) { public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task); return mChildren.indexOf(task);
} }
/**
* @param index
* @return
* indexTask
*/
public Task getChildTaskByIndex(int index) { public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) { if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index"); Log.e(TAG, "getTaskByIndex: invalid index");
@ -321,8 +343,13 @@ public class TaskList extends Node {
return mChildren.get(index); return mChildren.get(index);
} }
/**
* @param gid
* @return
* gidTask
*/
public Task getChilTaskByGid(String gid) { public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) { for (Task task : mChildren) {//一种常见的ArrayList的遍历方法四种见精读笔记
if (task.getGid().equals(gid)) if (task.getGid().equals(gid))
return task; return task;
} }
@ -340,4 +367,4 @@ public class TaskList extends Node {
public int getIndex() { public int getIndex() {
return this.mIndex; return this.mIndex;
} }
} }

@ -1,28 +1,27 @@
/* /*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * Description便
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package net.micode.notes.gtask.exception; package net.micode.notes.gtask.exception;
public class ActionFailureException extends RuntimeException { public class ActionFailureException extends RuntimeException {
private static final long serialVersionUID = 4425249765923293627L; private static final long serialVersionUID = 4425249765923293627L;
/*
* serialVersionUIDjava
* serialVersionUID
* Made By Cuican
*/
public ActionFailureException() { public ActionFailureException() {
super(); super();
} }
/*
* JAVA使superthis.
* new
* 使super
* super()super (paramString)Exception ()Exception (paramString)
* Made By Cuican
*/
public ActionFailureException(String paramString) { public ActionFailureException(String paramString) {
super(paramString); super(paramString);
} }
@ -30,4 +29,4 @@ public class ActionFailureException extends RuntimeException {
public ActionFailureException(String paramString, Throwable paramThrowable) { public ActionFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable); super(paramString, paramThrowable);
} }
} }

@ -1,28 +1,28 @@
/* /*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * Description便
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package net.micode.notes.gtask.exception; package net.micode.notes.gtask.exception;
public class NetworkFailureException extends Exception { public class NetworkFailureException extends Exception {
private static final long serialVersionUID = 2107610287180234136L; private static final long serialVersionUID = 2107610287180234136L;
/*
* serialVersionUIDjava
* serialVersionUID
* Made By Cuican
*/
public NetworkFailureException() { public NetworkFailureException() {
super(); super();
} }
/*
* JAVA使superthis.
* new
* 使super
* super()super (paramString)Exception ()Exception (paramString)
* Made By Cuican
*/
public NetworkFailureException(String paramString) { public NetworkFailureException(String paramString) {
super(paramString); super(paramString);
} }
@ -30,4 +30,4 @@ public class NetworkFailureException extends Exception {
public NetworkFailureException(String paramString, Throwable paramThrowable) { public NetworkFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable); super(paramString, paramThrowable);
} }
} }

@ -1,36 +1,15 @@
/*
* 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; package net.micode.notes.gtask.remote;
import android.app.Notification; /*GTask
import android.app.NotificationManager; *
import android.app.PendingIntent; * private void showNotification(int tickerId, String content)
import android.content.Context; * protected Integer doInBackground(Void... unused) 线
import android.content.Intent; * protected void onProgressUpdate(String... progress) 使 线
import android.os.AsyncTask; * protected void onPostExecute(Integer result) Handler UI使doInBackground UI
*/
import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> { public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235; private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
public interface OnCompleteListener { public interface OnCompleteListener {
@ -57,52 +36,52 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
mTaskManager.cancelSync(); mTaskManager.cancelSync();
} }
public void publishProgess(String message) { public void publishProgess(String message) { // 发布进度单位系统将会调用onProgressUpdate()方法更新这些值
publishProgress(new String[] { publishProgress(new String[] {
message message
}); });
} }
private void showNotification(int tickerId, String content) { private void showNotification(int tickerId, String content) {
Notification notification = new Notification(R.drawable.notification, mContext Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis()); .getString(tickerId), System.currentTimeMillis());
notification.defaults = Notification.DEFAULT_LIGHTS; notification.defaults = Notification.DEFAULT_LIGHTS; // 调用系统自带灯光
notification.flags = Notification.FLAG_AUTO_CANCEL; notification.flags = Notification.FLAG_AUTO_CANCEL; // 点击清除按钮或点击通知后会自动消失
PendingIntent pendingIntent; PendingIntent pendingIntent; //一个描述了想要启动一个Activity、Broadcast或是Service的意图
if (tickerId != R.string.ticker_success) { if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0); NotesPreferenceActivity.class), 0); //如果同步不成功那么从系统取得一个用于启动一个NotesPreferenceActivity的PendingIntent对象
} else { } else {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0); NotesListActivity.class), 0); //如果同步成功那么从系统取得一个用于启动一个NotesListActivity的PendingIntent对象
} }
notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content, notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
pendingIntent); pendingIntent);
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);//通过NotificationManager对象的notify方法来执行一个notification的消息
} }
@Override @Override
protected Integer doInBackground(Void... unused) { protected Integer doInBackground(Void... unused) {
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
.getSyncAccountName(mContext))); .getSyncAccountName(mContext))); //利用getString,将把 NotesPreferenceActivity.getSyncAccountName(mContext))的字符串内容传进sync_progress_login中
return mTaskManager.sync(mContext, this); return mTaskManager.sync(mContext, this); //进行后台同步具体操作
} }
@Override @Override
protected void onProgressUpdate(String... progress) { protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]); showNotification(R.string.ticker_syncing, progress[0]);
if (mContext instanceof GTaskSyncService) { if (mContext instanceof GTaskSyncService) { //instanceof 判断mContext是否是GTaskSyncService的实例
((GTaskSyncService) mContext).sendBroadcast(progress[0]); ((GTaskSyncService) mContext).sendBroadcast(progress[0]);
} }
} }
@Override @Override
protected void onPostExecute(Integer result) { protected void onPostExecute(Integer result) { //用于在执行完后台任务后更新UI,显示结果
if (result == GTaskManager.STATE_SUCCESS) { if (result == GTaskManager.STATE_SUCCESS) {
showNotification(R.string.ticker_success, mContext.getString( showNotification(R.string.ticker_success, mContext.getString(
R.string.success_sync_account, mTaskManager.getSyncAccount())); R.string.success_sync_account, mTaskManager.getSyncAccount()));
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis()); NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis()); //设置最新同步的时间
} else if (result == GTaskManager.STATE_NETWORK_ERROR) { } else if (result == GTaskManager.STATE_NETWORK_ERROR) {
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network)); showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network));
} else if (result == GTaskManager.STATE_INTERNAL_ERROR) { } else if (result == GTaskManager.STATE_INTERNAL_ERROR) {
@ -110,14 +89,14 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
} else if (result == GTaskManager.STATE_SYNC_CANCELLED) { } else if (result == GTaskManager.STATE_SYNC_CANCELLED) {
showNotification(R.string.ticker_cancel, mContext showNotification(R.string.ticker_cancel, mContext
.getString(R.string.error_sync_cancelled)); .getString(R.string.error_sync_cancelled));
} } //几种不同情况下的结果显示
if (mOnCompleteListener != null) { if (mOnCompleteListener != null) {
new Thread(new Runnable() { new Thread(new Runnable() { //这里好像是方法内的一个线程,但是并不太懂什么意思
public void run() { public void run() { //完成后的操作使用onComplete()将所有值都重新初始化,相当于完成一次操作
mOnCompleteListener.onComplete(); mOnCompleteListener.onComplete();
} }
}).start(); }).start();
} }
} }
} }

@ -1,70 +1,13 @@
/*
* 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; package net.micode.notes.gtask.remote;
import android.accounts.Account; /*
import android.accounts.AccountManager; * GTASKGTASK
import android.accounts.AccountManagerFuture; * 使accountManager JSONObject HttpParams authToken Gid
import android.app.Activity; */
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import net.micode.notes.gtask.data.Node;
import net.micode.notes.gtask.data.Task;
import net.micode.notes.gtask.data.TaskList;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.gtask.exception.NetworkFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import net.micode.notes.ui.NotesPreferenceActivity;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
public class GTaskClient { public class GTaskClient {
private static final String TAG = GTaskClient.class.getSimpleName(); private static final String TAG = GTaskClient.class.getSimpleName();
private static final String GTASK_URL = "https://mail.google.com/tasks/"; private static final String GTASK_URL = "https://mail.google.com/tasks/"; //这个是指定的URL
private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig"; private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig";
@ -102,6 +45,10 @@ public class GTaskClient {
mUpdateArray = null; mUpdateArray = null;
} }
/*
* 使 getInstance()
* mInstance
*/
public static synchronized GTaskClient getInstance() { public static synchronized GTaskClient getInstance() {
if (mInstance == null) { if (mInstance == null) {
mInstance = new GTaskClient(); mInstance = new GTaskClient();
@ -109,42 +56,50 @@ public class GTaskClient {
return mInstance; return mInstance;
} }
/*Activity
*
* 使URL使URL
* truefalse
*/
public boolean login(Activity activity) { public boolean login(Activity activity) {
// we suppose that the cookie would expire after 5 minutes // we suppose that the cookie would expire after 5 minutes
// then we need to re-login // then we need to re-login
//判断距离最后一次登录操作是否超过5分钟
final long interval = 1000 * 60 * 5; final long interval = 1000 * 60 * 5;
if (mLastLoginTime + interval < System.currentTimeMillis()) { if (mLastLoginTime + interval < System.currentTimeMillis()) {
mLoggedin = false; mLoggedin = false;
} }
// need to re-login after account switch // need to re-login after account switch 重新登录操作
if (mLoggedin if (mLoggedin
&& !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity
.getSyncAccountName(activity))) { .getSyncAccountName(activity))) {
mLoggedin = false; mLoggedin = false;
} }
//如果没超过时间,则不需要重新登录
if (mLoggedin) { if (mLoggedin) {
Log.d(TAG, "already logged in"); Log.d(TAG, "already logged in");
return true; return true;
} }
mLastLoginTime = System.currentTimeMillis(); mLastLoginTime = System.currentTimeMillis();//更新最后登录时间,改为系统当前的时间
String authToken = loginGoogleAccount(activity, false); String authToken = loginGoogleAccount(activity, false);//判断是否登录到谷歌账户
if (authToken == null) { if (authToken == null) {
Log.e(TAG, "login google account failed"); Log.e(TAG, "login google account failed");
return false; return false;
} }
// login with custom domain if necessary // login with custom domain if necessary
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase() //尝试使用用户自己的域名登录
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase() //将用户账号名改为统一格式(小写)后判断是否为一个谷歌账号地址
.endsWith("googlemail.com"))) { .endsWith("googlemail.com"))) {
StringBuilder url = new StringBuilder(GTASK_URL).append("a/"); StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
int index = mAccount.name.indexOf('@') + 1; int index = mAccount.name.indexOf('@') + 1;
String suffix = mAccount.name.substring(index); String suffix = mAccount.name.substring(index);
url.append(suffix + "/"); url.append(suffix + "/");
mGetUrl = url.toString() + "ig"; mGetUrl = url.toString() + "ig"; //设置用户对应的getUrl
mPostUrl = url.toString() + "r/ig"; mPostUrl = url.toString() + "r/ig"; //设置用户对应的postUrl
if (tryToLoginGtask(activity, authToken)) { if (tryToLoginGtask(activity, authToken)) {
mLoggedin = true; mLoggedin = true;
@ -152,6 +107,7 @@ public class GTaskClient {
} }
// try to login with google official url // try to login with google official url
//如果用户账户无法登录则使用谷歌官方的URI进行登录
if (!mLoggedin) { if (!mLoggedin) {
mGetUrl = GTASK_GET_URL; mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL; mPostUrl = GTASK_POST_URL;
@ -164,10 +120,15 @@ public class GTaskClient {
return true; return true;
} }
/*
* 使
* 使AccountManager
*
*/
private String loginGoogleAccount(Activity activity, boolean invalidateToken) { private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
String authToken; String authToken; //令牌,是登录操作保证安全性的一个方法
AccountManager accountManager = AccountManager.get(activity); AccountManager accountManager = AccountManager.get(activity);//AccountManager这个类给用户提供了集中注册账号的接口
Account[] accounts = accountManager.getAccountsByType("com.google"); Account[] accounts = accountManager.getAccountsByType("com.google");//获取全部以com.google结尾的account
if (accounts.length == 0) { if (accounts.length == 0) {
Log.e(TAG, "there is no available google account"); Log.e(TAG, "there is no available google account");
@ -176,6 +137,7 @@ public class GTaskClient {
String accountName = NotesPreferenceActivity.getSyncAccountName(activity); String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
Account account = null; Account account = null;
//遍历获得的accounts信息寻找已经记录过的账户信息
for (Account a : accounts) { for (Account a : accounts) {
if (a.name.equals(accountName)) { if (a.name.equals(accountName)) {
account = a; account = a;
@ -190,11 +152,13 @@ public class GTaskClient {
} }
// get the token now // get the token now
//获取选中账号的令牌
AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account, AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null); "goanna_mobile", null, activity, null, null);
try { try {
Bundle authTokenBundle = accountManagerFuture.getResult(); Bundle authTokenBundle = accountManagerFuture.getResult();
authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN); authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN);
//如果是invalidateToken那么需要调用invalidateAuthToken(String, String)方法废除这个无效token
if (invalidateToken) { if (invalidateToken) {
accountManager.invalidateAuthToken("com.google", authToken); accountManager.invalidateAuthToken("com.google", authToken);
loginGoogleAccount(activity, false); loginGoogleAccount(activity, false);
@ -207,10 +171,12 @@ public class GTaskClient {
return authToken; return authToken;
} }
//尝试登陆Gtask这只是一个预先判断令牌是否是有效以及是否能登上GTask的方法,而不是具体实现登陆的方法
private boolean tryToLoginGtask(Activity activity, String authToken) { private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) { if (!loginGtask(authToken)) {
// maybe the auth token is out of date, now let's invalidate the // maybe the auth token is out of authTokedate, now let's invalidate the
// token and try again // token and try again
//删除过一个无效的authToken申请一个新的后再次尝试登陆
authToken = loginGoogleAccount(activity, true); authToken = loginGoogleAccount(activity, true);
if (authToken == null) { if (authToken == null) {
Log.e(TAG, "login google account failed"); Log.e(TAG, "login google account failed");
@ -225,25 +191,27 @@ public class GTaskClient {
return true; return true;
} }
//实现登录GTask的具体操作
private boolean loginGtask(String authToken) { private boolean loginGtask(String authToken) {
int timeoutConnection = 10000; int timeoutConnection = 10000;
int timeoutSocket = 15000; int timeoutSocket = 15000; //socket是一种通信连接实现数据的交换的端口
HttpParams httpParameters = new BasicHttpParams(); HttpParams httpParameters = new BasicHttpParams(); //实例化一个新的HTTP参数类
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);//设置连接超时时间
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);//设置设置端口超时时间
mHttpClient = new DefaultHttpClient(httpParameters); mHttpClient = new DefaultHttpClient(httpParameters);
BasicCookieStore localBasicCookieStore = new BasicCookieStore(); BasicCookieStore localBasicCookieStore = new BasicCookieStore(); //设置本地cookie
mHttpClient.setCookieStore(localBasicCookieStore); mHttpClient.setCookieStore(localBasicCookieStore);
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false); HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false);
// login gtask // login gtask
try { try {
String loginUrl = mGetUrl + "?auth=" + authToken; String loginUrl = mGetUrl + "?auth=" + authToken; //设置登录的url
HttpGet httpGet = new HttpGet(loginUrl); HttpGet httpGet = new HttpGet(loginUrl); //通过登录的uri实例化网页上资源的查找
HttpResponse response = null; HttpResponse response = null;
response = mHttpClient.execute(httpGet); response = mHttpClient.execute(httpGet);
// get the cookie now // get the cookie now
//获取CookieStore里存放的cookie,看如果存有“GTL(不知道什么意思)”则说明有验证成功的有效的cookie
List<Cookie> cookies = mHttpClient.getCookieStore().getCookies(); List<Cookie> cookies = mHttpClient.getCookieStore().getCookies();
boolean hasAuthCookie = false; boolean hasAuthCookie = false;
for (Cookie cookie : cookies) { for (Cookie cookie : cookies) {
@ -256,6 +224,7 @@ public class GTaskClient {
} }
// get the client version // get the client version
//获取client的内容具体操作是在返回的Content中截取从_setup(开始到)}</script>中间的字符串内容也就是gtask_url的内容
String resString = getResponseContent(response.getEntity()); String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup("; String jsBegin = "_setup(";
String jsEnd = ")}</script>"; String jsEnd = ")}</script>";
@ -284,6 +253,10 @@ public class GTaskClient {
return mActionId++; return mActionId++;
} }
/*
* 使HttpPost
* httpPost
*/
private HttpPost createHttpPost() { private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl); HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
@ -291,24 +264,28 @@ public class GTaskClient {
return httpPost; return httpPost;
} }
/*URL
* 使getContentEncoding()
*
*/
private String getResponseContent(HttpEntity entity) throws IOException { private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null; String contentEncoding = null;
if (entity.getContentEncoding() != null) { if (entity.getContentEncoding() != null) {//通过URL得到HttpEntity对象如果不为空则使用getContent方法创建一个流将数据从网络都过来
contentEncoding = entity.getContentEncoding().getValue(); contentEncoding = entity.getContentEncoding().getValue();
Log.d(TAG, "encoding: " + contentEncoding); Log.d(TAG, "encoding: " + contentEncoding);
} }
InputStream input = entity.getContent(); InputStream input = entity.getContent();
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) { if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {//GZIP是使用DEFLATE进行压缩数据的另一个压缩库
input = new GZIPInputStream(entity.getContent()); input = new GZIPInputStream(entity.getContent());
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) { } else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {//DEFLATE是一个无专利的压缩算法它可以实现无损数据压缩
Inflater inflater = new Inflater(true); Inflater inflater = new Inflater(true);
input = new InflaterInputStream(entity.getContent(), inflater); input = new InflaterInputStream(entity.getContent(), inflater);
} }
try { try {
InputStreamReader isr = new InputStreamReader(input); InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr); BufferedReader br = new BufferedReader(isr);//是一个包装类,它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了时候,再读入内存,是为了提供读的效率而设计的
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
while (true) { while (true) {
@ -323,20 +300,28 @@ public class GTaskClient {
} }
} }
/*JSON
* jsonjs
* UrlEncodedFormEntity entityhttpPost.setEntity(entity)jshttpPost
* 使getResponseContent
* json
*/
private JSONObject postRequest(JSONObject js) throws NetworkFailureException { private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) { if (!mLoggedin) {//未登录
Log.e(TAG, "please login first"); Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in"); throw new ActionFailureException("not logged in");
} }
//实例化一个httpPost的对象用来向服务器传输数据在这里就是发送请求而请求的内容在js里
HttpPost httpPost = createHttpPost(); HttpPost httpPost = createHttpPost();
try { try {
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>(); LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
list.add(new BasicNameValuePair("r", js.toString())); list.add(new BasicNameValuePair("r", js.toString()));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8"); //UrlEncodedFormEntity()的形式比较单一,是普通的键值对
httpPost.setEntity(entity); httpPost.setEntity(entity);
// execute the post // execute the post
//执行这个请求
HttpResponse response = mHttpClient.execute(httpPost); HttpResponse response = mHttpClient.execute(httpPost);
String jsString = getResponseContent(response.getEntity()); String jsString = getResponseContent(response.getEntity());
return new JSONObject(jsString); return new JSONObject(jsString);
@ -360,6 +345,12 @@ public class GTaskClient {
} }
} }
/*
* .gtask.data.TaskTask
* jsonTask,jsPost
* postRequest
* 使task.setGidtasknew_ID
*/
public void createTask(Task task) throws NetworkFailureException { public void createTask(Task task) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
@ -386,6 +377,9 @@ public class GTaskClient {
} }
} }
/*
* createTasktasklistgid
*/
public void createTaskList(TaskList tasklist) throws NetworkFailureException { public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
@ -412,6 +406,11 @@ public class GTaskClient {
} }
} }
/*
*
* 使JSONObject使jsPost.putPutUpdateArrayClientVersion
* 使postRequestjspost,
*/
public void commitUpdate() throws NetworkFailureException { public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) { if (mUpdateArray != null) {
try { try {
@ -433,6 +432,10 @@ public class GTaskClient {
} }
} }
/*
*
* commitUpdate()
*/
public void addUpdateNode(Node node) throws NetworkFailureException { public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) { if (node != null) {
// too many update items may result in an error // too many update items may result in an error
@ -447,6 +450,12 @@ public class GTaskClient {
} }
} }
/*
* task,tasktask
* getGidtaskgid
* JSONObject.put(String name, Object value)task
* postRequest
*/
public void moveTask(Task task, TaskList preParent, TaskList curParent) public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException { throws NetworkFailureException {
commitUpdate(); commitUpdate();
@ -463,15 +472,17 @@ public class GTaskClient {
if (preParent == curParent && task.getPriorSibling() != null) { if (preParent == curParent && task.getPriorSibling() != null) {
// put prioring_sibing_id only if moving within the tasklist and // put prioring_sibing_id only if moving within the tasklist and
// it is not the first one // it is not the first one
//设置优先级ID只有当移动是发生在文件中
action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling()); action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling());
} }
action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid()); action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid()); //设置移动前所属列表
action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid()); //设置当前所属列表
if (preParent != curParent) { if (preParent != curParent) {
// put the dest_list only if moving between tasklists // put the dest_list only if moving between tasklists
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid()); action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());
} }
actionList.put(action); actionList.put(action);
//最后将ACTION_LIST加入到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version // client_version
@ -486,6 +497,11 @@ public class GTaskClient {
} }
} }
/*
*
* JSON
* 使postRequest
*/
public void deleteNode(Node node) throws NetworkFailureException { public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
@ -494,7 +510,7 @@ public class GTaskClient {
// action_list // action_list
node.setDeleted(true); node.setDeleted(true);
actionList.put(node.getUpdateAction(getActionId())); actionList.put(node.getUpdateAction(getActionId())); //这里会获取到删除操作的ID加入到actionLiast中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version // client_version
@ -509,6 +525,11 @@ public class GTaskClient {
} }
} }
/*
*
* GetURI使getResponseContent
* "_setup(")}</script>GTASK_JSON_LISTS
*/
public JSONArray getTaskLists() throws NetworkFailureException { public JSONArray getTaskLists() throws NetworkFailureException {
if (!mLoggedin) { if (!mLoggedin) {
Log.e(TAG, "please login first"); Log.e(TAG, "please login first");
@ -521,6 +542,7 @@ public class GTaskClient {
response = mHttpClient.execute(httpGet); response = mHttpClient.execute(httpGet);
// get the task list // get the task list
//筛选工作把筛选出的字符串放入jsString
String resString = getResponseContent(response.getEntity()); String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup("; String jsBegin = "_setup(";
String jsEnd = ")}</script>"; String jsEnd = ")}</script>";
@ -531,6 +553,7 @@ public class GTaskClient {
jsString = resString.substring(begin + jsBegin.length(), end); jsString = resString.substring(begin + jsBegin.length(), end);
} }
JSONObject js = new JSONObject(jsString); JSONObject js = new JSONObject(jsString);
//获取GTASK_JSON_LISTS
return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS); return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS);
} catch (ClientProtocolException e) { } catch (ClientProtocolException e) {
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
@ -547,6 +570,9 @@ public class GTaskClient {
} }
} }
/*
* TASKListgid,
*/
public JSONArray getTaskList(String listGid) throws NetworkFailureException { public JSONArray getTaskList(String listGid) throws NetworkFailureException {
commitUpdate(); commitUpdate();
try { try {
@ -558,7 +584,7 @@ public class GTaskClient {
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL); GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId()); action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid); action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid); //这里设置为传入的listGid
action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false); action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false);
actionList.put(action); actionList.put(action);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList); jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
@ -579,7 +605,8 @@ public class GTaskClient {
return mAccount; return mAccount;
} }
//重置更新的内容
public void resetUpdateArray() { public void resetUpdateArray() {
mUpdateArray = null; mUpdateArray = null;
} }
} }

@ -1,119 +1,73 @@
/*
* 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; 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 { public class GTaskManager {
private static final String TAG = GTaskManager.class.getSimpleName(); private static final String TAG = GTaskManager.class.getSimpleName();
public static final int STATE_SUCCESS = 0; public static final int STATE_SUCCESS = 0;
public static final int STATE_NETWORK_ERROR = 1; public static final int STATE_NETWORK_ERROR = 1;
public static final int STATE_INTERNAL_ERROR = 2; public static final int STATE_INTERNAL_ERROR = 2;
public static final int STATE_SYNC_IN_PROGRESS = 3; public static final int STATE_SYNC_IN_PROGRESS = 3;
public static final int STATE_SYNC_CANCELLED = 4; public static final int STATE_SYNC_CANCELLED = 4;
private static GTaskManager mInstance = null; private static GTaskManager mInstance = null;
private Activity mActivity; private Activity mActivity;
private Context mContext; private Context mContext;
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
private boolean mSyncing; private boolean mSyncing;
private boolean mCancelled; private boolean mCancelled;
private HashMap<String, TaskList> mGTaskListHashMap; private HashMap<String, TaskList> mGTaskListHashMap;
private HashMap<String, Node> mGTaskHashMap; private HashMap<String, Node> mGTaskHashMap;
private HashMap<String, MetaData> mMetaHashMap; private HashMap<String, MetaData> mMetaHashMap;
private TaskList mMetaList; private TaskList mMetaList;
private HashSet<Long> mLocalDeleteIdMap; private HashSet<Long> mLocalDeleteIdMap;
private HashMap<String, Long> mGidToNid; private HashMap<String, Long> mGidToNid;
private HashMap<Long, String> mNidToGid; private HashMap<Long, String> mNidToGid;
private GTaskManager() { private GTaskManager() { //对象初始化函数
mSyncing = false; mSyncing = false; //正在同步,flase代表未执行
mCancelled = false; mCancelled = false; //全局标识flase代表可以执行
mGTaskListHashMap = new HashMap<String, TaskList>(); mGTaskListHashMap = new HashMap<String, TaskList>(); //<>代表Java的泛型,就是创建一个用类型作为参数的类。
mGTaskHashMap = new HashMap<String, Node>(); mGTaskHashMap = new HashMap<String, Node>();
mMetaHashMap = new HashMap<String, MetaData>(); mMetaHashMap = new HashMap<String, MetaData>();
mMetaList = null; mMetaList = null;
mLocalDeleteIdMap = new HashSet<Long>(); mLocalDeleteIdMap = new HashSet<Long>();
mGidToNid = new HashMap<String, Long>(); mGidToNid = new HashMap<String, Long>(); //GoogleID to NodeID??
mNidToGid = new HashMap<Long, String>(); mNidToGid = new HashMap<Long, String>(); //NodeID to GoogleID???通过hashmap散列表建立映射
} }
public static synchronized GTaskManager getInstance() { /**
* synchronized线
*
* @author TTS
* @return GtaskManger
*/
public static synchronized GTaskManager getInstance() { //可能运行在多线程环境下,使用语言级同步--synchronized
if (mInstance == null) { if (mInstance == null) {
mInstance = new GTaskManager(); mInstance = new GTaskManager();
} }
return mInstance; return mInstance;
} }
/**
* synchronized线
* @author TTS
* @param activity
*/
public synchronized void setActivityContext(Activity activity) { public synchronized void setActivityContext(Activity activity) {
// used for getting authtoken // used for getting auth token
mActivity = activity; mActivity = activity;
} }
public int sync(Context context, GTaskASyncTask asyncTask) { /**
*
*
* @author TTS
* @param context-----
* @param asyncTask-------
* @return int
*/
public int sync(Context context, GTaskASyncTask asyncTask) { //核心函数
if (mSyncing) { if (mSyncing) {
Log.d(TAG, "Sync is in progress"); Log.d(TAG, "Sync is in progress"); //创建日志文件调试信息debug
return STATE_SYNC_IN_PROGRESS; return STATE_SYNC_IN_PROGRESS;
} }
mContext = context; mContext = context;
@ -128,8 +82,8 @@ public class GTaskManager {
mNidToGid.clear(); mNidToGid.clear();
try { try {
GTaskClient client = GTaskClient.getInstance(); GTaskClient client = GTaskClient.getInstance(); //getInstance即为创建一个实例,client--客户机
client.resetUpdateArray(); client.resetUpdateArray(); //JSONArray类型reset即置为NULL
// login google task // login google task
if (!mCancelled) { if (!mCancelled) {
@ -140,15 +94,15 @@ public class GTaskManager {
// get the task list from google // get the task list from google
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list)); asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list));
initGTaskList(); initGTaskList(); //获取Google上的JSONtasklist转为本地TaskList
// do content sync work // do content sync work
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing)); asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing));
syncContent(); syncContent();
} catch (NetworkFailureException e) { } catch (NetworkFailureException e) { //分为两种异常,此类异常为网络异常
Log.e(TAG, e.toString()); Log.e(TAG, e.toString()); //创建日志文件调试信息error
return STATE_NETWORK_ERROR; return STATE_NETWORK_ERROR;
} catch (ActionFailureException e) { } catch (ActionFailureException e) { //此类异常为操作异常
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
return STATE_INTERNAL_ERROR; return STATE_INTERNAL_ERROR;
} catch (Exception e) { } catch (Exception e) {
@ -168,32 +122,41 @@ public class GTaskManager {
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
} }
/**
*GtaskListGoogleJSONtasklistTaskList
*mMetaListmGTaskListHashMapmGTaskHashMap
*@author TTS
*@exception NetworkFailureException
*@return void
*/
private void initGTaskList() throws NetworkFailureException { private void initGTaskList() throws NetworkFailureException {
if (mCancelled) if (mCancelled)
return; return;
GTaskClient client = GTaskClient.getInstance(); GTaskClient client = GTaskClient.getInstance(); //getInstance即为创建一个实例client应指远端客户机
try { try {
JSONArray jsTaskLists = client.getTaskLists(); //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 // init meta list first
mMetaList = null; mMetaList = null; //TaskList类型
for (int i = 0; i < jsTaskLists.length(); i++) { for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i); JSONObject object = jsTaskLists.getJSONObject(i); //JSONObject与JSONArray一个为对象一个为数组。此处取出单个JASONObject
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);
if (name if (name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {
.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { mMetaList = new TaskList(); //MetaList意为元表,Tasklist类型此处为初始化
mMetaList = new TaskList(); mMetaList.setContentByRemoteJSON(object); //将JSON中部分数据复制到自己定义的对象中相对应的数据name->mname...
mMetaList.setContentByRemoteJSON(object);
// load meta data // load meta data
JSONArray jsMetas = client.getTaskList(gid); JSONArray jsMetas = client.getTaskList(gid); //原注释为get action_list------list
for (int j = 0; j < jsMetas.length(); j++) { for (int j = 0; j < jsMetas.length(); j++) {
object = (JSONObject) jsMetas.getJSONObject(j); object = (JSONObject) jsMetas.getJSONObject(j);
MetaData metaData = new MetaData(); MetaData metaData = new MetaData(); //继承自Node
metaData.setContentByRemoteJSON(object); metaData.setContentByRemoteJSON(object);
if (metaData.isWorthSaving()) { if (metaData.isWorthSaving()) { //if not worth to savemetadata将不加入mMetaList
mMetaList.addChildTask(metaData); mMetaList.addChildTask(metaData);
if (metaData.getGid() != null) { if (metaData.getGid() != null) {
mMetaHashMap.put(metaData.getRelatedGid(), metaData); mMetaHashMap.put(metaData.getRelatedGid(), metaData);
@ -214,16 +177,16 @@ public class GTaskManager {
// init task list // init task list
for (int i = 0; i < jsTaskLists.length(); i++) { for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i); JSONObject object = jsTaskLists.getJSONObject(i);
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); //通过getString函数传入本地某个标志数据的名称获取其在远端的名称。
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);
if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)
&& !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX && !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX
+ GTaskStringUtils.FOLDER_META)) { + GTaskStringUtils.FOLDER_META)) {
TaskList tasklist = new TaskList(); TaskList tasklist = new TaskList(); //继承自Node
tasklist.setContentByRemoteJSON(object); tasklist.setContentByRemoteJSON(object);
mGTaskListHashMap.put(gid, tasklist); mGTaskListHashMap.put(gid, tasklist);
mGTaskHashMap.put(gid, tasklist); mGTaskHashMap.put(gid, tasklist); //为什么加两遍???
// load tasks // load tasks
JSONArray jsTasks = client.getTaskList(gid); JSONArray jsTasks = client.getTaskList(gid);
@ -247,13 +210,18 @@ public class GTaskManager {
} }
} }
private void syncContent() throws NetworkFailureException { /**
*
* @throws NetworkFailureException
* @return
*/
private void syncContent() throws NetworkFailureException { //本地内容同步操作
int syncType; int syncType;
Cursor c = null; Cursor c = null; //数据库指针
String gid; String gid; //GoogleID??
Node node; Node node; //Node包含Sync_Action的不同类型
mLocalDeleteIdMap.clear(); mLocalDeleteIdMap.clear(); //HashSet<Long>类型
if (mCancelled) { if (mCancelled) {
return; return;
@ -301,8 +269,8 @@ public class GTaskManager {
node = mGTaskHashMap.get(gid); node = mGTaskHashMap.get(gid);
if (node != null) { if (node != null) {
mGTaskHashMap.remove(gid); mGTaskHashMap.remove(gid);
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); //通过hashmap建立联系
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); //通过hashmap建立联系
syncType = node.getSyncAction(c); syncType = node.getSyncAction(c);
} else { } else {
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
@ -327,14 +295,14 @@ public class GTaskManager {
} }
// go through remaining items // go through remaining items
Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator(); Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator(); //Iterator迭代器
while (iter.hasNext()) { while (iter.hasNext()) {
Map.Entry<String, Node> entry = iter.next(); Map.Entry<String, Node> entry = iter.next();
node = entry.getValue(); node = entry.getValue();
doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null);
} }
// mCancelled can be set by another thread, so we neet to check one by // mCancelled can be set by another thread, so we neet to check one by //thread----线程
// one // one
// clear local delete table // clear local delete table
if (!mCancelled) { if (!mCancelled) {
@ -351,6 +319,11 @@ public class GTaskManager {
} }
/**
*
* @author TTS
* @throws NetworkFailureException
*/
private void syncFolder() throws NetworkFailureException { private void syncFolder() throws NetworkFailureException {
Cursor c = null; Cursor c = null;
String gid; String gid;
@ -394,7 +367,7 @@ public class GTaskManager {
try { try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)", c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)",
new String[] { new String[] {
String.valueOf(Notes.ID_CALL_RECORD_FOLDER) String.valueOf(Notes.ID_CALL_RECORD_FOLDER)
}, null); }, null);
if (c != null) { if (c != null) {
if (c.moveToNext()) { if (c.moveToNext()) {
@ -476,6 +449,14 @@ public class GTaskManager {
GTaskClient.getInstance().commitUpdate(); GTaskClient.getInstance().commitUpdate();
} }
/**
* syncTypeaddLocalNodeaddRemoteNodedeleteNodeupdateLocalNodeupdateRemoteNode
* @author TTS
* @param syncType
* @param node
* @param c
* @throws NetworkFailureException
*/
private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) { if (mCancelled) {
return; return;
@ -522,6 +503,12 @@ public class GTaskManager {
} }
} }
/**
* Node
* @author TTS
* @param node
* @throws NetworkFailureException
*/
private void addLocalNode(Node node) throws NetworkFailureException { private void addLocalNode(Node node) throws NetworkFailureException {
if (mCancelled) { if (mCancelled) {
return; return;
@ -596,6 +583,15 @@ public class GTaskManager {
updateRemoteMeta(node.getGid(), sqlNote); updateRemoteMeta(node.getGid(), sqlNote);
} }
/**
* updatenode
* @author TTS
* @param node
* ----
* @param c
* ----Cursor
* @throws NetworkFailureException
*/
private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) { if (mCancelled) {
return; return;
@ -619,12 +615,22 @@ public class GTaskManager {
updateRemoteMeta(node.getGid(), sqlNote); updateRemoteMeta(node.getGid(), sqlNote);
} }
/**
* Node
* updateRemoteMeta
* @author TTS
* @param node
* ----
* @param c
* --Cursor
* @throws NetworkFailureException
*/
private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException { private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) { if (mCancelled) {
return; return;
} }
SqlNote sqlNote = new SqlNote(mContext, c); SqlNote sqlNote = new SqlNote(mContext, c); //从本地mContext中获取内容
Node n; Node n;
// update remotely // update remotely
@ -634,11 +640,12 @@ public class GTaskManager {
String parentGid = mNidToGid.get(sqlNote.getParentId()); String parentGid = mNidToGid.get(sqlNote.getParentId());
if (parentGid == null) { if (parentGid == null) {
Log.e(TAG, "cannot find task's parent tasklist"); Log.e(TAG, "cannot find task's parent tasklist"); //调试信息
throw new ActionFailureException("cannot add remote task"); throw new ActionFailureException("cannot add remote task");
} }
mGTaskListHashMap.get(parentGid).addChildTask(task); mGTaskListHashMap.get(parentGid).addChildTask(task); //在本地生成的GTaskList中增加子结点
//登录远程服务器创建Task
GTaskClient.getInstance().createTask(task); GTaskClient.getInstance().createTask(task);
n = (Node) task; n = (Node) task;
@ -656,6 +663,7 @@ public class GTaskManager {
else else
folderName += sqlNote.getSnippet(); folderName += sqlNote.getSnippet();
//iterator迭代器通过统一的接口迭代所有的map元素
Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator(); Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
Map.Entry<String, TaskList> entry = iter.next(); Map.Entry<String, TaskList> entry = iter.next();
@ -687,11 +695,20 @@ public class GTaskManager {
sqlNote.resetLocalModified(); sqlNote.resetLocalModified();
sqlNote.commit(true); sqlNote.commit(true);
// gid-id mapping // gid-id mapping //创建id间的映射
mGidToNid.put(n.getGid(), sqlNote.getId()); mGidToNid.put(n.getGid(), sqlNote.getId());
mNidToGid.put(sqlNote.getId(), n.getGid()); mNidToGid.put(sqlNote.getId(), n.getGid());
} }
/**
* Nodemeta(updateRemoteMeta)
* @author TTS
* @param node
* ----
* @param c
* --Cursor
* @throws NetworkFailureException
*/
private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) { if (mCancelled) {
return; return;
@ -701,7 +718,7 @@ public class GTaskManager {
// update remotely // update remotely
node.setContentByLocalJSON(sqlNote.getContent()); node.setContentByLocalJSON(sqlNote.getContent());
GTaskClient.getInstance().addUpdateNode(node); GTaskClient.getInstance().addUpdateNode(node); //GTaskClient用途为从本地登陆远端服务器
// update meta // update meta
updateRemoteMeta(node.getGid(), sqlNote); updateRemoteMeta(node.getGid(), sqlNote);
@ -710,15 +727,19 @@ public class GTaskManager {
if (sqlNote.isNoteType()) { if (sqlNote.isNoteType()) {
Task task = (Task) node; Task task = (Task) node;
TaskList preParentList = task.getParent(); TaskList preParentList = task.getParent();
//preParentList为通过node获取的父节点列表
String curParentGid = mNidToGid.get(sqlNote.getParentId()); String curParentGid = mNidToGid.get(sqlNote.getParentId());
//curParentGid为通过光标在数据库中找到sqlNote的mParentId再通过mNidToGid由long类型转为String类型的Gid
if (curParentGid == null) { if (curParentGid == null) {
Log.e(TAG, "cannot find task's parent tasklist"); Log.e(TAG, "cannot find task's parent tasklist");
throw new ActionFailureException("cannot update remote task"); throw new ActionFailureException("cannot update remote task");
} }
TaskList curParentList = mGTaskListHashMap.get(curParentGid); TaskList curParentList = mGTaskListHashMap.get(curParentGid);
//通过HashMap找到对应Gid的TaskList
if (preParentList != curParentList) { if (preParentList != curParentList) { //?????????????
preParentList.removeChildTask(task); preParentList.removeChildTask(task);
curParentList.addChildTask(task); curParentList.addChildTask(task);
GTaskClient.getInstance().moveTask(task, preParentList, curParentList); GTaskClient.getInstance().moveTask(task, preParentList, curParentList);
@ -727,9 +748,19 @@ public class GTaskManager {
// clear local modified flag // clear local modified flag
sqlNote.resetLocalModified(); sqlNote.resetLocalModified();
//commit到本地数据库
sqlNote.commit(true); sqlNote.commit(true);
} }
/**
* meta meta----------
* @author TTS
* @param gid
* ---GoogleIDString
* @param sqlNote
* ---使SqlNote
* @throws NetworkFailureException
*/
private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException {
if (sqlNote != null && sqlNote.isNoteType()) { if (sqlNote != null && sqlNote.isNoteType()) {
MetaData metaData = mMetaHashMap.get(gid); MetaData metaData = mMetaHashMap.get(gid);
@ -746,12 +777,18 @@ public class GTaskManager {
} }
} }
/**
* syncID
* @author TTS
* @return void
* @throws NetworkFailureException
*/
private void refreshLocalSyncId() throws NetworkFailureException { private void refreshLocalSyncId() throws NetworkFailureException {
if (mCancelled) { if (mCancelled) {
return; return;
} }
// get the latest gtask list // get the latest gtask list //获取最近的最晚的gtask list
mGTaskHashMap.clear(); mGTaskHashMap.clear();
mGTaskListHashMap.clear(); mGTaskListHashMap.clear();
mMetaHashMap.clear(); mMetaHashMap.clear();
@ -762,16 +799,16 @@ public class GTaskManager {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type<>? AND parent_id<>?)", new String[] { "(type<>? AND parent_id<>?)", new String[] {
String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER) String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)
}, NoteColumns.TYPE + " DESC"); }, NoteColumns.TYPE + " DESC"); //query语句五个参数NoteColumns.TYPE + " DESC"-----为按类型递减顺序返回查询结果。new String[] {String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)}------为选择参数。"(type<>? AND parent_id<>?)"-------指明返回行过滤器。SqlNote.PROJECTION_NOTE--------应返回的数据列的名字。Notes.CONTENT_NOTE_URI--------contentProvider包含所有数据集所对应的uri
if (c != null) { if (c != null) {
while (c.moveToNext()) { while (c.moveToNext()) {
String gid = c.getString(SqlNote.GTASK_ID_COLUMN); String gid = c.getString(SqlNote.GTASK_ID_COLUMN);
Node node = mGTaskHashMap.get(gid); Node node = mGTaskHashMap.get(gid);
if (node != null) { if (node != null) {
mGTaskHashMap.remove(gid); mGTaskHashMap.remove(gid);
ContentValues values = new ContentValues(); ContentValues values = new ContentValues(); //在ContentValues中创建键值对。准备通过contentResolver写入数据
values.put(NoteColumns.SYNC_ID, node.getLastModified()); values.put(NoteColumns.SYNC_ID, node.getLastModified());
mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, //进行批量更改选择参数为NULL应该可以用insert替换参数分别为表名和需要更新的value对象。
c.getLong(SqlNote.ID_COLUMN)), values, null, null); c.getLong(SqlNote.ID_COLUMN)), values, null, null);
} else { } else {
Log.e(TAG, "something is missed"); Log.e(TAG, "something is missed");
@ -790,11 +827,20 @@ public class GTaskManager {
} }
} }
/**
* ,mAccount.name
* @author TTS
* @return String
*/
public String getSyncAccount() { public String getSyncAccount() {
return GTaskClient.getInstance().getSyncAccount().name; return GTaskClient.getInstance().getSyncAccount().name;
} }
/**
* mCancelledtrue
* @author TTS
*/
public void cancelSync() { public void cancelSync() {
mCancelled = true; mCancelled = true;
} }
} }

@ -1,27 +1,20 @@
/*
* 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; package net.micode.notes.gtask.remote;
import android.app.Activity; /*
import android.app.Service; * Service
import android.content.Context; *
import android.content.Intent; * private void startSync()
import android.os.Bundle; * private void cancelSync()
import android.os.IBinder; * public void onCreate()
* public int onStartCommand(Intent intent, int flags, int startId) serviceserviceservice
* public void onLowMemory() serviceservice
* public IBinder onBind()
* public void sendBroadcast(String msg)
* public static void startSync(Activity activity)
* public static void cancelSync(Context context)
* public static boolean isSyncing()
* public static String getProgressString()
*/
public class GTaskSyncService extends Service { public class GTaskSyncService extends Service {
public final static String ACTION_STRING_NAME = "sync_action_type"; public final static String ACTION_STRING_NAME = "sync_action_type";
@ -42,6 +35,7 @@ public class GTaskSyncService extends Service {
private static String mSyncProgress = ""; private static String mSyncProgress = "";
//开始一个同步的工作
private void startSync() { private void startSync() {
if (mSyncTask == null) { if (mSyncTask == null) {
mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() { mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
@ -52,10 +46,11 @@ public class GTaskSyncService extends Service {
} }
}); });
sendBroadcast(""); sendBroadcast("");
mSyncTask.execute(); mSyncTask.execute(); //这个函数让任务是以单线程队列方式或线程池队列方式运行
} }
} }
private void cancelSync() { private void cancelSync() {
if (mSyncTask != null) { if (mSyncTask != null) {
mSyncTask.cancelSync(); mSyncTask.cancelSync();
@ -63,7 +58,7 @@ public class GTaskSyncService extends Service {
} }
@Override @Override
public void onCreate() { public void onCreate() { //初始化一个service
mSyncTask = null; mSyncTask = null;
} }
@ -72,6 +67,7 @@ public class GTaskSyncService extends Service {
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) { if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) { switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {
//两种情况,开始同步或者取消同步
case ACTION_START_SYNC: case ACTION_START_SYNC:
startSync(); startSync();
break; break;
@ -81,7 +77,7 @@ public class GTaskSyncService extends Service {
default: default:
break; break;
} }
return START_STICKY; return START_STICKY; //等待新的intent来是这个service继续运行
} }
return super.onStartCommand(intent, flags, startId); return super.onStartCommand(intent, flags, startId);
} }
@ -93,26 +89,26 @@ public class GTaskSyncService extends Service {
} }
} }
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) { //不知道干吗用的
return null; return null;
} }
public void sendBroadcast(String msg) { public void sendBroadcast(String msg) {
mSyncProgress = msg; mSyncProgress = msg;
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME); //创建一个新的Intent
intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null); intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null); //附加INTENT中的相应参数的值
intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg); intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg);
sendBroadcast(intent); sendBroadcast(intent); //发送这个通知
} }
public static void startSync(Activity activity) { public static void startSync(Activity activity) {//执行一个serviceservice的内容里的同步动作就是开始同步
GTaskManager.getInstance().setActivityContext(activity); GTaskManager.getInstance().setActivityContext(activity);
Intent intent = new Intent(activity, GTaskSyncService.class); Intent intent = new Intent(activity, GTaskSyncService.class);
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC); intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC);
activity.startService(intent); activity.startService(intent);
} }
public static void cancelSync(Context context) { public static void cancelSync(Context context) {//执行一个serviceservice的内容里的同步动作就是取消同步
Intent intent = new Intent(context, GTaskSyncService.class); Intent intent = new Intent(context, GTaskSyncService.class);
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC); intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC);
context.startService(intent); context.startService(intent);
@ -125,4 +121,4 @@ public class GTaskSyncService extends Service {
public static String getProgressString() { public static String getProgressString() {
return mSyncProgress; return mSyncProgress;
} }
} }

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#88555555" />
<item android:state_selected="true" android:color="#ff999999" />
<item android:color="#ff000000" />
</selector>

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#50000000" />
</selector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/new_note_pressed" />
<item
android:drawable="@drawable/new_note_normal" />
</selector>

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/account_dialog_title"
style="?android:attr/textAppearanceMedium"
android:singleLine="true"
android:ellipsize="end"
android:gravity="center"
android:layout_marginTop="-2.7dip"
android:layout_marginBottom="-2.7dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/account_dialog_subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:layout_marginBottom="1dip"
android:gravity="center"/>
</LinearLayout>

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dip"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/preferences_add_account" />
</LinearLayout>

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<NumberPicker
android:id="@+id/date"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
/>
<NumberPicker
android:id="@+id/hour"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
<NumberPicker
android:id="@+id/minute"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
<NumberPicker
android:id="@+id/amPm"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
</LinearLayout>

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<EditText
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/et_foler_name"
android:layout_width="fill_parent"
android:hint="@string/hint_foler_name"
android:layout_height="fill_parent" />

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="50dip" >
<TextView
android:id="@+id/tv_folder_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textAppearance="@style/TextAppearancePrimaryItem" />
</LinearLayout>

@ -1,400 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/list_background"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/note_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_modified_date"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="left|center_vertical"
android:layout_marginRight="8dip"
android:textAppearance="@style/TextAppearanceSecondaryItem" />
<ImageView
android:id="@+id/iv_alert_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@drawable/title_alert" />
<TextView
android:id="@+id/tv_alert_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="2dip"
android:layout_marginRight="8dip"
android:textAppearance="@style/TextAppearanceSecondaryItem" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_btn_set_color" />
</LinearLayout>
<LinearLayout
android:id="@+id/sv_note_edit"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ImageView
android:layout_width="fill_parent"
android:layout_height="7dip"
android:background="@drawable/bg_color_btn_mask" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:scrollbars="none"
android:overScrollMode="never"
android:layout_gravity="left|top"
android:fadingEdgeLength="0dip">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<net.micode.notes.ui.NoteEditText
android:id="@+id/note_edit_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="left|top"
android:background="@null"
android:autoLink="all"
android:linksClickable="false"
android:minLines="12"
android:textAppearance="@style/TextAppearancePrimaryItem"
android:lineSpacingMultiplier="1.2" />
<LinearLayout
android:id="@+id/note_edit_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="-10dip"
android:visibility="gone" />
</LinearLayout>
</ScrollView>
<ImageView
android:layout_width="fill_parent"
android:layout_height="7dip"
android:background="@drawable/bg_color_btn_mask" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/btn_set_bg_color"
android:layout_height="43dip"
android:layout_width="wrap_content"
android:background="@drawable/bg_color_btn_mask"
android:layout_gravity="top|right" />
<LinearLayout
android:id="@+id/note_bg_color_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/note_edit_color_selector_panel"
android:layout_marginTop="30dip"
android:layout_marginRight="8dip"
android:layout_gravity="top|right"
android:visibility="gone">
<FrameLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_bg_yellow"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_bg_yellow_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginRight="5dip"
android:focusable="false"
android:visibility="gone"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_bg_blue"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_bg_blue_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:layout_marginRight="3dip"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_bg_white"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_bg_white_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:layout_marginRight="2dip"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_bg_green"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_bg_green_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/iv_bg_red"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_bg_red_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:src="@drawable/selected" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/font_size_selector"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/font_size_selector_bg"
android:layout_gravity="bottom"
android:visibility="gone">
<FrameLayout
android:id="@+id/ll_font_small"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/font_small"
android:layout_marginBottom="5dip" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_font_small"
android:textAppearance="@style/TextAppearanceUnderMenuIcon" />
</LinearLayout>
<ImageView
android:id="@+id/iv_small_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginRight="6dip"
android:layout_marginBottom="-7dip"
android:focusable="false"
android:visibility="gone"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:id="@+id/ll_font_normal"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/font_normal"
android:layout_marginBottom="5dip" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_font_normal"
android:textAppearance="@style/TextAppearanceUnderMenuIcon" />
</LinearLayout>
<ImageView
android:id="@+id/iv_medium_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:layout_marginRight="6dip"
android:layout_marginBottom="-7dip"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:id="@+id/ll_font_large"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/font_large"
android:layout_marginBottom="5dip" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_font_large"
android:textAppearance="@style/TextAppearanceUnderMenuIcon" />
</LinearLayout>
<ImageView
android:id="@+id/iv_large_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:layout_marginRight="6dip"
android:layout_marginBottom="-7dip"
android:src="@drawable/selected" />
</FrameLayout>
<FrameLayout
android:id="@+id/ll_font_super"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/font_super"
android:layout_marginBottom="5dip" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/menu_font_super"
android:textAppearance="@style/TextAppearanceUnderMenuIcon" />
</LinearLayout>
<ImageView
android:id="@+id/iv_super_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:focusable="false"
android:visibility="gone"
android:layout_marginRight="6dip"
android:layout_marginBottom="-7dip"
android:src="@drawable/selected" />
</FrameLayout>
</LinearLayout>
</FrameLayout>

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/cb_edit_item"
android:layout_width="wrap_content"
android:layout_height="28dip"
android:checked="false"
android:focusable="false"
android:layout_gravity="top|left" />
<net.micode.notes.ui.NoteEditText
android:id="@+id/et_edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.2"
android:layout_gravity="center_vertical"
android:textAppearance="@style/TextAppearancePrimaryItem"
android:background="@null" />
</LinearLayout>

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/note_item"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="0dip"
android:layout_weight="1"
android:textAppearance="@style/TextAppearancePrimaryItem"
android:visibility="gone" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearanceSecondaryItem" />
</LinearLayout>
</LinearLayout>
<CheckBox
android:id="@android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false"
android:visibility="gone" />
</LinearLayout>
<ImageView
android:id="@+id/iv_alert_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"/>
</FrameLayout>

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/list_background">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/title_bar_bg"
android:visibility="gone"
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="#FFEAD1AE"
android:textSize="@dimen/text_font_size_medium" />
<ListView
android:id="@+id/notes_list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:cacheColorHint="@null"
android:listSelector="@android:color/transparent"
android:divider="@null"
android:fadingEdge="@null" />
</LinearLayout>
<Button
android:id="@+id/btn_new_note"
android:background="@drawable/new_note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:layout_gravity="bottom" />
</FrameLayout>

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/navigation_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button android:id="@+id/selection_menu"
android:divider="?android:attr/listDividerAlertDialog"
android:singleLine="true"
android:gravity="left|center_vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="?android:attr/borderlessButtonStyle" />
</LinearLayout>

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<View
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="100dip"
android:visibility="invisible"
android:focusable="false"
android:background="@drawable/list_footer_bg" />

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

Loading…
Cancel
Save