diff --git a/src/main/java/net/micode/notes/data/Contact.java b/src/main/java/net/micode/notes/data/Contact.java index d97ac5d..708ea9f 100644 --- a/src/main/java/net/micode/notes/data/Contact.java +++ b/src/main/java/net/micode/notes/data/Contact.java @@ -26,46 +26,49 @@ import android.util.Log; import java.util.HashMap; public class Contact { - private static HashMap sContactCache; - private static final String TAG = "Contact"; - + //联系人数据库 + /*hashmap是一系列的键-值队(以键查找值),hashmap的特点是:无序,键不重复 是泛型的概念,这里意思是,键是字符串,值也是字符串*/ + private static HashMap sContactCache;//创建实体类来存储所写联系人信息 + private static final String TAG = "Contact";//定义该类的名称 private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + " AND " + Data.RAW_CONTACT_ID + " IN " + "(SELECT raw_contact_id " + " FROM phone_lookup" - + " WHERE min_match = '+')"; - + + " WHERE min_match = '+')";//在数据库中查找电话号码 public static String getContact(Context context, String phoneNumber) { if(sContactCache == null) { + //创建实体类缓存列表 sContactCache = new HashMap(); } - if(sContactCache.containsKey(phoneNumber)) { + //如果在数据库中包含此键值则返回电话号码 return sContactCache.get(phoneNumber); } - + //toCallerIDMinMatch是安卓自带的号码匹配工具,截取查询号码的后7位作为匹配依据 String selection = CALLER_ID_SELECTION.replace("+", PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); + //cursor类是对数据库的操作,获取整行的数据,从数据库中查询联系人内容 Cursor cursor = context.getContentResolver().query( - Data.CONTENT_URI, + Data.CONTENT_URI,//数据储存的地址 new String [] { Phone.DISPLAY_NAME }, selection, new String[] { phoneNumber }, null); - if (cursor != null && cursor.moveToFirst()) { + //若数据库存在,则游标移动到游标所表示的信息元组的第一行开始 try { String name = cursor.getString(0); - sContactCache.put(phoneNumber, name); + sContactCache.put(phoneNumber, name);//把找到的联系人电话和名字移到缓存列表中 return name; } catch (IndexOutOfBoundsException e) { - Log.e(TAG, " Cursor get string error " + e.toString()); + Log.e(TAG, " Cursor get string error " + e.toString());//异常处理 return null; } finally { - cursor.close(); + cursor.close();//关闭数据库的访问 } } else { + //数据库不存在或没找到此联系电话 Log.d(TAG, "No contact matched with number:" + phoneNumber); return null; } diff --git a/src/main/java/net/micode/notes/data/Notes.java b/src/main/java/net/micode/notes/data/Notes.java index f240604..b3aa269 100644 --- a/src/main/java/net/micode/notes/data/Notes.java +++ b/src/main/java/net/micode/notes/data/Notes.java @@ -15,26 +15,33 @@ */ package net.micode.notes.data; - +/*uri是统一资源标志符(Uniform Resource Identifier),而在这个类中定义了各种Uri常量, +以便在其他的类中调用。Uri用处很多,涉及到安卓权限,比如通过Uri可以: +直接拨打电话、调出拨打电话界面、调WEB浏览器、卸载、安装、播放、调用发邮件、直接发邮件等系统功能 +Android上可用的每种资源 -包括 图像、视频片段、音频资源等都可以用Uri来表示*/ import android.net.Uri; public class Notes { - public static final String AUTHORITY = "micode_notes"; - public static final String TAG = "Notes"; - public static final int TYPE_NOTE = 0; - public static final int TYPE_FOLDER = 1; - public static final int TYPE_SYSTEM = 2; + /*便签数据库,该类主要实现了对便签的相关属性包括:Anthority, Tag,以及数据,联系人的信息进行保存管理, + 其中主要实现了对若干属性的定义,并创建了DataColumns,DataColumns接口的定义,该两个接口可用于其余类的实现, + 在便签管理中实现TextNote,CallNote两个类,用于对便签内容的保存。*/ + public static final String AUTHORITY = "micode_notes";//定义了一个权限名,这里是为了符合Uri的格式而定义的。 + public static final String TAG = "Notes";//定义该类的名称 + public static final int TYPE_NOTE = 0;//Note的类型,这里规定了三种;普通Note, + public static final int TYPE_FOLDER = 1;//文件夹Folder, + public static final int TYPE_SYSTEM = 2;//系统文件System /** - * Following IDs are system folders' identifiers - * {@link Notes#ID_ROOT_FOLDER } is default folder - * {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder - * {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records + * Following IDs are system folders' identifiers(下列ID是系统文件的标识) + * {@link Notes#ID_ROOT_FOLDER } is default folder(根目录(默认文件夹)) + * {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder(临时文件夹) + * {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records(通话记录文件夹) + * {@link Notes#ID_TRASH_FOLER}(垃圾文件夹) */ public static final int ID_ROOT_FOLDER = 0; public static final int ID_TEMPARAY_FOLDER = -1; public static final int ID_CALL_RECORD_FOLDER = -2; public static final int ID_TRASH_FOLER = -3; - + //下列是各个文件夹名称标识,定义各种小部件(widget) public static final String INTENT_EXTRA_ALERT_DATE = "net.micode.notes.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"; @@ -42,28 +49,30 @@ public class Notes { 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_2X = 0; - public static final int TYPE_WIDGET_4X = 1; + public static final int TYPE_WIDGET_INVALIDE = -1;//定义查询便签和文件夹的指针 + public static final int TYPE_WIDGET_2X = 0;//2*2小部件 + public static final int TYPE_WIDGET_4X = 1;//4*4小部件 public static class DataConstants { + //存放textnotes和callnotes地址 public static final String NOTE = TextNote.CONTENT_ITEM_TYPE; public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE; } /** - * Uri to query all notes and folders + * Uri to query all notes and folders(统一资源标识符查询便签和文件夹) */ public static final Uri CONTENT_NOTE_URI = Uri.parse("content://" + AUTHORITY + "/note"); /** - * Uri to query data + * Uri to query data(统一资源标识符查询数据) */ public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data"); public interface NoteColumns { + //定义NoteColumns的常量,用于后面创建数据库的表头,定义Note的一系列属性 /** - * The unique ID for a row + * The unique ID for a row(主键) *

Type: INTEGER (long)

*/ public static final String ID = "_id"; @@ -72,7 +81,7 @@ public class Notes { * The parent's id for note or folder *

Type: INTEGER (long)

*/ - public static final String PARENT_ID = "parent_id"; + public static final String PARENT_ID = "parent_id";//父节点id /** * Created data for note or folder @@ -84,14 +93,14 @@ public class Notes { * Latest modified date *

Type: INTEGER (long)

*/ - public static final String MODIFIED_DATE = "modified_date"; + public static final String MODIFIED_DATE = "modified_date";//更新日期 /** * Alert date *

Type: INTEGER (long)

*/ - public static final String ALERTED_DATE = "alert_date"; + public static final String ALERTED_DATE = "alert_date";//更改日期 /** * Folder's name or text content of note @@ -122,7 +131,7 @@ public class Notes { * note, it has at least one attachment *

Type: INTEGER

*/ - public static final String HAS_ATTACHMENT = "has_attachment"; + public static final String HAS_ATTACHMENT = "has_attachment";//是否有附件 /** * Folder's count of notes @@ -140,78 +149,78 @@ public class Notes { * The last sync id *

Type: INTEGER (long)

*/ - public static final String SYNC_ID = "sync_id"; + public static final String SYNC_ID = "sync_id";//最后一次的同步id /** - * Sign to indicate local modified or not + * Sign to indicate(显示) local modified or not(本地是否修改过标识) *

Type: INTEGER

*/ - public static final String LOCAL_MODIFIED = "local_modified"; + public static final String LOCAL_MODIFIED = "local_modified";//本地是否修改过 /** * Original parent id before moving into temporary folder *

Type : INTEGER

*/ - public static final String ORIGIN_PARENT_ID = "origin_parent_id"; + public static final String ORIGIN_PARENT_ID = "origin_parent_id";//父节点id在移到临时文件夹之前 /** * The gtask id *

Type : TEXT

*/ - public static final String GTASK_ID = "gtask_id"; + public static final String GTASK_ID = "gtask_id";//后台任务的id /** * The version code *

Type : INTEGER (long)

*/ - public static final String VERSION = "version"; + public static final String VERSION = "version";//版本号 } public interface DataColumns { + //定义DataColumns的常量,用于后面创建数据库的表头。主要是定义存储便签数据内容 /** * The unique ID for a row *

Type: INTEGER (long)

*/ - public static final String ID = "_id"; + public static final String ID = "_id";//每一行id /** - * The MIME type of the item represented by this row. + * The MIME type of the item represented by this row.(这行代表的mime类型) *

Type: Text

*/ - public static final String MIME_TYPE = "mime_type"; + public static final String MIME_TYPE = "mime_type";//MIME类型能包含视频、图像、文本、音频、应用程序等数据 /** * The reference id to note that this data belongs to *

Type: INTEGER (long)

*/ - public static final String NOTE_ID = "note_id"; + public static final String NOTE_ID = "note_id";//标签id /** * Created data for note or folder *

Type: INTEGER (long)

*/ - public static final String CREATED_DATE = "created_date"; + public static final String CREATED_DATE = "created_date";//创建时间 /** * Latest modified date *

Type: INTEGER (long)

*/ - public static final String MODIFIED_DATE = "modified_date"; + public static final String MODIFIED_DATE = "modified_date";//修改时间 /** * Data's content *

Type: TEXT

*/ - public static final String CONTENT = "content"; - + public static final String CONTENT = "content";//内容 + /*以下定义了五个常量*/ /** * Generic data column, the meaning is {@link #MIMETYPE} specific, used for * integer data type *

Type: INTEGER

*/ public static final String DATA1 = "data1"; - /** * Generic data column, the meaning is {@link #MIMETYPE} specific, used for * integer data type @@ -242,38 +251,42 @@ public class Notes { } public static final class TextNote implements DataColumns { + //文本标签实现DataColumns接口,继承上述所有常量 + /*模式指示文本是否处于检查列表模式 + 1:检查列表模式,0:正常模式*/ /** * Mode to indicate the text in check list mode or not *

Type: Integer 1:check list mode 0: normal mode

*/ - public static final String MODE = DATA1; + public static final String MODE = DATA1;//继承DATA1 - public static final int MODE_CHECK_LIST = 1; + public static final int MODE_CHECK_LIST = 1;//1:检查列表模式 - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note";//内容类型 - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";//内容项目的类型 - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note"); + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");//content 的索引标识符 } public static final class CallNote implements DataColumns { + //记录通话数据的表头 /** * Call date for this record *

Type: INTEGER (long)

*/ - public static final String CALL_DATE = DATA1; + public static final String CALL_DATE = DATA1;//通话日期 /** * Phone number for this record *

Type: TEXT

*/ - public static final String PHONE_NUMBER = DATA3; + public static final String PHONE_NUMBER = DATA3;//电话号码 - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note"; + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";//内容类型 - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note"; + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";//内容项目类型 - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note"); + public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");//content 的索引标识符 } } diff --git a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java index ffe5d57..02164f4 100644 --- a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java +++ b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package net.micode.notes.data; import android.content.ContentValues; @@ -26,22 +25,23 @@ import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.NoteColumns; - +//数据库帮助类,用于辅助创建、处理数据库的条目 public class NotesDatabaseHelper extends SQLiteOpenHelper { - private static final String DB_NAME = "note.db"; + private static final String DB_NAME = "note.db";//数据库名字 - private static final int DB_VERSION = 4; + private static final int DB_VERSION = 4;//数据库版本 public interface TABLE { + //接口类,定义数据库表的便签和数据 public static final String NOTE = "note"; public static final String DATA = "data"; } - private static final String TAG = "NotesDatabaseHelper"; - - private static NotesDatabaseHelper mInstance; + private static final String TAG = "NotesDatabaseHelper";//定义该类的名称 + private static NotesDatabaseHelper mInstance;//实例化对象 + //创建标签表表头并初始化 private static final String CREATE_NOTE_TABLE_SQL = "CREATE TABLE " + TABLE.NOTE + "(" + NoteColumns.ID + " INTEGER PRIMARY KEY," + @@ -62,7 +62,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + ")"; - + //创建数据表表头并初始化 private static final String CREATE_DATA_TABLE_SQL = "CREATE TABLE " + TABLE.DATA + "(" + DataColumns.ID + " INTEGER PRIMARY KEY," + @@ -77,7 +77,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + ")"; - + //对数据表创建索引,以便签的ID作为数据库的ID,用来做数据库ID的索引 private static final String CREATE_DATA_NOTE_ID_INDEX_SQL = "CREATE INDEX IF NOT EXISTS note_id_index ON " + TABLE.DATA + "(" + DataColumns.NOTE_ID + ");"; @@ -85,6 +85,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Increase folder's note count when move note to the folder */ + //创建触发器当把便签移入文件夹时,文件夹的便签数量+1 private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = "CREATE TRIGGER increase_folder_count_on_update "+ " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + @@ -97,6 +98,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Decrease folder's note count when move note from folder */ + //创建触发器当把便签移出文件夹时,减少文件夹的便签数量-1 private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER = "CREATE TRIGGER decrease_folder_count_on_update " + " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE + @@ -110,6 +112,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Increase folder's note count when insert new note to the folder */ + //创建触发器当把便签插入到文件夹时,文件夹的便签数量+1 private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = "CREATE TRIGGER increase_folder_count_on_insert " + " AFTER INSERT ON " + TABLE.NOTE + @@ -122,6 +125,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Decrease folder's note count when delete note from the folder */ + //创建触发器当把便签从文件夹删除时,文件夹的便签数量-1 private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = "CREATE TRIGGER decrease_folder_count_on_delete " + " AFTER DELETE ON " + TABLE.NOTE + @@ -135,6 +139,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Update note's content when insert data with type {@link DataConstants#NOTE} */ + //创建触发器,当向note插入数据时,更新note的内容,并更改表格内容 private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER = "CREATE TRIGGER update_note_content_on_insert " + " AFTER INSERT ON " + TABLE.DATA + @@ -148,6 +153,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Update note's content when data with {@link DataConstants#NOTE} type has changed */ + //创建触发器,当note数据改变时,更新note的内容,并更改表格内容 private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER = "CREATE TRIGGER update_note_content_on_update " + " AFTER UPDATE ON " + TABLE.DATA + @@ -161,6 +167,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Update note's content when data with {@link DataConstants#NOTE} type has deleted */ + //创建触发器,当note数据被删除时,更新note的内容,并更改表格内容 private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER = "CREATE TRIGGER update_note_content_on_delete " + " AFTER delete ON " + TABLE.DATA + @@ -174,6 +181,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Delete datas belong to note which has been deleted */ + //创建触发器,删除已经被删除的便签的数据 private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER = "CREATE TRIGGER delete_data_on_delete " + " AFTER DELETE ON " + TABLE.NOTE + @@ -185,6 +193,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Delete notes belong to folder which has been deleted */ + //创建触发器,删除已经被删除的文件夹的便签 private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER = "CREATE TRIGGER folder_delete_notes_on_delete " + " AFTER DELETE ON " + TABLE.NOTE + @@ -196,6 +205,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { /** * Move notes belong to folder which has been moved to trash folder */ + //创建触发器,移出已近被移到垃圾文件夹中的便签 private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER = "CREATE TRIGGER folder_move_notes_on_trash " + " AFTER UPDATE ON " + TABLE.NOTE + @@ -205,18 +215,18 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { " SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + " END"; - + //构造函数,传入数据库的名称和版本 public NotesDatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } - + //创建数据库,并且自动执行create方法,并且定义了下面的属性。 public void createNoteTable(SQLiteDatabase db) { db.execSQL(CREATE_NOTE_TABLE_SQL); reCreateNoteTableTriggers(db); createSystemFolder(db); Log.d(TAG, "note table has been created"); } - + //如果触发器存在则drop,然后再次创建触发器 private void reCreateNoteTableTriggers(SQLiteDatabase db) { db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); @@ -234,49 +244,49 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER); db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER); } - + //创建系统文件夹 private void createSystemFolder(SQLiteDatabase db) { - ContentValues values = new ContentValues(); + ContentValues values = new ContentValues();//创建对象记录基本数据的值 /** - * call record foler for call notes + * call record foler for call notes(呼叫记录文件夹) */ - values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER); - values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); - db.insert(TABLE.NOTE, null, values); + values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);//放入数据(NoteColumns的id,呼叫记录文件夹的ld) + values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);//将note的文件夹类型,与要放入数据库记录的格式类型映射,形成values的键-值 + db.insert(TABLE.NOTE, null, values);//向数据库的note表中插入数据 /** - * root folder which is default folder + * root folder which is default folder(默认文件夹) */ - values.clear(); + values.clear();//清空值且以下步骤与上述相同 values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); db.insert(TABLE.NOTE, null, values); /** - * temporary folder which is used for moving note + * temporary folder which is used for moving note(为移动note而设置的临时文件夹) */ - values.clear(); + values.clear();//清空值且以下步骤与上述相同 values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); db.insert(TABLE.NOTE, null, values); /** - * create trash folder + * create trash folder(创建垃圾回收文件夹) */ - values.clear(); + values.clear();////清空值且以下步骤与上述相同 values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); db.insert(TABLE.NOTE, null, values); } - + //创建数据库,并且自动执行create方法,并且定义了下面的属性。 public void createDataTable(SQLiteDatabase db) { db.execSQL(CREATE_DATA_TABLE_SQL); reCreateDataTableTriggers(db); db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); Log.d(TAG, "data table has been created"); } - + //如果触发器存在则drop,然后再次创建触发器 private void reCreateDataTableTriggers(SQLiteDatabase db) { db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update"); @@ -286,7 +296,8 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER); db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER); } - + /*如果NotesDatabaseHelper的实例创建失败,那就重新建一个,重新分配内从空间 + static synchronized限制线程同时访问该实例*/ static synchronized NotesDatabaseHelper getInstance(Context context) { if (mInstance == null) { mInstance = new NotesDatabaseHelper(context); @@ -294,52 +305,52 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { return mInstance; } - @Override + //onCreat方法创建note和data表 public void onCreate(SQLiteDatabase db) { createNoteTable(db); createDataTable(db); } - @Override + //当打开数据库时传入的版本号与当前的版本号不同时会调用该方法,更新版本 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - boolean reCreateTriggers = false; - boolean skipV2 = false; + boolean reCreateTriggers = false;//是否重建 + boolean skipV2 = false;//是否从V2升级到V3 - if (oldVersion == 1) { - upgradeToV2(db); + if (oldVersion == 1) {//版本是1 + upgradeToV2(db);//更新到2 skipV2 = true; // this upgrade including the upgrade from v2 to v3 oldVersion++; } - if (oldVersion == 2 && !skipV2) { - upgradeToV3(db); + if (oldVersion == 2 && !skipV2) {//版本是2且没有跳过2号版本,就更新到3号版本 + upgradeToV3(db);//更新到3 reCreateTriggers = true; oldVersion++; } - if (oldVersion == 3) { - upgradeToV4(db); + if (oldVersion == 3) {//版本是3 + upgradeToV4(db);//更新到4 oldVersion++; } - if (reCreateTriggers) { + if (reCreateTriggers) {//如果重新创建触发器,则重新创建两个表的触发器 reCreateNoteTableTriggers(db); reCreateDataTableTriggers(db); } - if (oldVersion != newVersion) { + if (oldVersion != newVersion) {//如果旧版本不等于新版本则抛出更新版本失败错误 throw new IllegalStateException("Upgrade notes database to version " + newVersion + "fails"); } } - + //更新数据库到版本2 private void upgradeToV2(SQLiteDatabase db) { db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); createNoteTable(db); createDataTable(db); } - + //更新数据库到版本3 private void upgradeToV3(SQLiteDatabase db) { // drop unused triggers db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert"); @@ -354,7 +365,7 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); db.insert(TABLE.NOTE, null, values); } - + //更新数据库到版本4 private void upgradeToV4(SQLiteDatabase db) { db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0"); diff --git a/src/main/java/net/micode/notes/data/NotesProvider.java b/src/main/java/net/micode/notes/data/NotesProvider.java index edb0a60..eac119f 100644 --- a/src/main/java/net/micode/notes/data/NotesProvider.java +++ b/src/main/java/net/micode/notes/data/NotesProvider.java @@ -33,15 +33,14 @@ import net.micode.notes.R; import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.NotesDatabaseHelper.TABLE; - - +/*1. 便签信息提供类,该类继承于ContentProvider类,由此可见该类主要用于数据的提供的功能,供其他模块实现,相当于对便签信息的管理,该类定义了相关的UriMathcher用于匹配Uri,使数据管理更加安全,并定义了一些列的方法,对该软件创建的数据库进行管理,例如,OnCreate, query,insert,update, parseSelection等方法,用于对被选中的数据对象进行相关的删除,插入,更新等操作,实现对数据库的管理,为上层的使用提供了一个较好的接口,对数据库信息进行抽象。*/ public class NotesProvider extends ContentProvider { - private static final UriMatcher mMatcher; - - private NotesDatabaseHelper mHelper; + private static final UriMatcher mMatcher;//UriMatcher是Android提供的用来操作Uri的工具类 - private static final String TAG = "NotesProvider"; + private NotesDatabaseHelper mHelper;//创建数据库帮助类实体对象 + private static final String TAG = "NotesProvider";//该类的自定义标签 + //1-6都是uri资源的id private static final int URI_NOTE = 1; private static final int URI_NOTE_ITEM = 2; private static final int URI_DATA = 3; @@ -49,22 +48,25 @@ public class NotesProvider extends ContentProvider { private static final int URI_SEARCH = 5; private static final int URI_SEARCH_SUGGEST = 6; - + //将以下这些变量放在static模块中,只初始化一次,提高运行速度以及减少空间浪费。将各个Uri与其代号关联在一起 static { - mMatcher = new UriMatcher(UriMatcher.NO_MATCH); + mMatcher = new UriMatcher(UriMatcher.NO_MATCH);//创建uri工具类实例对象 + //注册URI路径的过程 mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM); mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH); + //SUGGEST_URI_PATH_QUERY 并不属于URI的一部分,而应是用于指向此路径的常量 mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST); mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST); } /** * 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 + "," + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," @@ -72,116 +74,124 @@ public class NotesProvider extends ContentProvider { + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; - + //note搜索查询 private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION + " FROM " + TABLE.NOTE + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; - @Override + //创建一个便签数据库助手mHelper public boolean onCreate() { mHelper = NotesDatabaseHelper.getInstance(getContext()); return true; } - @Override + //查询uri在数据库中对应的位置 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - Cursor c = null; - SQLiteDatabase db = mHelper.getReadableDatabase(); + Cursor c = null;//函数返回对象 + /*getReadableDatabase()方法是先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。如果该问题成功解决,则只读数据库对象就会关闭,然后返回一个可读写的数据库对象。*/ + SQLiteDatabase db = mHelper.getReadableDatabase();//向数据库读操作 String id = null; switch (mMatcher.match(uri)) { - case URI_NOTE: + case URI_NOTE://匹配到标签的uri c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, - sortOrder); + sortOrder);//查询的表返回列行如何分组过滤条件,数据库查询语句 break; - case URI_NOTE_ITEM: - id = uri.getPathSegments().get(1); + case URI_NOTE_ITEM://匹配到标签条目 + id = uri.getPathSegments().get(1);//匹配到列表中便签项的路径中的1号字符 c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id - + parseSelection(selection), selectionArgs, null, null, sortOrder); + + parseSelection(selection), selectionArgs, null, null, sortOrder);//查询的表返回列行如何分组过滤条件,数据库查询语句 break; - case URI_DATA: + case URI_DATA://匹配到数据的uri c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null, - sortOrder); + sortOrder);//查询的表返回列行如何分组过滤条件,数据库查询语句 break; - case URI_DATA_ITEM: - id = uri.getPathSegments().get(1); + case URI_DATA_ITEM://匹配到数据条目 + id = uri.getPathSegments().get(1);//匹配到列表中数据项的路径中的1号字符 c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id - + parseSelection(selection), selectionArgs, null, null, sortOrder); + + parseSelection(selection), selectionArgs, null, null, sortOrder);//数据库查询语句 break; - case URI_SEARCH: - case URI_SEARCH_SUGGEST: + case URI_SEARCH://匹配到搜索 + case URI_SEARCH_SUGGEST://匹配到搜索建议 if (sortOrder != null || projection != null) { + //如果sortOrder或projection不为空抛出错误 throw new IllegalArgumentException( "do not specify sortOrder, selection, selectionArgs, or projection" + "with this query"); } String searchString = null; - if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) { + if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) {//匹配到搜索建议 if (uri.getPathSegments().size() > 1) { + //如果如果该路径数组大小大于一则取第一个元素 searchString = uri.getPathSegments().get(1); } } else { + //小于1则取第零个元素 searchString = uri.getQueryParameter("pattern"); } if (TextUtils.isEmpty(searchString)) { + //如果路径为空则返回空 return null; } try { + /*通过上文得到的搜索字符串,进行格式加工,而后通过rawQuery()直接在“NOTES_SNIPPET_SEARCH_QUERY”数据库中搜索ID=searchString的对应信息串。*/ searchString = String.format("%%%s%%", searchString); + /*cursor = db.rawQuery("select name from *** where id=?", new String[]{"1"});*/ c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY, new String[] { searchString }); } catch (IllegalStateException ex) { - Log.e(TAG, "got exception: " + ex.toString()); + Log.e(TAG, "got exception: " + ex.toString());//出错抛出异常 } break; default: - throw new IllegalArgumentException("Unknown URI " + uri); + throw new IllegalArgumentException("Unknown URI " + uri);//无法匹配上述的uri,抛出错误 } if (c != null) { + //若getContentResolver发生变化,就接收通知 c.setNotificationUri(getContext().getContentResolver(), uri); } return c; } - @Override + //插入一个新的uri public Uri insert(Uri uri, ContentValues values) { - SQLiteDatabase db = mHelper.getWritableDatabase(); + SQLiteDatabase db = mHelper.getWritableDatabase();//向数据库写操作 long dataId = 0, noteId = 0, insertedId = 0; switch (mMatcher.match(uri)) { case URI_NOTE: - insertedId = noteId = db.insert(TABLE.NOTE, null, values); + insertedId = noteId = db.insert(TABLE.NOTE, null, values);//向note表插入一个uri break; case URI_DATA: - if (values.containsKey(DataColumns.NOTE_ID)) { - noteId = values.getAsLong(DataColumns.NOTE_ID); + if (values.containsKey(DataColumns.NOTE_ID)) {//如果数据包含主键 + noteId = values.getAsLong(DataColumns.NOTE_ID);//转换为long型 } else { - Log.d(TAG, "Wrong data format without note id:" + values.toString()); + Log.d(TAG, "Wrong data format without note id:" + values.toString());//信息不含主键抛出异常错误 } - insertedId = dataId = db.insert(TABLE.DATA, null, values); + insertedId = dataId = db.insert(TABLE.DATA, null, values);//向数据表插入一个uri break; default: - throw new IllegalArgumentException("Unknown URI " + uri); + throw new IllegalArgumentException("Unknown URI " + uri);//不匹配的uri } - // Notify the note uri + // Notify the note uri(报告note id) if (noteId > 0) { getContext().getContentResolver().notifyChange( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null); } - // Notify the data uri + // Notify the data uri(报告data id) if (dataId > 0) { getContext().getContentResolver().notifyChange( ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null); } - return ContentUris.withAppendedId(uri, insertedId); + return ContentUris.withAppendedId(uri, insertedId);//返回插入uri的路径 } - @Override + //删除一个uri public int delete(Uri uri, String selection, String[] selectionArgs) { int count = 0; String id = null; @@ -189,8 +199,8 @@ public class NotesProvider extends ContentProvider { boolean deleteData = false; switch (mMatcher.match(uri)) { case URI_NOTE: - selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 "; - count = db.delete(TABLE.NOTE, selection, selectionArgs); + selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 ";//要删除的note的信息 + count = db.delete(TABLE.NOTE, selection, selectionArgs);//删除且返回数量 break; case URI_NOTE_ITEM: id = uri.getPathSegments().get(1); @@ -200,11 +210,13 @@ public class NotesProvider extends ContentProvider { */ long noteId = Long.valueOf(id); if (noteId <= 0) { + // ID小于0表示是系统文件夹,不能删除 break; } count = db.delete(TABLE.NOTE, - NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs); + NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs);//删除且返回数量 break; + //以下两个与上两个相同 case URI_DATA: count = db.delete(TABLE.DATA, selection, selectionArgs); deleteData = true; @@ -216,34 +228,35 @@ public class NotesProvider extends ContentProvider { deleteData = true; break; default: - throw new IllegalArgumentException("Unknown URI " + uri); + throw new IllegalArgumentException("Unknown URI " + uri);//不匹配的uri } if (count > 0) { - if (deleteData) { + if (deleteData) {//如果真的删除了数据,则要求监听器对观察者发送通知 getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); } - getContext().getContentResolver().notifyChange(uri, null); + getContext().getContentResolver().notifyChange(uri, null);//对所有修改进行通知 } - return count; + return count;//返回删除数量 } - @Override + //更新一个uri public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - int count = 0; + int count = 0;//更新数量 String id = null; SQLiteDatabase db = mHelper.getWritableDatabase(); boolean updateData = false; switch (mMatcher.match(uri)) { case URI_NOTE: - increaseNoteVersion(-1, selection, selectionArgs); - count = db.update(TABLE.NOTE, values, selection, selectionArgs); + increaseNoteVersion(-1, selection, selectionArgs);//先升级版本再更新 + count = db.update(TABLE.NOTE, values, selection, selectionArgs);//更新且返回数量 break; case URI_NOTE_ITEM: - id = uri.getPathSegments().get(1); + id = uri.getPathSegments().get(1);//获取该item的id increaseNoteVersion(Long.valueOf(id), selection, selectionArgs); count = db.update(TABLE.NOTE, values, NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs); break; + //与上述两个相同 case URI_DATA: count = db.update(TABLE.DATA, values, selection, selectionArgs); updateData = true; @@ -255,23 +268,24 @@ public class NotesProvider extends ContentProvider { updateData = true; break; default: - throw new IllegalArgumentException("Unknown URI " + uri); + throw new IllegalArgumentException("Unknown URI " + uri);//不匹配uri } if (count > 0) { - if (updateData) { + if (updateData) {//如果对数据进行了更新,则要求监听器对观察者发送通知 getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); } - getContext().getContentResolver().notifyChange(uri, null); + getContext().getContentResolver().notifyChange(uri, null);//对所有更新进行通知 } - return count; + return count;//返回更新的数量 } private String parseSelection(String selection) { + //如果selection不是空字符,那么返回" AND (" + selection + ')'如果是空字符,返回"" return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); } - private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { + //在数据库中升级版本 StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); sql.append(TABLE.NOTE); @@ -282,22 +296,23 @@ public class NotesProvider extends ContentProvider { if (id > 0 || !TextUtils.isEmpty(selection)) { sql.append(" WHERE "); } - if (id > 0) { + if (id > 0) {//id>0就将其写入数据库 sql.append(NoteColumns.ID + "=" + String.valueOf(id)); } if (!TextUtils.isEmpty(selection)) { + //如果输入的字符串是非空的就将其写入数据库 String selectString = id > 0 ? parseSelection(selection) : selection; for (String args : selectionArgs) { selectString = selectString.replaceFirst("\\?", args); } sql.append(selectString); } - + // execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句 mHelper.getWritableDatabase().execSQL(sql.toString()); } @Override - public String getType(Uri uri) { + public String getType(Uri uri) {//获取uri的数据类型,实际永远返回null // TODO Auto-generated method stub return null; } diff --git a/src/main/java/net/micode/notes/tool/BackupUtils.java b/src/main/java/net/micode/notes/tool/BackupUtils.java index 39f6ec4..1a46d58 100644 --- a/src/main/java/net/micode/notes/tool/BackupUtils.java +++ b/src/main/java/net/micode/notes/tool/BackupUtils.java @@ -35,13 +35,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; - +/*备份工具类,用于数据备份读取和显示*/ public class BackupUtils { - private static final String TAG = "BackupUtils"; + private static final String TAG = "BackupUtils";//定义类的名字标识 // Singleton stuff - private static BackupUtils sInstance; + private static BackupUtils sInstance;//定义实体对象 public static synchronized BackupUtils getInstance(Context context) { + //获取实体对象 if (sInstance == null) { sInstance = new BackupUtils(context); } @@ -49,56 +50,57 @@ public class BackupUtils { } /** - * Following states are signs to represents backup or restore - * status + * Following states are signs to represents backup or restore(以下是表示备份或恢复的符号) + * status(状态) */ - // Currently, the sdcard is not mounted + // Currently, the sdcard is not mounted(当前sd卡未安装) public static final int STATE_SD_CARD_UNMOUONTED = 0; - // The backup file not exist + // The backup file not exist(备份文件不存在) public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; - // The data is not well formated, may be changed by other programs + // The data is not well formated, may be changed by other programs(数据格式不正确可能被其他程序更改) public static final int STATE_DATA_DESTROIED = 2; - // Some run-time exception which causes restore or backup fails + // Some run-time exception which causes restore or backup fails(导致备份或还原失败的默写运行异常) public static final int STATE_SYSTEM_ERROR = 3; - // Backup or restore success + // Backup or restore success(备份或还原成功) public static final int STATE_SUCCESS = 4; - private TextExport mTextExport; - + private TextExport mTextExport;//实例化对象 + //构造函数 private BackupUtils(Context context) { mTextExport = new TextExport(context); } - + //判断外部存储功能是否可用 private static boolean externalStorageAvailable() { return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } - + //返回输出到文本后的状态 public int exportToText() { return mTextExport.exportToText(); } - + //返回输出文本文件名字 public String getExportedTextFileName() { return mTextExport.mFileName; } - + //返回输出文本文件路径 public String getExportedTextFileDir() { return mTextExport.mFileDirectory; } - + //文本输出类 private static class TextExport { + //note映射数组,存储note信息 private static final String[] NOTE_PROJECTION = { NoteColumns.ID, NoteColumns.MODIFIED_DATE, NoteColumns.SNIPPET, NoteColumns.TYPE }; - + //以下几行定义note数组里的属性值 private static final int NOTE_COLUMN_ID = 0; private static final int NOTE_COLUMN_MODIFIED_DATE = 1; private static final int NOTE_COLUMN_SNIPPET = 2; - + //数据映射数组,存储数据信息 private static final String[] DATA_PROJECTION = { DataColumns.CONTENT, DataColumns.MIME_TYPE, @@ -107,40 +109,44 @@ public class BackupUtils { DataColumns.DATA3, DataColumns.DATA4, }; - + //数据内容属性 private static final int DATA_COLUMN_CONTENT = 0; - + //媒体类型属性 private static final int DATA_COLUMN_MIME_TYPE = 1; - + //访问日期属性 private static final int DATA_COLUMN_CALL_DATE = 2; - + //电话号码属性 private static final int DATA_COLUMN_PHONE_NUMBER = 4; - + //文本格式数组 private final String [] TEXT_FORMAT; + //文件命名格式 private static final int FORMAT_FOLDER_NAME = 0; + //便签日期格式 private static final int FORMAT_NOTE_DATE = 1; + //便签内容格式 private static final int FORMAT_NOTE_CONTENT = 2; - private Context mContext; - private String mFileName; - private String mFileDirectory; + private Context mContext;//定义上下文类 + private String mFileName;//定义文件名 + private String mFileDirectory;//定义文件路径 public TextExport(Context context) { + //从context类实例中获取信息,给对应的属性赋初始值 TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); mContext = context; mFileName = ""; mFileDirectory = ""; } - + //获取文本格式内容 private String getFormat(int id) { return TEXT_FORMAT[id]; } /** - * Export the folder identified by folder id to text + * Export the folder identified by folder id to text(通过文件夹id向文本输出文件夹) */ private void exportFolderToText(String folderId, PrintStream ps) { - // Query notes belong to this folder + // Query notes belong to this folder(查询该notes是否属于这个文件夹) Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { folderId @@ -149,21 +155,21 @@ public class BackupUtils { if (notesCursor != null) { if (notesCursor.moveToFirst()) { do { - // Print note's last modified date + // Print note's last modified date(打印标签的最后一次更改日期) ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( mContext.getString(R.string.format_datetime_mdhm), notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); - // Query data belong to this note + // Query data belong to this note(查询该note的数据) String noteId = notesCursor.getString(NOTE_COLUMN_ID); exportNoteToText(noteId, ps); - } while (notesCursor.moveToNext()); + } while (notesCursor.moveToNext());//对该note所有的数据 } - notesCursor.close(); + notesCursor.close();//关闭游标 } } /** - * Export note identified by id to a print stream + * Export note identified by id to a print stream(输出note id向一个打印流) */ private void exportNoteToText(String noteId, PrintStream ps) { Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, @@ -176,7 +182,7 @@ public class BackupUtils { do { String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); if (DataConstants.CALL_NOTE.equals(mimeType)) { - // Print phone number + // Print phone number(打印电话号码) String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); String location = dataCursor.getString(DATA_COLUMN_CONTENT); @@ -185,11 +191,11 @@ public class BackupUtils { ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), phoneNumber)); } - // Print call date + // Print call date(打印访问日期) ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat .format(mContext.getString(R.string.format_datetime_mdhm), callDate))); - // Print call attachment location + // Print call attachment location(打印位置) if (!TextUtils.isEmpty(location)) { ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), location)); @@ -201,35 +207,35 @@ public class BackupUtils { content)); } } - } while (dataCursor.moveToNext()); + } while (dataCursor.moveToNext());//对所有数据 } - dataCursor.close(); + dataCursor.close();//关闭游标 } - // print a line separator between note + // print a line separator between note(打印一个线分隔两个note) try { ps.write(new byte[] { Character.LINE_SEPARATOR, Character.LETTER_NUMBER }); } catch (IOException e) { - Log.e(TAG, e.toString()); + Log.e(TAG, e.toString());//错误报告 } } /** - * Note will be exported as text which is user readable + * Note will be exported as text which is user readable(以text形式输出到外部设备SDcard) */ public int exportToText() { if (!externalStorageAvailable()) { Log.d(TAG, "Media was not mounted"); - return STATE_SD_CARD_UNMOUONTED; + return STATE_SD_CARD_UNMOUONTED;//sd卡未安装 } PrintStream ps = getExportToTextPrintStream(); if (ps == null) { Log.e(TAG, "get print stream error"); - return STATE_SYSTEM_ERROR; + return STATE_SYSTEM_ERROR;//系统状态错误 } - // First export folder and its notes + // First export folder and its notes(第一次输出文件夹和他的note) Cursor folderCursor = mContext.getContentResolver().query( Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, @@ -240,7 +246,7 @@ public class BackupUtils { if (folderCursor != null) { if (folderCursor.moveToFirst()) { do { - // Print folder's name + // Print folder's name(打印文件夹名字) String folderName = ""; if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { folderName = mContext.getString(R.string.call_record_folder_name); @@ -252,12 +258,12 @@ public class BackupUtils { } String folderId = folderCursor.getString(NOTE_COLUMN_ID); exportFolderToText(folderId, ps); - } while (folderCursor.moveToNext()); + } while (folderCursor.moveToNext());//对所有文件夹 } - folderCursor.close(); + folderCursor.close();//关闭游标 } - // Export notes in root's folder + // Export notes in root's folder(输出notes到系统文件夹) Cursor noteCursor = mContext.getContentResolver().query( Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, @@ -270,7 +276,7 @@ public class BackupUtils { ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( mContext.getString(R.string.format_datetime_mdhm), noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); - // Query data belong to this note + // Query data belong to this note(查询这个note的数据) String noteId = noteCursor.getString(NOTE_COLUMN_ID); exportNoteToText(noteId, ps); } while (noteCursor.moveToNext()); @@ -286,18 +292,19 @@ public class BackupUtils { * Get a print stream pointed to the file {@generateExportedTextFile} */ private PrintStream getExportToTextPrintStream() { + //create file to exported failed File file = generateFileMountedOnSDcard(mContext, R.string.file_path, R.string.file_name_txt_format); if (file == null) { - Log.e(TAG, "create file to exported failed"); + Log.e(TAG, "create file to exported failed");//异常报告 return null; } - mFileName = file.getName(); - mFileDirectory = mContext.getString(R.string.file_path); + mFileName = file.getName();//文件名字 + mFileDirectory = mContext.getString(R.string.file_path);//文件路径 PrintStream ps = null; try { FileOutputStream fos = new FileOutputStream(file); - ps = new PrintStream(fos); + ps = new PrintStream(fos);//创建一个打印流指向这个创建的文件 } catch (FileNotFoundException e) { e.printStackTrace(); return null; @@ -305,36 +312,37 @@ public class BackupUtils { e.printStackTrace(); return null; } - return ps; + return ps;//返回新文件的打印流 } } /** - * Generate the text file to store imported data + * Generate the text file to store imported data(生成文件存储在外部存储器上) */ + //产生用于存储输入信息的文件 private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { StringBuilder sb = new StringBuilder(); - sb.append(Environment.getExternalStorageDirectory()); - sb.append(context.getString(filePathResId)); - File filedir = new File(sb.toString()); + sb.append(Environment.getExternalStorageDirectory());//外部(SD卡)的存储路径 + sb.append(context.getString(filePathResId));//文件的存储路径 + File filedir = new File(sb.toString());//存储路径信息 sb.append(context.getString( fileNameFormatResId, DateFormat.format(context.getString(R.string.format_date_ymd), - System.currentTimeMillis()))); - File file = new File(sb.toString()); + System.currentTimeMillis())));//将当前的系统时间以预定的格式输出 + File file = new File(sb.toString());//将输出连接到一个文件里 try { if (!filedir.exists()) { - filedir.mkdir(); + filedir.mkdir();//创建新文件夹 } if (!file.exists()) { - file.createNewFile(); + file.createNewFile();//创建新文件 } return file; } catch (SecurityException e) { - e.printStackTrace(); + e.printStackTrace();//错误抛出异常 } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace();////错误抛出异常 } return null; diff --git a/src/main/java/net/micode/notes/tool/DataUtils.java b/src/main/java/net/micode/notes/tool/DataUtils.java index 2a14982..831bb1f 100644 --- a/src/main/java/net/micode/notes/tool/DataUtils.java +++ b/src/main/java/net/micode/notes/tool/DataUtils.java @@ -34,52 +34,55 @@ import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; import java.util.ArrayList; import java.util.HashSet; - +/*数据的集成工具类*/ public class DataUtils { - public static final String TAG = "DataUtils"; + public static final String TAG = "DataUtils";//定义该自定义类标识 public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { + //处理批量删除便签的方法 if (ids == null) { - Log.d(TAG, "the ids is null"); + Log.d(TAG, "the ids is null");//输出debug调试,无note删除 return true; } if (ids.size() == 0) { - Log.d(TAG, "no id is in the hashset"); + Log.d(TAG, "no id is in the hashset");//无note删除 return true; } - + //提供一个任务列表 ArrayList operationList = new ArrayList(); for (long id : ids) { if(id == Notes.ID_ROOT_FOLDER) { - Log.e(TAG, "Don't delete system folder root"); + Log.e(TAG, "Don't delete system folder root");//检测当前id是不是指向根目录,若是返回一个异常信息 continue; } + //使用newDelete实现删除操作 ContentProviderOperation.Builder builder = ContentProviderOperation .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); + //将操作添加至列表 operationList.add(builder.build()); } try { ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); if (results == null || results.length == 0 || results[0] == null) { - Log.d(TAG, "delete notes failed, ids:" + ids.toString()); + Log.d(TAG, "delete notes failed, ids:" + ids.toString());//删除失败 return false; } return true; } catch (RemoteException e) { - Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));//返回异常错误 } catch (OperationApplicationException e) { - Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));//返回错误异常 } return false; } - + //移动note到文件夹 public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { - ContentValues values = new ContentValues(); - values.put(NoteColumns.PARENT_ID, desFolderId); - values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); - values.put(NoteColumns.LOCAL_MODIFIED, 1); - resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); + ContentValues values = new ContentValues();//获取note信息 + values.put(NoteColumns.PARENT_ID, desFolderId);//设置父节点为目标文件夹id + values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId);//设置原本的父节点为原本的文件夹的id + values.put(NoteColumns.LOCAL_MODIFIED, 1);//设置修改符号为1 + resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null);//对移动过的便签进行数据的更新 } - + //与上述批量删除note相同,批量移到指定文件夹 public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, long folderId) { if (ids == null) { @@ -97,6 +100,7 @@ public class DataUtils { } try { + //对于一些异常进行处理与汇报,applyBatch一次性处理一个操作列表 ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); if (results == null || results.length == 0 || results[0] == null) { Log.d(TAG, "delete notes failed, ids:" + ids.toString()); @@ -112,14 +116,14 @@ public class DataUtils { } /** - * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} + * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}}(获取除了系统文件夹的所有文件夹数量) */ public static int getUserFolderCount(ContentResolver resolver) { Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, new String[] { "COUNT(*)" }, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, - null); + null);//在数据库中查询并用游标指向它 int count = 0; if(cursor != null) { @@ -127,82 +131,87 @@ public class DataUtils { try { count = cursor.getInt(0); } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "get folder count failed:" + e.toString()); + Log.e(TAG, "get folder count failed:" + e.toString());//失败报告 } finally { cursor.close(); } } } - return count; + return count;//返回数量 } public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { + //在数据库中是否可见 Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, new String [] {String.valueOf(type)}, - null); + null);//查询note是否可以找到 boolean exist = false; if (cursor != null) { if (cursor.getCount() > 0) { - exist = true; + exist = true;//找到 } cursor.close(); } - return exist; + return exist;//可见 } public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { + //在数据库中note是否存在 Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), - null, null, null, null); + null, null, null, null);//查询数据是否存在 boolean exist = false; if (cursor != null) { if (cursor.getCount() > 0) { - exist = true; + exist = true;///找到 } cursor.close(); } - return exist; + return exist;//存在 } public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { + //在数据库中数据是否存在 Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), - null, null, null, null); + null, null, null, null);//查找数据 boolean exist = false; if (cursor != null) { if (cursor.getCount() > 0) { - exist = true; + exist = true;//找到 } cursor.close(); } - return exist; + return exist;//存在 } public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { + //检查文件夹名字是否可见 Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND " + NoteColumns.SNIPPET + "=?", - new String[] { name }, null); + new String[] { name }, null);//查询 boolean exist = false; if(cursor != null) { if(cursor.getCount() > 0) { - exist = true; + exist = true;//找到 } cursor.close(); } - return exist; + return exist;//可见 } public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) { + //使用hashset来存储不同窗口的id和type并且建立对应关系 Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, NoteColumns.PARENT_ID + "=?", new String[] { String.valueOf(folderId) }, - null); + null);//父ID是否为传入的folderId HashSet set = null; if (c != null) { @@ -213,7 +222,7 @@ public class DataUtils { AppWidgetAttribute widget = new AppWidgetAttribute(); widget.widgetId = c.getInt(0); widget.widgetType = c.getInt(1); - set.add(widget); + set.add(widget);//存储不同窗口的id和type } catch (IndexOutOfBoundsException e) { Log.e(TAG, e.toString()); } @@ -225,17 +234,18 @@ public class DataUtils { } public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { + //通过noteid获取呼叫号码 Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, new String [] { CallNote.PHONE_NUMBER }, CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, - null); + null);//在数据库查询 if (cursor != null && cursor.moveToFirst()) { try { - return cursor.getString(0); + return cursor.getString(0);//找到 } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "Get call number fails " + e.toString()); + Log.e(TAG, "Get call number fails " + e.toString());//没找到 } finally { cursor.close(); } @@ -244,45 +254,48 @@ public class DataUtils { } public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { + //通过映射关系,通过号码和日期获取ID Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, new String [] { CallNote.NOTE_ID }, CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" + CallNote.PHONE_NUMBER + ",?)", new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, - null); + null);//在数据库查询 if (cursor != null) { if (cursor.moveToFirst()) { try { - return cursor.getLong(0); + return cursor.getLong(0);//找到 } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "Get call note id fails " + e.toString()); + Log.e(TAG, "Get call note id fails " + e.toString());//失败 } } - cursor.close(); + cursor.close();//关闭游标 } return 0; } public static String getSnippetById(ContentResolver resolver, long noteId) { + //进入清单模式后,note会分为若干段,该函数将每一个段返回对应的字符串 Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, new String [] { NoteColumns.SNIPPET }, NoteColumns.ID + "=?", new String [] { String.valueOf(noteId)}, - null); + null);//查找 if (cursor != null) { String snippet = ""; if (cursor.moveToFirst()) { - snippet = cursor.getString(0); + snippet = cursor.getString(0);//找到 } - cursor.close(); + cursor.close();//关闭游标 return snippet; } - throw new IllegalArgumentException("Note is not found with id: " + noteId); + throw new IllegalArgumentException("Note is not found with id: " + noteId);//失败 } public static String getFormattedSnippet(String snippet) { + //将文件名标准化 if (snippet != null) { snippet = snippet.trim(); int index = snippet.indexOf('\n'); diff --git a/src/main/java/net/micode/notes/tool/GTaskStringUtils.java b/src/main/java/net/micode/notes/tool/GTaskStringUtils.java index 666b729..cd4c10b 100644 --- a/src/main/java/net/micode/notes/tool/GTaskStringUtils.java +++ b/src/main/java/net/micode/notes/tool/GTaskStringUtils.java @@ -15,36 +15,36 @@ */ package net.micode.notes.tool; - +/*定义了很多的静态常量字符串,目的就是为了提供jsonObject中相应字符串的"key"。把这些静态的定义单独写到了一个类里面,方便查找和更改*/ public class GTaskStringUtils { - public final static String GTASK_JSON_ACTION_ID = "action_id"; + public final static String GTASK_JSON_ACTION_ID = "action_id";//任务id - public final static String GTASK_JSON_ACTION_LIST = "action_list"; + public final static String GTASK_JSON_ACTION_LIST = "action_list";//任务列表 - public final static String GTASK_JSON_ACTION_TYPE = "action_type"; + public final static String GTASK_JSON_ACTION_TYPE = "action_type";//任务类型 - public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create";//新建 - public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all";//获取所有的任务类型 - public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move";//移动 - public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update";//更新 - public final static String GTASK_JSON_CREATOR_ID = "creator_id"; + public final static String GTASK_JSON_CREATOR_ID = "creator_id";//创建id - public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity";//子实体 - public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; + public final static String GTASK_JSON_CLIENT_VERSION = "client_version";//客户端 - public final static String GTASK_JSON_COMPLETED = "completed"; + public final static String GTASK_JSON_COMPLETED = "completed";//完成 - public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id";//当前列表id - public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id";//默认列表id - public final static String GTASK_JSON_DELETED = "deleted"; + public final static String GTASK_JSON_DELETED = "deleted";//删除 public final static String GTASK_JSON_DEST_LIST = "dest_list"; @@ -58,47 +58,47 @@ public class GTaskStringUtils { public final static String GTASK_JSON_GET_DELETED = "get_deleted"; - public final static String GTASK_JSON_ID = "id"; + public final static String GTASK_JSON_ID = "id";//id - public final static String GTASK_JSON_INDEX = "index"; + public final static String GTASK_JSON_INDEX = "index";//索引 - public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified";//最后一次更改 - public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point";//最后一次同步 - public final static String GTASK_JSON_LIST_ID = "list_id"; + public final static String GTASK_JSON_LIST_ID = "list_id";//列表id - public final static String GTASK_JSON_LISTS = "lists"; + public final static String GTASK_JSON_LISTS = "lists";//列表 - public final static String GTASK_JSON_NAME = "name"; + public final static String GTASK_JSON_NAME = "name";//名字 - public final static String GTASK_JSON_NEW_ID = "new_id"; + public final static String GTASK_JSON_NEW_ID = "new_id";//新id - public final static String GTASK_JSON_NOTES = "notes"; + public final static String GTASK_JSON_NOTES = "notes";//便签 - public final static String GTASK_JSON_PARENT_ID = "parent_id"; + public final static String GTASK_JSON_PARENT_ID = "parent_id";//父id public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; - public final static String GTASK_JSON_RESULTS = "results"; + public final static String GTASK_JSON_RESULTS = "results";//结果 - public final static String GTASK_JSON_SOURCE_LIST = "source_list"; + public final static String GTASK_JSON_SOURCE_LIST = "source_list";//源列表 - public final static String GTASK_JSON_TASKS = "tasks"; + public final static String GTASK_JSON_TASKS = "tasks";//任务 - public final static String GTASK_JSON_TYPE = "type"; + public final static String GTASK_JSON_TYPE = "type";//类型 - public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; + public final static String GTASK_JSON_TYPE_GROUP = "GROUP";//组类型 - public final static String GTASK_JSON_TYPE_TASK = "TASK"; + public final static String GTASK_JSON_TYPE_TASK = "TASK";//任务类型 - public final static String GTASK_JSON_USER = "user"; + public final static String GTASK_JSON_USER = "user";//使用者 - public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; + public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]";//小米便签 - public final static String FOLDER_DEFAULT = "Default"; + public final static String FOLDER_DEFAULT = "Default";//默认 - public final static String FOLDER_CALL_NOTE = "Call_Note"; + public final static String FOLDER_CALL_NOTE = "Call_Note";//呼叫标签 public final static String FOLDER_META = "METADATA"; diff --git a/src/main/java/net/micode/notes/tool/ResourceParser.java b/src/main/java/net/micode/notes/tool/ResourceParser.java index 1ad3ad6..d90f65f 100644 --- a/src/main/java/net/micode/notes/tool/ResourceParser.java +++ b/src/main/java/net/micode/notes/tool/ResourceParser.java @@ -21,25 +21,38 @@ import android.preference.PreferenceManager; import net.micode.notes.R; import net.micode.notes.ui.NotesPreferenceActivity; - +/*1. 简介:字面意义是资源分析器,实际上就是获取资源并且在程序中使用,比如颜色图片等 + 实现方法:主要利用R.java这个类,其中包括 + R.id 组件资源引用 + R.drawable 图片资源 (被使用) + R.layout 布局资源 + R.menu 菜单资源 + R.String 文字资源 + R.style 主题资源 (被使用) + 在按顺序设置好相应的id后,就可以编写简单的getXXX函数获取需要的资源 + + 特殊的变量 : + @BG_DEFAULT_COLOR 默认背景颜色(黄) + BG_DEFAULT_FONT_SIZE 默认文本大小(中)*/ public class ResourceParser { - + //以下五个为颜色常量赋值 public static final int YELLOW = 0; public static final int BLUE = 1; public static final int WHITE = 2; public static final int GREEN = 3; public static final int RED = 4; - + //为默认背景颜色常量赋值 public static final int BG_DEFAULT_COLOR = YELLOW; - + //为文本大小常量赋值 public static final int TEXT_SMALL = 0; public static final int TEXT_MEDIUM = 1; public static final int TEXT_LARGE = 2; public static final int TEXT_SUPER = 3; - + //为默认文字大小常量赋值 public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; - + //便签背景资源 public static class NoteBgResources { + //便签编辑背景颜色数组 private final static int [] BG_EDIT_RESOURCES = new int [] { R.drawable.edit_yellow, R.drawable.edit_blue, @@ -47,7 +60,7 @@ public class ResourceParser { R.drawable.edit_green, R.drawable.edit_red }; - + //便签编辑标题颜色数组 private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { R.drawable.edit_title_yellow, R.drawable.edit_title_blue, @@ -55,16 +68,16 @@ public class ResourceParser { R.drawable.edit_title_green, R.drawable.edit_title_red }; - + //获取便签背景资源 public static int getNoteBgResource(int id) { return BG_EDIT_RESOURCES[id]; } - + //获取便签标题背景资源 public static int getNoteTitleBgResource(int id) { return BG_EDIT_TITLE_RESOURCES[id]; } } - + //如果没有要求就获取默认背景id public static int getDefaultBgId(Context context) { if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { @@ -73,8 +86,9 @@ public class ResourceParser { return BG_DEFAULT_COLOR; } } - + //便签项目背景颜色设置 public static class NoteItemBgResources { + //背景上方颜色设置 private final static int [] BG_FIRST_RESOURCES = new int [] { R.drawable.list_yellow_up, R.drawable.list_blue_up, @@ -82,7 +96,7 @@ public class ResourceParser { R.drawable.list_green_up, R.drawable.list_red_up }; - + //背景默认颜色设置 private final static int [] BG_NORMAL_RESOURCES = new int [] { R.drawable.list_yellow_middle, R.drawable.list_blue_middle, @@ -90,7 +104,7 @@ public class ResourceParser { R.drawable.list_green_middle, R.drawable.list_red_middle }; - + //背景下方颜色设置 private final static int [] BG_LAST_RESOURCES = new int [] { R.drawable.list_yellow_down, R.drawable.list_blue_down, @@ -98,7 +112,7 @@ public class ResourceParser { R.drawable.list_green_down, R.drawable.list_red_down, }; - + //背景单一颜色设置 private final static int [] BG_SINGLE_RESOURCES = new int [] { R.drawable.list_yellow_single, R.drawable.list_blue_single, @@ -106,29 +120,30 @@ public class ResourceParser { R.drawable.list_green_single, R.drawable.list_red_single }; - + //获取背景上方颜色 public static int getNoteBgFirstRes(int id) { return BG_FIRST_RESOURCES[id]; } - + //获取背景下方颜色 public static int getNoteBgLastRes(int id) { return BG_LAST_RESOURCES[id]; } - + //获取背景单一颜色 public static int getNoteBgSingleRes(int id) { return BG_SINGLE_RESOURCES[id]; } - + //获取背景默认颜色 public static int getNoteBgNormalRes(int id) { return BG_NORMAL_RESOURCES[id]; } - + //获取文件夹背景颜色 public static int getFolderBgRes() { return R.drawable.list_folder; } } - + //此类设置widget(窗口)背景颜色 public static class WidgetBgResources { + //设置2*2窗口背景颜色 private final static int [] BG_2X_RESOURCES = new int [] { R.drawable.widget_2x_yellow, R.drawable.widget_2x_blue, @@ -136,11 +151,11 @@ public class ResourceParser { R.drawable.widget_2x_green, R.drawable.widget_2x_red, }; - + //获取2*2窗口背景颜色 public static int getWidget2xBgResource(int id) { return BG_2X_RESOURCES[id]; } - + //设置4*4窗口背景颜色 private final static int [] BG_4X_RESOURCES = new int [] { R.drawable.widget_4x_yellow, R.drawable.widget_4x_blue, @@ -148,20 +163,21 @@ public class ResourceParser { R.drawable.widget_4x_green, R.drawable.widget_4x_red }; - + //获取4*4窗口背景颜色 public static int getWidget4xBgResource(int id) { return BG_4X_RESOURCES[id]; } } - + //此类设置文本显示字体大小 public static class TextAppearanceResources { + //设置文本显示字体大小 private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { R.style.TextAppearanceNormal, R.style.TextAppearanceMedium, R.style.TextAppearanceLarge, R.style.TextAppearanceSuper }; - + //获取文本显示文字字体大小,如果id大于显示的长度则返回默认字体大小 public static int getTexAppearanceResource(int id) { /** * HACKME: Fix bug of store the resource id in shared preference. @@ -173,7 +189,7 @@ public class ResourceParser { } return TEXTAPPEARANCE_RESOURCES[id]; } - + //获取文本显示的长度 public static int getResourcesSize() { return TEXTAPPEARANCE_RESOURCES.length; } diff --git a/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java b/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java index ec6f819..a133555 100644 --- a/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java +++ b/src/main/java/net/micode/notes/widget/NoteWidgetProvider.java @@ -33,23 +33,26 @@ import net.micode.notes.ui.NoteEditActivity; import net.micode.notes.ui.NotesListActivity; public abstract class NoteWidgetProvider extends AppWidgetProvider { - public static final String [] PROJECTION = new String [] { + //note小部件类继承app小部件类且为抽象类待继承 + public static final String [] PROJECTION = new String [] {//设置便签挂饰数据的表头 NoteColumns.ID, NoteColumns.BG_COLOR_ID, - NoteColumns.SNIPPET + NoteColumns.SNIPPET//(片段,摘录) }; public static final int COLUMN_ID = 0; public static final int COLUMN_BG_COLOR_ID = 1; public static final int COLUMN_SNIPPET = 2; - private static final String TAG = "NoteWidgetProvider"; + private static final String TAG = "NoteWidgetProvider";//定义该类的名称 @Override public void onDeleted(Context context, int[] appWidgetIds) { + //调用AppWidgetManager中的INVALID_APPWIDGET_ID将挂件ID设置为无效,以达到删除挂件的目的 ContentValues values = new ContentValues(); - values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);//将新的widget信息存入数据库 for (int i = 0; i < appWidgetIds.length; i++) { + //遍历并修改所有的URI值 context.getContentResolver().update(Notes.CONTENT_NOTE_URI, values, NoteColumns.WIDGET_ID + "=?", @@ -58,6 +61,7 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { } private Cursor getNoteWidgetInfo(Context context, int widgetId) { + //得到NoteWidget信息 return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", @@ -66,23 +70,26 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { } protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + //小米便签挂件appWidgetlds信息的返回与更新 update(context, appWidgetManager, appWidgetIds, false); } private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, boolean privacyMode) { - for (int i = 0; i < appWidgetIds.length; i++) { - if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { + //更新widget的信息方法 + for (int i = 0; i < appWidgetIds.length; i++) {//对每一个appwidget遍历 + if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) {//不是被删除的widget int bgId = ResourceParser.getDefaultBgId(context); String snippet = ""; - Intent intent = new Intent(context, NoteEditActivity.class); + Intent intent = new Intent(context, NoteEditActivity.class);//创建Intent对象以用于Activity之间传递参数 intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); - intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);//附加组件id + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());//附加组件类型 Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); if (c != null && c.moveToFirst()) { if (c.getCount() > 1) { + //处理多个窗口同位出现的情况 Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); c.close(); return; @@ -90,43 +97,47 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { snippet = c.getString(COLUMN_SNIPPET); bgId = c.getInt(COLUMN_BG_COLOR_ID); intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); - intent.setAction(Intent.ACTION_VIEW); + intent.setAction(Intent.ACTION_VIEW);//为intent设置一个行为 } else { + ////若无关联内容则新建便签 snippet = context.getResources().getString(R.string.widget_havenot_content); - intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT);//为intent设置一个行为 } if (c != null) { - c.close(); + c.close();//关闭游标 } - + //主要是获取对应视图 RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); /** * Generate the pending intent to start host for the widget + * 为小部件生成启动主机的挂起意图 */ PendingIntent pendingIntent = null; if (privacyMode) { + //判定是否是私密模式 rv.setTextViewText(R.id.widget_text, context.getString(R.string.widget_under_visit_mode)); pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent( context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); } else { + //设置按钮,对点击事件进行处理 rv.setTextViewText(R.id.widget_text, snippet); pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, PendingIntent.FLAG_UPDATE_CURRENT); } - rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); - appWidgetManager.updateAppWidget(appWidgetIds[i], rv); + rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);//窗口服务部件 + appWidgetManager.updateAppWidget(appWidgetIds[i], rv);//更新widget的信息 } } } - protected abstract int getBgResourceId(int bgId); + protected abstract int getBgResourceId(int bgId);//从背景资源中获取当前应用ID - protected abstract int getLayoutId(); + protected abstract int getLayoutId();//获取布局ID - protected abstract int getWidgetType(); + protected abstract int getWidgetType();//获取widget类型 } diff --git a/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java index adcb2f7..945574c 100644 --- a/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java +++ b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_2x.java @@ -25,22 +25,22 @@ import net.micode.notes.tool.ResourceParser; public class NoteWidgetProvider_2x extends NoteWidgetProvider { - @Override + //2*2窗口大小 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.update(context, appWidgetManager, appWidgetIds); } - @Override + //获取布局id protected int getLayoutId() { return R.layout.widget_2x; } - @Override + //获取背景资源id protected int getBgResourceId(int bgId) { return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); } - @Override + //获取窗口类型id protected int getWidgetType() { return Notes.TYPE_WIDGET_2X; } diff --git a/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java index c12a02e..1b516b6 100644 --- a/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java +++ b/src/main/java/net/micode/notes/widget/NoteWidgetProvider_4x.java @@ -25,21 +25,21 @@ import net.micode.notes.tool.ResourceParser; public class NoteWidgetProvider_4x extends NoteWidgetProvider { - @Override + //4*4窗口大小 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.update(context, appWidgetManager, appWidgetIds); } - + //获取布局信息 protected int getLayoutId() { return R.layout.widget_4x; } - @Override + //获取背景资源信息 protected int getBgResourceId(int bgId) { return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); } - @Override + //获取窗口类型信息 protected int getWidgetType() { return Notes.TYPE_WIDGET_4X; }