();
}
-
- if(sContactCache.containsKey(phoneNumber)) { //接下来,如果sContactCache中包含给定电话号码的键值对,则直接返回缓存中的联系人姓名。
+// 如果sContactCache中已经包含了phoneNumber对应的联系人姓名,则直接返回缓存中的姓名
+ if(sContactCache.containsKey(phoneNumber)) {
return sContactCache.get(phoneNumber);
}
- String selection = CALLER_ID_SELECTION.replace("+", //首先将给定的电话号码转换为最小匹配形式,然后使用replace()方法将查询条件中的"+"替换为最小匹配的电话号码形式。
+ String selection = CALLER_ID_SELECTION.replace("+",
PhoneNumberUtils.toCallerIDMinMatch(phoneNumber));
- Cursor cursor = context.getContentResolver().query( //执行了一个查询操作,该方法会返回一个Cursor对象,用于遍历查询结果
- Data.CONTENT_URI, //指定了要查询的数据表的URI,表示通讯录数据。
- new String [] { Phone.DISPLAY_NAME }, //是要查询的列名,这里是查询联系人的显示名称。
- selection, //是查询条件,根据前面处理过的最小匹配电话号码来查询匹配的联系人信息。
- new String[] { phoneNumber }, //是查询条件中的参数值,用于替换查询条件中的"?"占位符。
- null); //最后一个参数是排序方式,这里为空,表示不进行排序。
-
- if (cursor != null && cursor.moveToFirst()) { //这个条件语句检查Cursor对象是否不为空,并且能够将游标移动到第一行。如果满足条件,则表示查询结果非空且至少存在一个匹配项。
+ Cursor cursor = context.getContentResolver().query(
+ Data.CONTENT_URI,
+ new String [] { Phone.DISPLAY_NAME },
+ selection,
+ new String[] { phoneNumber },
+ null);
+// 如果查询结果不为空同时在移动到第一条记录的情况下,将从Cursor中获取联系人姓名
+ if (cursor != null && cursor.moveToFirst()) {
try {
- String name = cursor.getString(0); //获取查询结果中第一列(索引为0)的数据,即联系人的显示名称。
- sContactCache.put(phoneNumber, name); //将此信息存储在sContactCache缓存中
+ String name = cursor.getString(0);
+ sContactCache.put(phoneNumber, name);
return name;
- } catch (IndexOutOfBoundsException e) { //如果在获取查询结果的过程中发生异常,说明查询结果中没有有效数据,此时会打印错误日志并返回null
+ } catch (IndexOutOfBoundsException e) {
Log.e(TAG, " Cursor get string error " + e.toString());
return null;
- } finally { //无论是否出现异常,最后都会通过cursor.close()方法关闭Cursor对象,释放资源。
+ } finally {
cursor.close();
}
- } else { //如果查询结果为空或者没有匹配项,就会执行这个分支。它会打印调试日志,指示没有找到与给定电话号码匹配的联系人,并返回null。
+ } else {
+ // 如果查询结果为空,打印日志并返回null表示没有找到匹配的联系人
Log.d(TAG, "No contact matched with number:" + phoneNumber);
return null;
}
}
}
-
diff --git a/src/Notes2/src/net/micode/notes/data/Notes.java b/src/Notes2/src/net/micode/notes/data/Notes.java
index 3820220..7cf0140 100644
--- a/src/Notes2/src/net/micode/notes/data/Notes.java
+++ b/src/Notes2/src/net/micode/notes/data/Notes.java
@@ -1,26 +1,14 @@
-/*
- * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package net.micode.notes.data;
+import android.content.ContentUris;
import android.net.Uri;
+// Notes 类中定义了很多常量,这些常量大多是int型和string型
public class Notes {
- public static final String AUTHORITY = "micode_notes"; //定义了一个字符串常量AUTHORITY,代表了内容提供者的授权信息。
- public static final String TAG = "Notes"; //定义了一个字符串常量TAG,可能用于在日志中进行标记或调试。
- public static final int TYPE_NOTE = 0; //定义了三个整型常量,分别表示笔记、文件夹和系统类型。
+ public static final String AUTHORITY = "micode_notes";
+ public static final String TAG = "Notes";
+
+ //以下三个常量对NoteColumns.TYPE的值进行设置时会用到
+ public static final int TYPE_NOTE = 0;
public static final int TYPE_FOLDER = 1;
public static final int TYPE_SYSTEM = 2;
@@ -30,23 +18,35 @@ public class Notes {
* {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder
* {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records
*/
- public static final int ID_ROOT_FOLDER = 0; //定义了一些文件夹的标识符常量。ID_ROOT_FOLDER表示根文件夹的标识符为0
- public static final int ID_TEMPARAY_FOLDER = -1; //表示临时文件夹的标识符为-1
- public static final int ID_CALL_RECORD_FOLDER = -2; //表示通话记录文件夹的标识符为-2
- public static final int ID_TRASH_FOLER = -3; //ID_TRASH_FOLER表示回收站文件夹的标识符为-3
- //定义了一些 Intent 传递参数的键名常量
- 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";//小部件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";//文件夹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; //2x大小的小部件类型
- public static final int TYPE_WIDGET_4X = 1; //4x
-
- public static class DataConstants { //内部静态类(定义在一个类的内部,无法从内部静态类的实例中访问外部类的非静态成员)
+ public static final int ID_ROOT_FOLDER = 0;
+ public static final int ID_TEMPARAY_FOLDER = -1;
+ public static final int ID_CALL_RECORD_FOLDER = -2;
+ public static final int ID_TRASH_FOLER = -3;
+
+ public static final String INTENT_EXTRA_ALERT_DATE =
+
+ "net.micode.notes.alert_date";
+ 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";
+ 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_2X = 0;
+ public static final int TYPE_WIDGET_4X = 1;
+
+ public static class DataConstants {
public static final String NOTE = TextNote.CONTENT_ITEM_TYPE;
public static final String CALL_NOTE = CallNote.CONTENT_ITEM_TYPE;
}
@@ -54,18 +54,20 @@ public class Notes {
/**
* 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
*/
- public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");//可以用于在应用程序中执行查询操作,以获取特定类型的数据。
+ public static final Uri CONTENT_DATA_URI = Uri.parse("content://" +
- /**
- * 定义了一个Java接口NoteColumns,用于定义笔记或文件夹的列名常量。
- */
- //Uri(统一资源标识符)是用来唯一标识资源的字符串格式。在Android中,Uri经常被用于访问和操作应用程序中的数据
+ AUTHORITY + "/data");//定义查找数据的指针。
+ // 定义NoteColumns的常量,用于后面创建数据库的表头
public interface NoteColumns {
/**
* The unique ID for a row
@@ -77,7 +79,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";//为什么会有parent_id
/**
* Created data for note or folder
@@ -145,7 +147,7 @@ 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";//同步
/**
* Sign to indicate local modified or not
@@ -170,11 +172,9 @@ public class Notes {
* Type : INTEGER (long)
*/
public static final String VERSION = "version";
- }
+ }//这些常量主要是定义便签的属性的。
- /**
- * 定义了一个Java接口DataColumns,用于存储笔记和文件夹的相关信息。
- */
+ // 定义DataColumns的常量,用于后面创建数据库的表头
public interface DataColumns {
/**
* The unique ID for a row
@@ -214,56 +214,66 @@ 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
* Type: INTEGER
*/
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
* Type: INTEGER
*/
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
* Type: TEXT
*/
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
* Type: TEXT
*/
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
* Type: TEXT
*/
public static final String DATA5 = "data5";
- }
-
+ }//主要是定义存储便签内容数据的
public static final class TextNote implements DataColumns {
/**
* 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;
- public static final int MODE_CHECK_LIST = 1; //1是检查模式,0是普通模式
+ public static final int MODE_CHECK_LIST = 1;
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note";//MIME类型,指定返回的数据类型为目录类型
+ 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");//标示URI,访问内容
- }
+ 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 {
/**
@@ -276,12 +286,18 @@ public class Notes {
* 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 =
- 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");//表示通话记录的内容URI,用于访问通话记录的内容。
- }
+ 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");
+ }//电话内容的数据结构
}
\ No newline at end of file
diff --git a/src/Notes2/src/net/micode/notes/data/NotesDatabaseHelper.java b/src/Notes2/src/net/micode/notes/data/NotesDatabaseHelper.java
index 744c9f3..ffe5d57 100644
--- a/src/Notes2/src/net/micode/notes/data/NotesDatabaseHelper.java
+++ b/src/Notes2/src/net/micode/notes/data/NotesDatabaseHelper.java
@@ -27,57 +27,50 @@ 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"; //私有变量
+public class NotesDatabaseHelper extends SQLiteOpenHelper {
+ 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 { //内部接口table
- public static final String NOTE = "note"; //笔记本的名字叫note
+ public interface TABLE {
+ public static final String NOTE = "note";
- public static final String DATA = "data"; //数据表的名字叫data
+ public static final String DATA = "data";
}
- private static final String TAG = "NotesDatabaseHelper"; //日志标签,用于在日志中标记该类的信息
+ private static final String TAG = "NotesDatabaseHelper";
- private static NotesDatabaseHelper mInstance; //mInstance会在NotesDatabaseHelper类中作为单例模式的实现,以确保在应用程序中只有一个NotesDatabaseHelper类的实例被创建并被全局范围内所使用。
+ private static NotesDatabaseHelper mInstance;
- /**
- * 创建两个数据库表,分别存储笔记和与笔记相关的数据,以及相应的索引。
- */
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
- NoteColumns.ID + " INTEGER PRIMARY KEY," + //主键(保证表中的每一行都有唯一性)
- NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + //父级的id
- NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + //用于标识的标识符
- NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + //背景颜色
- NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + //笔记的创建时间
- NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + //表示是否包含部件
- NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + //笔记的修改时间
- NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + //子笔记的数量
- NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + //笔记的摘要或片段内容
- NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + //类型
- NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + //关联的小部件的id
- NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + //小部件的类型
- NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + //用于同步的id,与远程同步服务有关
- NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + //笔记是否在本地被修改
- NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + //原始父级的id
- NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + //google任务服务的id
- NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + //笔记的版本号
+ NoteColumns.ID + " INTEGER PRIMARY KEY," +
+ NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
+ NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
+ NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
+ NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";
- /**
- * 创建数据表的SQL语句创建数据表的SQL语句
- */
-
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
- DataColumns.ID + " INTEGER PRIMARY KEY," + //DataColumns.ID表示一个名为"ID"的列,数据类型为INTEGER(整数),并且被定义为主键。
- DataColumns.MIME_TYPE + " TEXT NOT NULL," + //版本
- DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + //笔记的名称
- NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + //创建时间
- NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + //上一次修改时间
- DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," + //摘要
+ DataColumns.ID + " INTEGER PRIMARY KEY," +
+ DataColumns.MIME_TYPE + " TEXT NOT NULL," +
+ DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
@@ -213,18 +206,10 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //类的继承,
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
- /**
- * 接受cotext参数(包含了应用程序的运行环境信息),用于创建和打开数据库
- * @param context
- */
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
- /**
- * (创建名为note的表,并且为该表重新创建触发器和创建系统文件夹。)
- * @param db
- */
public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL);
reCreateNoteTableTriggers(db);
@@ -250,10 +235,6 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //类的继承,
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
}
- /**
- * 在数据库中创建系统级别的文件夹。
- * @param db
- */
private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues();
@@ -289,10 +270,6 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //类的继承,
db.insert(TABLE.NOTE, null, values);
}
- /**
- * 用于创建数据表,其中包括执行创建表的SQL语句、重新创建触发器以及创建索引,并在完成之后记录日志。
- * @param db
- */
public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL);
reCreateDataTableTriggers(db);
@@ -300,10 +277,6 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //类的继承,
Log.d(TAG, "data table has been created");
}
- /**
- * 用于重新创建数据表的触发器。首先,它会删除已存在的触发器,然后再重新创建触发器。
- * @param 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_update");
@@ -314,47 +287,37 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //类的继承,
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
}
- static synchronized NotesDatabaseHelper getInstance(Context context) { //static synchronized 是Java中的修饰符,用于同时指定一个方法或代码块为静态和同步。
+ static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context);
}
return mInstance;
}
- /**
- * 系统的首次创建
- * @param db
- */
@Override
public void onCreate(SQLiteDatabase db) {
createNoteTable(db);
createDataTable(db);
}
- /**
- * 数据库升级
- * @param db
- * @param oldVersion
- * @param newVersion
- */
@Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //db是要升级的数据库对象,oldVersion是当前数据库版本号,newVersion是要升级到的新版本号。
- boolean reCreateTriggers = false; //是否重新创建触发器和是否跳过V2版本的升级。
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ boolean reCreateTriggers = false;
boolean skipV2 = false;
- if (oldVersion == 1) { //执行升级到V2版本的操作。
+ if (oldVersion == 1) {
upgradeToV2(db);
skipV2 = true; // this upgrade including the upgrade from v2 to v3
oldVersion++;
}
- if (oldVersion == 2 && !skipV2) { //执行升级到V3版本的操作。
+ if (oldVersion == 2 && !skipV2) {
upgradeToV3(db);
reCreateTriggers = true;
oldVersion++;
}
- if (oldVersion == 3) { //执行升级到V4版本的操作。
+ if (oldVersion == 3) {
upgradeToV4(db);
oldVersion++;
}
@@ -364,36 +327,36 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper { //类的继承,
reCreateDataTableTriggers(db);
}
- if (oldVersion != newVersion) { //判断升级后的数据库版本号是否与目标版本号相等。如果不相等,则抛出一个异常。
+ if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails");
}
}
private void upgradeToV2(SQLiteDatabase db) {
- db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); //删除名为Note和Data的表。
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
- createNoteTable(db); //创建新的表
+ createNoteTable(db);
createDataTable(db);
}
private void upgradeToV3(SQLiteDatabase db) {
// drop unused triggers
- db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert"); //删除三个触发器
+ db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
// add a column for gtask id
- db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID //向Note表中添加一个名为gtask_id的列。该列的数据类型为TEXT,非空,并设置默认值为空字符串。
+ db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''");
// add a trash system folder
- ContentValues values = new ContentValues(); //创建一个ContentValues对象,用于存储待插入到数据库的键值对。
- values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); //系统级别的文件夹,用于存放已经删除的笔记。
- values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); //表示向Note表中插入的记录类型为Notes.TYPE_SYSTEM,即系统级别的记录
+ ContentValues values = new ContentValues();
+ values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
+ values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
private void upgradeToV4(SQLiteDatabase db) {
- db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION //向Note表中添加一个名为version的列。该列的数据类型为INTEGER
+ db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
-}
\ No newline at end of file
+}
diff --git a/src/Notes2/src/net/micode/notes/gtask/remote/GTaskASyncTask.java b/src/Notes2/src/net/micode/notes/gtask/remote/GTaskASyncTask.java
index b3b61e7..b71470c 100644
--- a/src/Notes2/src/net/micode/notes/gtask/remote/GTaskASyncTask.java
+++ b/src/Notes2/src/net/micode/notes/gtask/remote/GTaskASyncTask.java
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+//执行与 GTask(Google 任务)相关的同步操作,并在执行过程中显示通知,并在操作完成后调用回调接口通知完成事件。
package net.micode.notes.gtask.remote;
@@ -28,7 +29,6 @@ import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
-
public class GTaskASyncTask extends AsyncTask {
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
@@ -37,13 +37,13 @@ public class GTaskASyncTask extends AsyncTask {
void onComplete();
}
- private Context mContext;
+ private Context mContext;//成员变量——上下文对象,用于获取系统服务。
- private NotificationManager mNotifiManager;
+ private NotificationManager mNotifiManager;//成员变量——通知管理器,用于发送通知。
- private GTaskManager mTaskManager;
+ private GTaskManager mTaskManager;//成员变量——GTaskManager 实例,用于执行 GTask 相关的操作。
- private OnCompleteListener mOnCompleteListener;
+ private OnCompleteListener mOnCompleteListener;//成员变量——任务完成的回调接口。
public GTaskASyncTask(Context context, OnCompleteListener listener) {
mContext = context;
@@ -53,16 +53,19 @@ public class GTaskASyncTask extends AsyncTask {
mTaskManager = GTaskManager.getInstance();
}
+ //取消同步操作,调用 mTaskManager.cancelSync()
public void cancelSync() {
mTaskManager.cancelSync();
}
+ //更新执行进度,调用 publishProgress(),并传入进度信息。
public void publishProgess(String message) {
publishProgress(new String[] {
message
});
}
+ //向用户提示当前同步的状态,显示通知,是一个用于交互的方法
private void showNotification(int tickerId, String content) {
Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis());
@@ -77,11 +80,14 @@ public class GTaskASyncTask extends AsyncTask {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0);
}
- notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
- pendingIntent);
+ // notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
+// pendingIntent);
+ notification.contentIntent = pendingIntent;
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
+
}
+ //此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间
@Override
protected Integer doInBackground(Void... unused) {
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
@@ -89,6 +95,7 @@ public class GTaskASyncTask extends AsyncTask {
return mTaskManager.sync(mContext, this);
}
+ //可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
@Override
protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]);
@@ -97,6 +104,7 @@ public class GTaskASyncTask extends AsyncTask {
}
}
+ //相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI
@Override
protected void onPostExecute(Integer result) {
if (result == GTaskManager.STATE_SUCCESS) {
diff --git a/src/Notes2/src/net/micode/notes/gtask/remote/GTaskClient.java b/src/Notes2/src/net/micode/notes/gtask/remote/GTaskClient.java
index cfdd529..9f1c9dd 100644
--- a/src/Notes2/src/net/micode/notes/gtask/remote/GTaskClient.java
+++ b/src/Notes2/src/net/micode/notes/gtask/remote/GTaskClient.java
@@ -13,6 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/*
+ * 主要功能:实现GTASK的登录操作,进行GTASK任务的创建,创建任务列表,从网络上获取任务和任务列表的内容
+ * 主要使用类或技术:accountManager JSONObject HttpParams authToken Gid
+ */
package net.micode.notes.gtask.remote;
@@ -60,7 +64,6 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
-<<<<<<< HEAD
//标明了这个类的名字
public class GTaskClient {
private static final String TAG = GTaskClient.class.getSimpleName(); //私有化一个用于日志输出的标签常量
@@ -95,40 +98,6 @@ public class GTaskClient {
//GTaskClient 类的一个私有构造方法,使用 private 关键字修饰,表示只能在类内部调用
private GTaskClient() {
mHttpClient = null; //初始化为null
-=======
-
-public class GTaskClient {
- private static final String TAG = GTaskClient.class.getSimpleName();
-
- private static final String GTASK_URL = "https://mail.google.com/tasks/";
-
- private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig";
-
- private static final String GTASK_POST_URL = "https://mail.google.com/tasks/r/ig";
-
- private static GTaskClient mInstance = null;
-
- private DefaultHttpClient mHttpClient;
-
- private String mGetUrl;
-
- private String mPostUrl;
-
- private long mClientVersion;
-
- private boolean mLoggedin;
-
- private long mLastLoginTime;
-
- private int mActionId;
-
- private Account mAccount;
-
- private JSONArray mUpdateArray;
-
- private GTaskClient() {
- mHttpClient = null;
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
mClientVersion = -1;
@@ -139,7 +108,6 @@ public class GTaskClient {
mUpdateArray = null;
}
-<<<<<<< HEAD
//用来获取的实例化对象
public static synchronized GTaskClient getInstance() { //使用 public 关键字修饰,表示可以从任何地方访问
if (mInstance == null) { //首先判断 mInstance 是否为 null,即判断是否已经存在单例实例
@@ -258,121 +226,11 @@ public class GTaskClient {
//尝试登陆Gtask,这只是一个预先判断令牌是否是有效以及是否能登上GTask的方法,而不是具体实现登陆的方法
-=======
- public static synchronized GTaskClient getInstance() {
- if (mInstance == null) {
- mInstance = new GTaskClient();
- }
- return mInstance;
- }
-
- public boolean login(Activity activity) {
- // we suppose that the cookie would expire after 5 minutes
- // then we need to re-login
- final long interval = 1000 * 60 * 5;
- if (mLastLoginTime + interval < System.currentTimeMillis()) {
- mLoggedin = false;
- }
-
- // need to re-login after account switch
- if (mLoggedin
- && !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity
- .getSyncAccountName(activity))) {
- mLoggedin = false;
- }
-
- if (mLoggedin) {
- Log.d(TAG, "already logged in");
- return true;
- }
-
- mLastLoginTime = System.currentTimeMillis();
- String authToken = loginGoogleAccount(activity, false);
- if (authToken == null) {
- Log.e(TAG, "login google account failed");
- return false;
- }
-
- // login with custom domain if necessary
- if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
- .endsWith("googlemail.com"))) {
- StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
- int index = mAccount.name.indexOf('@') + 1;
- String suffix = mAccount.name.substring(index);
- url.append(suffix + "/");
- mGetUrl = url.toString() + "ig";
- mPostUrl = url.toString() + "r/ig";
-
- if (tryToLoginGtask(activity, authToken)) {
- mLoggedin = true;
- }
- }
-
- // try to login with google official url
- if (!mLoggedin) {
- mGetUrl = GTASK_GET_URL;
- mPostUrl = GTASK_POST_URL;
- if (!tryToLoginGtask(activity, authToken)) {
- return false;
- }
- }
-
- mLoggedin = true;
- return true;
- }
-
- private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
- String authToken;
- AccountManager accountManager = AccountManager.get(activity);
- Account[] accounts = accountManager.getAccountsByType("com.google");
-
- if (accounts.length == 0) {
- Log.e(TAG, "there is no available google account");
- return null;
- }
-
- String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
- Account account = null;
- for (Account a : accounts) {
- if (a.name.equals(accountName)) {
- account = a;
- break;
- }
- }
- if (account != null) {
- mAccount = account;
- } else {
- Log.e(TAG, "unable to get an account with the same name in the settings");
- return null;
- }
-
- // get the token now
- AccountManagerFuture accountManagerFuture = accountManager.getAuthToken(account,
- "goanna_mobile", null, activity, null, null);
- try {
- Bundle authTokenBundle = accountManagerFuture.getResult();
- authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN);
- if (invalidateToken) {
- accountManager.invalidateAuthToken("com.google", authToken);
- loginGoogleAccount(activity, false);
- }
- } catch (Exception e) {
- Log.e(TAG, "get auth token failed");
- authToken = null;
- }
-
- return authToken;
- }
-
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) {
// maybe the auth token is out of date, now let's invalidate the
// token and try again
-<<<<<<< HEAD
//删除过一个无效的authToken,申请一个新的后再次尝试登陆
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
authToken = loginGoogleAccount(activity, true);
if (authToken == null) {
Log.e(TAG, "login google account failed");
@@ -387,7 +245,6 @@ public class GTaskClient {
return true;
}
-<<<<<<< HEAD
//实现登录GTask的具体操作
private boolean loginGtask(String authToken) {
int timeoutConnection = 10000;
@@ -397,22 +254,11 @@ public class GTaskClient {
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); //设置设置端口超时时间
mHttpClient = new DefaultHttpClient(httpParameters);
BasicCookieStore localBasicCookieStore = new BasicCookieStore(); //设置本地cookie
-=======
- private boolean loginGtask(String authToken) {
- int timeoutConnection = 10000;
- int timeoutSocket = 15000;
- HttpParams httpParameters = new BasicHttpParams();
- HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
- HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
- mHttpClient = new DefaultHttpClient(httpParameters);
- BasicCookieStore localBasicCookieStore = new BasicCookieStore();
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
mHttpClient.setCookieStore(localBasicCookieStore);
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false);
// login gtask
try {
-<<<<<<< HEAD
String loginUrl = mGetUrl + "?auth=" + authToken; //设置登录的url
HttpGet httpGet = new HttpGet(loginUrl); //通过登录的uri实例化网页上资源的查找
HttpResponse response = null;
@@ -423,17 +269,6 @@ public class GTaskClient {
List cookies = mHttpClient.getCookieStore().getCookies();
boolean hasAuthCookie = false;
for (Cookie cookie : cookies) { //看如果存有“GTL”,则说明有验证成功的有效的cookie
-=======
- String loginUrl = mGetUrl + "?auth=" + authToken;
- HttpGet httpGet = new HttpGet(loginUrl);
- HttpResponse response = null;
- response = mHttpClient.execute(httpGet);
-
- // get the cookie now
- List cookies = mHttpClient.getCookieStore().getCookies();
- boolean hasAuthCookie = false;
- for (Cookie cookie : cookies) {
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
if (cookie.getName().contains("GTL")) {
hasAuthCookie = true;
}
@@ -443,21 +278,14 @@ public class GTaskClient {
}
// get the client version
-<<<<<<< HEAD
//获取client的内容
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup(";
String jsEnd = ")}";
int begin = resString.indexOf(jsBegin);
int end = resString.lastIndexOf(jsEnd);
String jsString = null;
-<<<<<<< HEAD
if (begin != -1 && end != -1 && begin < end) { //if循环用来在返回的Content中截取从_setup(开始到)}中间的字符串内容,也就是gtask_url的内容
-=======
- if (begin != -1 && end != -1 && begin < end) {
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
jsString = resString.substring(begin + jsBegin.length(), end);
}
JSONObject js = new JSONObject(jsString);
@@ -479,15 +307,11 @@ public class GTaskClient {
return mActionId++;
}
-<<<<<<< HEAD
//实例化创建一个用于向网络传输数据的对象
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
httpPost.setHeader("AT", "1");
-<<<<<<< HEAD
return httpPost; //返回一个空的httpPost实例化对象
}
@@ -495,39 +319,21 @@ public class GTaskClient {
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
if (entity.getContentEncoding() != null) { //使用getContentEncoding()获取网络上的资源和数据
-=======
- return httpPost;
- }
-
- private String getResponseContent(HttpEntity entity) throws IOException {
- String contentEncoding = null;
- if (entity.getContentEncoding() != null) {
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
contentEncoding = entity.getContentEncoding().getValue();
Log.d(TAG, "encoding: " + contentEncoding);
}
InputStream input = entity.getContent();
-<<<<<<< HEAD
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) { //GZIP是使用DEFLATE进行压缩数据的另一个压缩库
input = new GZIPInputStream(entity.getContent());
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) { //DEFLATE是一个无专利的压缩算法,它可以实现无损数据压缩
-=======
- if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {
- input = new GZIPInputStream(entity.getContent());
- } else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
Inflater inflater = new Inflater(true);
input = new InflaterInputStream(entity.getContent(), inflater);
}
try {
InputStreamReader isr = new InputStreamReader(input);
-<<<<<<< HEAD
BufferedReader br = new BufferedReader(isr); //是一个包装类,它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了时候,再读入内存,是为了提供读的效率而设计的
-=======
- BufferedReader br = new BufferedReader(isr);
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
StringBuilder sb = new StringBuilder();
while (true) {
@@ -542,21 +348,15 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//通过JSON发送请求
//请求的具体内容在json的实例化对象js中然后传入
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) {
Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in");
}
-<<<<<<< HEAD
//实例化一个httpPost的对象用来向服务器传输数据,在这里就是发送请求,而请求的内容在js里
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
HttpPost httpPost = createHttpPost();
try {
LinkedList list = new LinkedList();
@@ -565,10 +365,7 @@ public class GTaskClient {
httpPost.setEntity(entity);
// execute the post
-<<<<<<< HEAD
//执行这个请求
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
HttpResponse response = mHttpClient.execute(httpPost);
String jsString = getResponseContent(response.getEntity());
return new JSONObject(jsString);
@@ -592,7 +389,6 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//创建单个任务
//传入参数是一个.gtask.data.Task包里Task类的对象
public void createTask(Task task) throws NetworkFailureException {
@@ -600,12 +396,6 @@ public class GTaskClient {
try {
JSONObject jsPost = new JSONObject();//利用json获取Task里的内容,并且创建相应的jsPost
-=======
- public void createTask(Task task) throws NetworkFailureException {
- commitUpdate();
- try {
- JSONObject jsPost = new JSONObject();
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
JSONArray actionList = new JSONArray();
// action_list
@@ -619,11 +409,7 @@ public class GTaskClient {
JSONObject jsResponse = postRequest(jsPost);
JSONObject jsResult = (JSONObject) jsResponse.getJSONArray(
GTaskStringUtils.GTASK_JSON_RESULTS).get(0);
-<<<<<<< HEAD
task.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID)); //使用task.setGid设置task的new_ID
-=======
- task.setGid(jsResult.getString(GTaskStringUtils.GTASK_JSON_NEW_ID));
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
} catch (JSONException e) {
Log.e(TAG, e.toString());
@@ -632,10 +418,7 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//创建一个任务列表
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate();
try {
@@ -662,7 +445,6 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//同步更新操作
public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) {
@@ -671,24 +453,11 @@ public class GTaskClient {
// action_list
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray); //使用jsPost.put,Put的信息包括UpdateArray和ClientVersion
-=======
- public void commitUpdate() throws NetworkFailureException {
- if (mUpdateArray != null) {
- try {
- JSONObject jsPost = new JSONObject();
-
- // action_list
- jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, mUpdateArray);
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
// client_version
jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
-<<<<<<< HEAD
postRequest(jsPost); //使用postRequest发送这个jspost,进行处理
-=======
- postRequest(jsPost);
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
mUpdateArray = null;
} catch (JSONException e) {
Log.e(TAG, e.toString());
@@ -698,20 +467,13 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//添加更新的事项
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) {
// too many update items may result in an error
// set max to 10 items
if (mUpdateArray != null && mUpdateArray.length() > 10) {
-<<<<<<< HEAD
commitUpdate(); //调用commitUpdate()来提交更新
-=======
- commitUpdate();
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
}
if (mUpdateArray == null)
@@ -720,10 +482,7 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//用来移动任务,它通过构建 JSON 对象和发送 POST 请求来实现任务的移动操作
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
commitUpdate();
@@ -733,11 +492,8 @@ public class GTaskClient {
JSONObject action = new JSONObject();
// action_list
-<<<<<<< HEAD
//type——移动类型,ID——操作的 ID,GTASK_JSON_ID——要移动的任务的 ID
//SOURCE_LIST——要移动任务的原始父任务列表的 ID,DEST_PARENT——要移动任务的新父任务列表的 ID
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_MOVE);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
@@ -745,27 +501,17 @@ public class GTaskClient {
if (preParent == curParent && task.getPriorSibling() != null) {
// put prioring_sibing_id only if moving within the tasklist and
// it is not the first one
-<<<<<<< HEAD
//设置优先级ID,只有当移动是发生在文件中
action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling());
}
action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid());//设置移动前所属列表
action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid());//设置当前所属列表
-=======
- action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling());
- }
- action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid());
- action.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT, curParent.getGid());
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
if (preParent != curParent) {
// put the dest_list only if moving between tasklists
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());
}
actionList.put(action);
-<<<<<<< HEAD
//最后将ACTION_LIST加入到jsPost中
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
@@ -780,7 +526,6 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//用来删除节点,它通过构建 JSON 对象和发送 POST 请求来实现节点的删除操作
public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate(); // 提交更新操作
@@ -858,84 +603,11 @@ public class GTaskClient {
JSONObject jsPost = new JSONObject();//创建一个新的 JSONObject jsPost 用于存储 POST 请求的数据。
JSONArray actionList = new JSONArray();//创建一个新的 JSONArray actionList 用于存列表。
JSONObject action = new JSONObject();//创建一个新的 JSONObject action 用于表示单个操作。
-=======
- public void deleteNode(Node node) throws NetworkFailureException {
- commitUpdate();
- try {
- JSONObject jsPost = new JSONObject();
- JSONArray actionList = new JSONArray();
-
- // action_list
- node.setDeleted(true);
- actionList.put(node.getUpdateAction(getActionId()));
- jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
-
- // client_version
- jsPost.put(GTaskStringUtils.GTASK_JSON_CLIENT_VERSION, mClientVersion);
-
- postRequest(jsPost);
- mUpdateArray = null;
- } catch (JSONException e) {
- Log.e(TAG, e.toString());
- e.printStackTrace();
- throw new ActionFailureException("delete node: handing jsonobject failed");
- }
- }
-
- public JSONArray getTaskLists() throws NetworkFailureException {
- if (!mLoggedin) {
- Log.e(TAG, "please login first");
- throw new ActionFailureException("not logged in");
- }
-
- try {
- HttpGet httpGet = new HttpGet(mGetUrl);
- HttpResponse response = null;
- response = mHttpClient.execute(httpGet);
-
- // get the task list
- String resString = getResponseContent(response.getEntity());
- String jsBegin = "_setup(";
- String jsEnd = ")}";
- int begin = resString.indexOf(jsBegin);
- int end = resString.lastIndexOf(jsEnd);
- String jsString = null;
- if (begin != -1 && end != -1 && begin < end) {
- jsString = resString.substring(begin + jsBegin.length(), end);
- }
- JSONObject js = new JSONObject(jsString);
- return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS);
- } catch (ClientProtocolException e) {
- Log.e(TAG, e.toString());
- e.printStackTrace();
- throw new NetworkFailureException("gettasklists: httpget failed");
- } catch (IOException e) {
- Log.e(TAG, e.toString());
- e.printStackTrace();
- throw new NetworkFailureException("gettasklists: httpget failed");
- } catch (JSONException e) {
- Log.e(TAG, e.toString());
- e.printStackTrace();
- throw new ActionFailureException("get task lists: handing jasonobject failed");
- }
- }
-
- public JSONArray getTaskList(String listGid) throws NetworkFailureException {
- commitUpdate();
- try {
- JSONObject jsPost = new JSONObject();
- JSONArray actionList = new JSONArray();
- JSONObject action = new JSONObject();
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
// action_list
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
-<<<<<<< HEAD
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());//这里设置为传入的listGid
-=======
- action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid);
action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false);
actionList.put(action);
@@ -953,18 +625,12 @@ public class GTaskClient {
}
}
-<<<<<<< HEAD
//用于获取同步账户信息
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
public Account getSyncAccount() {
return mAccount;
}
-<<<<<<< HEAD
//重置更新内容
-=======
->>>>>>> 3a7a23b9d2717a31b97b2a5c6deed09784b90564
public void resetUpdateArray() {
mUpdateArray = null;
}
diff --git a/src/Notes2/src/net/micode/notes/model/WorkingNote.java b/src/Notes2/src/net/micode/notes/model/WorkingNote.java
index be081e4..a1a2455 100644
--- a/src/Notes2/src/net/micode/notes/model/WorkingNote.java
+++ b/src/Notes2/src/net/micode/notes/model/WorkingNote.java
@@ -38,7 +38,7 @@ public class WorkingNote {
// Note Id
private long mNoteId;
// Note content
- private String mContent;
+ public String mContent;
// Note mode
private int mMode;
diff --git a/src/Notes2/src/net/micode/notes/tool/DataUtils.java b/src/Notes2/src/net/micode/notes/tool/DataUtils.java
index 2a14982..65eac90 100644
--- a/src/Notes2/src/net/micode/notes/tool/DataUtils.java
+++ b/src/Notes2/src/net/micode/notes/tool/DataUtils.java
@@ -34,10 +34,10 @@ 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 boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) {
+ public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) {//批量删除笔记
if (ids == null) {
Log.d(TAG, "the ids is null");
return true;
@@ -72,7 +72,7 @@ public class DataUtils {
return false;
}
- public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) {
+ public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) {//将笔记移动到指定文件夹。给定笔记的ID、源文件夹ID和目标文件夹ID,通过ContentValues设置新的父文件夹ID和原始父文件夹ID,然后调用ContentResolver的update方法更新笔记
ContentValues values = new ContentValues();
values.put(NoteColumns.PARENT_ID, desFolderId);
values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId);
@@ -80,7 +80,7 @@ public class DataUtils {
resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null);
}
- public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids,
+ public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids,//批量移动笔记到指定文件夹
long folderId) {
if (ids == null) {
Log.d(TAG, "the ids is null");
@@ -114,7 +114,7 @@ public class DataUtils {
/**
* Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}}
*/
- public static int getUserFolderCount(ContentResolver resolver) {
+ public static int getUserFolderCount(ContentResolver resolver) {//获取用户文件夹的数量
Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI,
new String[] { "COUNT(*)" },
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?",
@@ -135,7 +135,7 @@ public class DataUtils {
}
return count;
}
-
+//检查笔记是否在数据库中可见
public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) {
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
null,
@@ -152,7 +152,7 @@ public class DataUtils {
}
return exist;
}
-
+//检查笔记是否存在于数据库中
public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) {
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
null, null, null, null);
@@ -166,7 +166,7 @@ public class DataUtils {
}
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);
@@ -180,7 +180,7 @@ public class DataUtils {
}
return exist;
}
-
+//检查可见文件夹名称是否已存在
public static boolean checkVisibleFolderName(ContentResolver resolver, String name) {
Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null,
NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER +
@@ -223,7 +223,7 @@ public class DataUtils {
}
return set;
}
-
+//根据笔记ID获取通话号码
public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) {
Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,
new String [] { CallNote.PHONE_NUMBER },
@@ -242,7 +242,7 @@ public class DataUtils {
}
return "";
}
-
+//根据电话号码和通话日期获取笔记ID
public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) {
Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,
new String [] { CallNote.NOTE_ID },
@@ -263,7 +263,7 @@ public class DataUtils {
}
return 0;
}
-
+//根据笔记ID获取摘要内容
public static String getSnippetById(ContentResolver resolver, long noteId) {
Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
new String [] { NoteColumns.SNIPPET },
@@ -281,7 +281,7 @@ public class DataUtils {
}
throw new IllegalArgumentException("Note is not found with id: " + noteId);
}
-
+//格式化摘要内容
public static String getFormattedSnippet(String snippet) {
if (snippet != null) {
snippet = snippet.trim();
diff --git a/src/Notes2/src/net/micode/notes/ui/AlarmInitReceiver.java b/src/Notes2/src/net/micode/notes/ui/AlarmInitReceiver.java
index f221202..5a555c0 100644
--- a/src/Notes2/src/net/micode/notes/ui/AlarmInitReceiver.java
+++ b/src/Notes2/src/net/micode/notes/ui/AlarmInitReceiver.java
@@ -62,4 +62,13 @@ public class AlarmInitReceiver extends BroadcastReceiver {
c.close();
}
}
+
+ public static class AlarmReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ intent.setClass(context, AlarmAlertActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+ }
}
diff --git a/src/Notes2/src/net/micode/notes/ui/AlarmReceiver.java b/src/Notes2/src/net/micode/notes/ui/AlarmReceiver.java
deleted file mode 100644
index 54e503b..0000000
--- a/src/Notes2/src/net/micode/notes/ui/AlarmReceiver.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.ui;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-public class AlarmReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- intent.setClass(context, AlarmAlertActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
- }
-}
diff --git a/src/Notes2/src/net/micode/notes/ui/DateTimePickerDialog.java b/src/Notes2/src/net/micode/notes/ui/DateTimePickerDialog.java
index 2c47ba4..d6ad95e 100644
--- a/src/Notes2/src/net/micode/notes/ui/DateTimePickerDialog.java
+++ b/src/Notes2/src/net/micode/notes/ui/DateTimePickerDialog.java
@@ -1,19 +1,3 @@
-/*
- * 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.ui;
import java.util.Calendar;
@@ -32,35 +16,47 @@ import android.text.format.DateUtils;
public class DateTimePickerDialog extends AlertDialog implements OnClickListener {
private Calendar mDate = Calendar.getInstance();
+ //创建一个Calendar类型的变量 mDate,方便时间的操作
private boolean mIs24HourView;
private OnDateTimeSetListener mOnDateTimeSetListener;
+ //声明一个时间日期滚动选择控件 mOnDateTimeSetListener
private DateTimePicker mDateTimePicker;
+ //DateTimePicker控件,控件一般用于让用户可以从日期列表中选择单个值。
+ //运行时,单击控件边上的下拉箭头,会显示为两个部分:一个下拉列表,一个用于选择日期的
public interface OnDateTimeSetListener {
void OnDateTimeSet(AlertDialog dialog, long date);
}
public DateTimePickerDialog(Context context, long date) {
+ //对该界面对话框的实例化
super(context);
+ //对数据库的操作
mDateTimePicker = new DateTimePicker(context);
setView(mDateTimePicker);
+ //添加一个子视图
mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() {
public void onDateTimeChanged(DateTimePicker view, int year, int month,
- int dayOfMonth, int hourOfDay, int minute) {
+ int dayOfMonth, int hourOfDay, int minute) {
mDate.set(Calendar.YEAR, year);
mDate.set(Calendar.MONTH, month);
mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
mDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
mDate.set(Calendar.MINUTE, minute);
+ //将视图中的各选项设置为系统当前时间
updateTitle(mDate.getTimeInMillis());
}
});
mDate.setTimeInMillis(date);
+ //得到系统时间
mDate.set(Calendar.SECOND, 0);
+ //将秒数设置为0
mDateTimePicker.setCurrentDate(mDate.getTimeInMillis());
setButton(context.getString(R.string.datetime_dialog_ok), this);
setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener)null);
+ //设置按钮
set24HourView(DateFormat.is24HourFormat(this.getContext()));
+ //时间标准化打印
updateTitle(mDate.getTimeInMillis());
}
@@ -70,21 +66,22 @@ public class DateTimePickerDialog extends AlertDialog implements OnClickListener
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack;
- }
+ }//将时间日期滚动选择控件实例化
private void updateTitle(long date) {
int flag =
- DateUtils.FORMAT_SHOW_YEAR |
- DateUtils.FORMAT_SHOW_DATE |
- DateUtils.FORMAT_SHOW_TIME;
+ DateUtils.FORMAT_SHOW_YEAR |
+ DateUtils.FORMAT_SHOW_DATE |
+ DateUtils.FORMAT_SHOW_TIME;
flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_24HOUR;
setTitle(DateUtils.formatDateTime(this.getContext(), date, flag));
- }
+ }//android开发中常见日期管理工具类(API)——DateUtils:按照上下午显示时间
public void onClick(DialogInterface arg0, int arg1) {
if (mOnDateTimeSetListener != null) {
mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis());
}
- }
+ }//第一个参数arg0是接收到点击事件的对话框
+ //第二个参数arg1是该对话框上的按钮
}
\ No newline at end of file
diff --git a/src/Notes2/src/net/micode/notes/ui/DropdownMenu.java b/src/Notes2/src/net/micode/notes/ui/DropdownMenu.java
index 613dc74..0c4b307 100644
--- a/src/Notes2/src/net/micode/notes/ui/DropdownMenu.java
+++ b/src/Notes2/src/net/micode/notes/ui/DropdownMenu.java
@@ -30,14 +30,18 @@ import net.micode.notes.R;
public class DropdownMenu {
private Button mButton;
private PopupMenu mPopupMenu;
+ //声明一个下拉菜单
private Menu mMenu;
public DropdownMenu(Context context, Button button, int menuId) {
mButton = button;
mButton.setBackgroundResource(R.drawable.dropdown_icon);
+ //设置这个view的背景
mPopupMenu = new PopupMenu(context, mButton);
mMenu = mPopupMenu.getMenu();
mPopupMenu.getMenuInflater().inflate(menuId, mMenu);
+ //MenuInflater是用来实例化Menu目录下的Menu布局文件
+ //根据ID来确认menu的内容选项
mButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mPopupMenu.show();
@@ -48,14 +52,14 @@ public class DropdownMenu {
public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) {
if (mPopupMenu != null) {
mPopupMenu.setOnMenuItemClickListener(listener);
- }
+ }//设置菜单的监听
}
public MenuItem findItem(int id) {
return mMenu.findItem(id);
- }
+ }//对于菜单选项的初始化,根据索引搜索菜单需要的选项
public void setTitle(CharSequence title) {
mButton.setText(title);
- }
-}
+ }//布局文件,设置标题
+}
\ No newline at end of file
diff --git a/src/Notes2/src/net/micode/notes/ui/FoldersListAdapter.java b/src/Notes2/src/net/micode/notes/ui/FoldersListAdapter.java
index 96b77da..5e32e6d 100644
--- a/src/Notes2/src/net/micode/notes/ui/FoldersListAdapter.java
+++ b/src/Notes2/src/net/micode/notes/ui/FoldersListAdapter.java
@@ -30,10 +30,14 @@ import net.micode.notes.data.Notes.NoteColumns;
public class FoldersListAdapter extends CursorAdapter {
+ //CursorAdapter是Cursor和ListView的接口
+ //FoldersListAdapter继承了CursorAdapter的类
+ //主要作用是便签数据库和用户的交互
+ //这里就是用folder(文件夹)的形式展现给用户
public static final String [] PROJECTION = {
- NoteColumns.ID,
- NoteColumns.SNIPPET
- };
+ NoteColumns.ID,
+ NoteColumns.SNIPPET
+ };//调用数据库中便签的ID和片段
public static final int ID_COLUMN = 0;
public static final int NAME_COLUMN = 1;
@@ -41,12 +45,13 @@ public class FoldersListAdapter extends CursorAdapter {
public FoldersListAdapter(Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
- }
+ }//数据库操作
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ //ViewGroup是容器
return new FolderListItem(context);
- }
+ }//创建一个文件夹,对于各文件夹中子标签的初始化
@Override
public void bindView(View view, Context context, Cursor cursor) {
@@ -55,20 +60,22 @@ public class FoldersListAdapter extends CursorAdapter {
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
((FolderListItem) view).bind(folderName);
}
- }
+ }//将各个布局文件绑定起来
public String getFolderName(Context context, int position) {
Cursor cursor = (Cursor) getItem(position);
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
- }
+ }//根据数据库中标签的ID得到标签的各项内容
private class FolderListItem extends LinearLayout {
private TextView mName;
public FolderListItem(Context context) {
super(context);
+ //操作数据库
inflate(context, R.layout.folder_list_item, this);
+ //根据布局文件的名字等信息将其找出来
mName = (TextView) findViewById(R.id.tv_folder_name);
}
@@ -77,4 +84,4 @@ public class FoldersListAdapter extends CursorAdapter {
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Notes2/src/net/micode/notes/ui/NoteEditActivity.java b/src/Notes2/src/net/micode/notes/ui/NoteEditActivity.java
index 96a9ff8..b3a557b 100644
--- a/src/Notes2/src/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/Notes2/src/net/micode/notes/ui/NoteEditActivity.java
@@ -22,19 +22,32 @@ import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
import android.content.ContentUris;
+import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Paint;
+import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Environment;
import android.preference.PreferenceManager;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.text.style.BackgroundColorSpan;
+import android.text.style.ImageSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -47,11 +60,14 @@ import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
+import android.graphics.Typeface;
+
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.TextNote;
@@ -65,6 +81,7 @@ import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
+import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -149,6 +166,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private String mUserQuery;
private Pattern mPattern;
+ private final int PHOTO_REQUEST = 1;//请求码
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -158,13 +177,32 @@ public class NoteEditActivity extends Activity implements OnClickListener,
finish();
return;
}
+
initResources();
+
+
+
+ //根据id获取添加图片按钮
+ final ImageButton add_img_btn = (ImageButton) findViewById(R.id.add_img_btn);
+ //为点击图片按钮设置监听器
+ add_img_btn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Log.d(TAG, "onClick: click add image button");
+ //ACTION_GET_CONTENT: 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音)
+ Intent loadImage = new Intent(Intent.ACTION_GET_CONTENT);
+ //Category属性用于指定当前动作(Action)被执行的环境.
+ //CATEGORY_OPENABLE; 用来指示一个ACTION_GET_CONTENT的intent
+ loadImage.addCategory(Intent.CATEGORY_OPENABLE);
+ loadImage.setType("image/*");
+ startActivityForResult(loadImage, PHOTO_REQUEST);
+ }
+ });
+
+ count();
}
- /**
- * Current activity may be killed when the memory is low. Once it is killed, for another time
- * user load this activity, we should restore the former state
- */
+
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
@@ -263,14 +301,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
@Override
- protected void onResume() {
+ protected void onResume() {//能获得用户焦点:可以操作
super.onResume();
- initNoteScreen();
+ initNoteScreen();//初始化便签屏幕
}
private void initNoteScreen() {
- mNoteEditor.setTextAppearance(this, TextAppearanceResources
- .getTexAppearanceResource(mFontSizeId));
+ mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
switchToListMode(mWorkingNote.getContent());
} else {
@@ -288,11 +325,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
| DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR));
- /**
- * TODO: Add the menu for setting alert. Currently disable it because the DateTimePicker
- * is not ready
- */
showAlertHeader();
+ //将有图片路径的位置转换为图片
+ convertToImage();
}
private void showAlertHeader() {
@@ -312,6 +347,47 @@ public class NoteEditActivity extends Activity implements OnClickListener,
};
}
+ //路径字符串格式 转换为 图片image格式
+ private void convertToImage() {
+ NoteEditText noteEditText = (NoteEditText) findViewById(R.id.note_edit_view); //获取当前的edit
+ Editable editable = noteEditText.getText();//1.获取text
+ String noteText = editable.toString(); //2.将note内容转换为字符串
+ int length = editable.length(); //内容的长度
+ //3.截取img片段 [local]+uri+[local],提取uri
+ for(int i = 0; i < length; i++) {
+ for(int j = i; j < length; j++) {
+ String img_fragment = noteText.substring(i, j+1); //img_fragment:关于图片路径的片段
+ if(img_fragment.length() > 15 && img_fragment.endsWith("[/local]") && img_fragment.startsWith("[local]")){
+ int limit = 7; //[local]为7个字符
+ //[local][/local]共15个字符,剩下的为真正的path长度
+ int len = img_fragment.length()-15;
+ //从[local]之后的len个字符就是path
+ String path = img_fragment.substring(limit,limit+len);//获取到了图片路径
+ Bitmap bitmap = null;
+ Log.d(TAG, "图片的路径是:"+path);
+ try {
+ bitmap = BitmapFactory.decodeFile(path);//将图片路径解码为图片格式
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if(bitmap!=null){ //若图片存在
+ Log.d(TAG, "图片不为null");
+ ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
+ //4.创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
+ String ss = "[local]" + path + "[/local]";
+ SpannableString spannableString = new SpannableString(ss);
+ //5.将指定的标记对象附加到文本的开始...结束范围
+ spannableString.setSpan(imageSpan, 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ Log.d(TAG, "Create spannable string success!");
+ Editable edit_text = noteEditText.getEditableText();
+ edit_text.delete(i,i+len+15); //6.删掉图片路径的文字
+ edit_text.insert(i, spannableString); //7.在路径的起始位置插入图片
+ }
+ }
+ }
+ }
+ }
+
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
@@ -358,12 +434,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
|| ev.getX() > (x + view.getWidth())
|| ev.getY() < y
|| ev.getY() > (y + view.getHeight())) {
- return false;
- }
+ return false;
+ }
return true;
}
private void initResources() {
+ editText = (EditText) findViewById(R.id.note_edit_view);
+ textView = (TextView) findViewById(R.id.text_num);
mHeadViewPanel = findViewById(R.id.note_title);
mNoteHeaderHolder = new HeadViewHolder();
mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date);
@@ -418,7 +496,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
- mWorkingNote.getWidgetId()
+ mWorkingNote.getWidgetId()
});
sendBroadcast(intent);
@@ -430,7 +508,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
if (id == R.id.btn_set_bg_color) {
mNoteBgColorSelector.setVisibility(View.VISIBLE);
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
- - View.VISIBLE);
+ View.VISIBLE);
} else if (sBgSelectorBtnsMap.containsKey(id)) {
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
@@ -563,10 +641,6 @@ public class NoteEditActivity extends Activity implements OnClickListener,
d.show();
}
- /**
- * Share note to apps that support {@link Intent#ACTION_SEND} action
- * and {@text/plain} type
- */
private void sendTo(Context context, String info) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, info);
@@ -621,7 +695,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
saveNote();
}
if (mWorkingNote.getNoteId() > 0) {
- Intent intent = new Intent(this, AlarmReceiver.class);
+ Intent intent = new Intent(this, AlarmInitReceiver.AlarmReceiver.class);
intent.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mWorkingNote.getNoteId()));
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = ((AlarmManager) getSystemService(ALARM_SERVICE));
@@ -773,12 +847,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
switchToListMode(mNoteEditor.getText().toString());
} else {
if (!getWorkingText()) {
- mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ",
- ""));
+ mWorkingNote.setWorkingText(mWorkingNote.getContent().replace(TAG_UNCHECKED + " ", ""));
}
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mEditTextList.setVisibility(View.GONE);
mNoteEditor.setVisibility(View.VISIBLE);
+ convertToImage(); //退出清单模式,应该将有图片的地方显示出来
}
}
@@ -870,4 +944,201 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private void showToast(int resId, int duration) {
Toast.makeText(this, resId, duration).show();
}
+
+ @Override
+ //重写onActivityResult()来处理返回的数据
+ protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ super.onActivityResult(requestCode, resultCode, intent);
+ ContentResolver resolver = getContentResolver();
+ switch (requestCode) {
+ case PHOTO_REQUEST:
+ Uri originalUri = intent.getData(); //1.获得图片的真实路径
+ Bitmap bitmap = null;
+ try {
+ bitmap = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));//2.解码图片
+ } catch (FileNotFoundException e) {
+ Log.d(TAG, "onActivityResult: get file_exception");
+ e.printStackTrace();
+ }
+
+ if(bitmap != null){
+ //3.根据Bitmap对象创建ImageSpan对象
+ Log.d(TAG, "onActivityResult: bitmap is not null");
+ ImageSpan imageSpan = new ImageSpan(NoteEditActivity.this, bitmap);
+ String path = getPath(this,originalUri);
+ //4.使用[local][/local]将path括起来,用于之后方便识别图片路径在note中的位置
+ String img_fragment= "[local]" + path + "[/local]";
+ //创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
+ SpannableString spannableString = new SpannableString(img_fragment);
+ spannableString.setSpan(imageSpan, 0, img_fragment.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ //5.将选择的图片追加到EditText中光标所在位置
+ NoteEditText e = (NoteEditText) findViewById(R.id.note_edit_view);
+ int index = e.getSelectionStart(); //获取光标所在位置
+ Log.d(TAG, "Index是: " + index);
+ Editable edit_text = e.getEditableText();
+ edit_text.insert(index, spannableString); //将图片插入到光标所在位置
+
+ mWorkingNote.mContent = e.getText().toString();
+ //6.把改动提交到数据库中,两个数据库表都要改的
+ ContentResolver contentResolver = getContentResolver();
+ ContentValues contentValues = new ContentValues();
+ final long id = mWorkingNote.getNoteId();
+ contentValues.put("snippet",mWorkingNote.mContent);
+ contentResolver.update(Uri.parse("content://micode_notes/note"), contentValues,"_id=?",new String[]{""+id});
+ ContentValues contentValues1 = new ContentValues();
+ contentValues1.put("content",mWorkingNote.mContent);
+ contentResolver.update(Uri.parse("content://micode_notes/data"), contentValues1,"mime_type=? and note_id=?", new String[]{"vnd.android.cursor.item/text_note",""+id});
+
+ }else{
+ Toast.makeText(NoteEditActivity.this, "获取图片失败", Toast.LENGTH_SHORT).show();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+
+
+ //获取文件的real path
+ public String getPath(final Context context, final Uri uri) {
+
+ final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+
+ // DocumentProvider
+ if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+ //ExternalStorageProvider
+ if (isExternalStorageDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ if ("primary".equalsIgnoreCase(type)) {
+ return Environment.getExternalStorageDirectory() + "/" + split[1];
+ }
+ }
+ // DownloadsProvider
+ else if (isDownloadsDocument(uri)) {
+ final String id = DocumentsContract.getDocumentId(uri);
+ final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+ return getDataColumn(context, contentUri, null, null);
+ }
+ //MediaProvider
+ if (isMediaDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ Uri contentUri = null;
+ if ("image".equals(type)) {
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+ }
+
+ final String selection = "_id=?";
+ final String[] selectionArgs = new String[]{split[1]};
+
+ return getDataColumn(context, contentUri, selection, selectionArgs);
+ }
+ }
+ // Media
+ else if ("content".equalsIgnoreCase(uri.getScheme())) {
+ return getDataColumn(context, uri, null, null);
+ }
+ // File
+ else if ("file".equalsIgnoreCase(uri.getScheme())) {
+ return uri.getPath();
+ }
+ return null;
+ }
+
+
+ //获取数据列_获取此 Uri 的数据列的值。这对MediaStore Uris 和其他基于文件的 ContentProvider。
+ public String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+
+ Cursor cursor = null;
+ final String column = "_data";
+ final String[] projection = {column};
+
+ try {
+ cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ final int column_index = cursor.getColumnIndexOrThrow(column);
+ return cursor.getString(column_index);
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ return null;
+ }
+
+ public boolean isExternalStorageDocument(Uri uri) {
+ return "com.android.externalstorage.documents".equals(uri.getAuthority());
+ }
+
+ //是否为下载文件
+ public boolean isDownloadsDocument(Uri uri) {
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+ }
+
+ //是否为媒体文件
+ public boolean isMediaDocument(Uri uri) {
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
+ }
+
+ private EditText editText;
+ private TextView textView;
+
+ private String Textchange(String oriText){
+ StringBuffer stringBuffer = new StringBuffer(oriText);
+ int Flag1 = -1;
+ int Flag2 = -1;
+ do {//不计入表示图片的字符
+ Flag1 = stringBuffer.indexOf("");
+ if (Flag1 != -1 && Flag2 != -1) {
+ stringBuffer = stringBuffer.replace(Flag1, Flag2+1, "");
+ }
+ } while (Flag1 != -1 && Flag2 != -1);
+
+ do {//不计入换行字符
+ Flag1 = stringBuffer.indexOf("\n");
+
+ if (Flag1 != -1){
+ stringBuffer = stringBuffer.replace(Flag1, Flag1+1, "");
+ }
+ } while (Flag1 != -1);
+ do {//不计入空格字符
+ Flag1 = stringBuffer.indexOf(" ");
+
+ if (Flag1 != -1) {
+ stringBuffer = stringBuffer.replace(Flag1, Flag1+1, "");
+ }
+ } while (Flag1 != -1);
+ return stringBuffer.toString();
+ }
+
+ private void count() {
+
+ mNoteEditor.addTextChangedListener(new TextWatcher() {
+ int currentLength = 0;
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ textView.setText("字符数:" + currentLength);
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ currentLength = Textchange(mNoteEditor.getText().toString()).length();
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ textView.setText("字符数:" + currentLength);
+ }
+ });
+ }
+
}
+
+
diff --git a/src/Notes2/src/net/micode/notes/ui/NotesListActivity.java b/src/Notes2/src/net/micode/notes/ui/NotesListActivity.java
index 66aedec..e46a664 100644
--- a/src/Notes2/src/net/micode/notes/ui/NotesListActivity.java
+++ b/src/Notes2/src/net/micode/notes/ui/NotesListActivity.java
@@ -14,150 +14,116 @@
* limitations under the License.
*/
-/**
- * 代表这个类是UI包中的一个
- */
package net.micode.notes.ui;
-/**
- * 这些类涵盖了 Android 应用程序开发中常用的
- * UI 元素、数据存储、后台任务处理、系统服务调用等方面的功能。
- */
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.appwidget.AppWidgetManager;
+import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.ActionMode;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Display;
+import android.view.HapticFeedbackConstants;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnCreateContextMenuListener;
+import android.view.View.OnTouchListener;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.PopupMenu;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import net.micode.notes.R;
+import net.micode.notes.data.Notes;
+import net.micode.notes.data.Notes.NoteColumns;
+import net.micode.notes.gtask.remote.GTaskSyncService;
+import net.micode.notes.model.WorkingNote;
+import net.micode.notes.tool.BackupUtils;
+import net.micode.notes.tool.DataUtils;
+import net.micode.notes.tool.ResourceParser;
+import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute;
+import net.micode.notes.widget.NoteWidgetProvider_2x;
+import net.micode.notes.widget.NoteWidgetProvider_4x;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashSet;
-import android.app.Activity; //表示应用程序中的一个活动,例如界面展示等
-import android.app.AlertDialog; //用于显示对话框的类
-import android.app.Dialog; //用于创建对话框的类
-import android.appwidget.AppWidgetManager; //用于管理桌面小组件的类
-import android.content.AsyncQueryHandler; //用于在后台执行异步数据库查询的处理器。
-import android.content.ContentResolver; //用于访问应用程序的内容提供者,进行数据的增删改查。
-import android.content.ContentValues; //用于存储键值对,用于对数据库进行操作。
-import android.content.Context; //表示 Android 应用程序的当前状态,提供访问应用程序的资源和类的接口。
-import android.content.DialogInterface; //用于创建对话框与用户进行交互。
-import android.content.Intent; //用于在应用程序内部或者不同应用程序之间进行交互或传递信息。
-import android.content.SharedPreferences; //用于存储应用程序的轻量级 key-value 数据。
-import android.database.Cursor; //用于在数据集中进行移动并访问查询结果。
-import android.os.AsyncTask; //用于在后台执行长时间运行的操作,并在主线程更新用户界面。
-import android.os.Bundle; //用于传递数据。
-import android.preference.PreferenceManager; //用于访问应用程序的默认共享偏好设置。
-import android.text.Editable; //表示文本框中的可编辑文本。
-import android.text.TextUtils; //用于处理和操作文本数据。
-import android.text.TextWatcher; //用于监听文本变化的接口。
-import android.util.Log; //用于在调试时记录日志。
-import android.view.ActionMode; //用于在用户界面上执行上下文操作的模式。
-import android.view.ContextMenu; //用于在视图组件上下文菜单的呈现。
-import android.view.ContextMenu.ContextMenuInfo; //提供有关创建上下文菜单的视图组件的额外信息。
-import android.view.Display; //表示屏幕上的显示内容。
-import android.view.HapticFeedbackConstants; //用于触觉反馈的常量值。
-
-
-import android.view.LayoutInflater; //用于动态加载 XML 布局文件。
-import android.view.Menu; //表示应用程序的菜单。
-import android.view.MenuItem; //用于表示菜单项。
-import android.view.MenuItem.OnMenuItemClickListener; //用于监听菜单项点击事件的接口。
-import android.view.MotionEvent; //用于表示单个事件的运动事件。
-import android.view.View; //用户界面上的可视元素。
-import android.view.View.OnClickListener; //用于监听视图点击事件的接口。
-import android.view.View.OnCreateContextMenuListener; //用于监听创建上下文菜单的接口。
-import android.view.View.OnTouchListener; //用于监听视图触摸事件的接口。
-
-
-import android.view.inputmethod.InputMethodManager; //用于管理输入法框架的接口。
-import android.widget.AdapterView; //用于在视图组件中表示数据项的子集合。
-import android.widget.AdapterView.OnItemClickListener; //用于监听列表项点击事件的接口。
-import android.widget.AdapterView.OnItemLongClickListener; //用于监听列表项长按事件的接口。
-import android.widget.Button; //用于在用户界面中表示按钮。
-import android.widget.EditText; //用于在用户界面中表示可编辑的文本视图。
-import android.widget.ListView; //用于在用户界面中表示列表视图。
-import android.widget.PopupMenu; //用于显示弹出菜单的类。
-import android.widget.TextView; //用于在用户界面中表示文本视图。
-import android.widget.Toast; //用于显示简短消息的类。
-import net.micode.notes.R; //引用应用程序的资源。
-import net.micode.notes.data.Notes; //包含与笔记相关的数据的类。
-
-
-import net.micode.notes.data.Notes.NoteColumns; //包含笔记数据列的类。
-import net.micode.notes.gtask.remote.GTaskSyncService; //用于与 Google 任务同步服务进行交互的类
-import net.micode.notes.model.WorkingNote; //与正在编辑的笔记相关联的类。
-import net.micode.notes.tool.BackupUtils; //用于处理备份的工具类
-import net.micode.notes.tool.DataUtils; //包含处理数据的实用方法的类。
-import net.micode.notes.tool.ResourceParser; //用于解析资源的类。
-import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; //用于在笔记列表适配器中表示应用程序小部件属性的类。
-import net.micode.notes.widget.NoteWidgetProvider_2x; //用于创建 2x 大小笔记应用程序小部件的类。
-import net.micode.notes.widget.NoteWidgetProvider_4x; //用于创建 4x 大小笔记应用程序小部件的类。用于创建 4x 大小笔记应用程序小部件的类。
-
-import java.io.BufferedReader; //用于从字符输入流中读取文本的类。
-import java.io.IOException; //用于处理输入输出异常的类。
-import java.io.InputStream; //用于表示输入字节流的类。
-import java.io.InputStreamReader; //用于从字节流到字符流的桥梁。
-import java.util.HashSet; //用于表示一组不重复的元素的类。
-
-/**
- * 该类是Activity类的子类
- * 实现了监听用户点击的接口功能
- */
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
- /**
- * 定义了一些静态常量
- */
- private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0; //定义查询便签列表相关的变量
+ private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
- private static final int FOLDER_LIST_QUERY_TOKEN = 1; //定义查询的相关变量
+ private static final int FOLDER_LIST_QUERY_TOKEN = 1;
- private static final int MENU_FOLDER_DELETE = 0; //标识用户是否选择了删除选项
+ private static final int MENU_FOLDER_DELETE = 0;
- private static final int MENU_FOLDER_VIEW = 1; //标识用户选择的外观
+ private static final int MENU_FOLDER_VIEW = 1;
- private static final int MENU_FOLDER_CHANGE_NAME = 2; //标识用户是否选择重命名
+ private static final int MENU_FOLDER_CHANGE_NAME = 2;
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction";
- //定义一个字符串指向应用介绍
-
- /**
- * 这是一个枚举类型,用于表示列表的编辑状态。
- * 枚举类型可以用来定义一组相关的常量,
- * 这里定义了三种可能的列表编辑状态:
- * NOTE_LIST(便签列表)、SUB_FOLDER(子文件夹)、
- * CALL_RECORD_FOLDER(通话记录文件夹)
- */
+
private enum ListEditState {
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER
};
- private ListEditState mState; //定义了一个标识列表编辑状态的变量
+ private ListEditState mState;
- private BackgroundQueryHandler mBackgroundQueryHandler; //用于在后台执行数据库查询等操作,以避免阻塞UI线程
+ private BackgroundQueryHandler mBackgroundQueryHandler;
- private NotesListAdapter mNotesListAdapter; //用于管理便签列表中数据项的适配器,通常与 ListView 一起使用
+ private NotesListAdapter mNotesListAdapter;
- private ListView mNotesListView; //它表示便签列表的视图,用于显示便签列表中的数据项,
- // 并与适配器(NotesListAdapter)一起工作以展示数据。
+ private ListView mNotesListView;
- /**
- * 定义了一些类变量
- */
- private Button mAddNewNote; //声明了一个私有成员变量 mAddNewNote,类型为 Button,
- // 用来表示一个按钮控件,通常用于用户点击以添加新的便签。
+ private Button mAddNewNote;
- private boolean mDispatch; //声明了一个私有成员变量 mDispatch,类型为 boolean,
- // 用来表示一个标志位,可能用于控制某些事件的分发。
+ private boolean mDispatch;
- private int mOriginY; //声明了两个私有成员变量 mOriginY 和 mDispatchY,类型为 int,
- private int mDispatchY; // 可能用于记录某些位置坐标的信息。
+ private int mOriginY;
- private TextView mTitleBar; //声明了一个私有成员变量 mTitleBar,类型为 TextView,
- // 用来表示一个文本视图,通常用于显示标题栏的文本信息。
+ private int mDispatchY;
- private long mCurrentFolderId; //用来表示当前文件夹的ID。
+ private TextView mTitleBar;
- private ContentResolver mContentResolver; //用来获取应用的内容提供者,用于访问应用的数据
+ private long mCurrentFolderId;
- private ModeCallback mModeCallBack; //用于处理列表的编辑模式
+ private ContentResolver mContentResolver;
- private static final String TAG = "NotesListActivity"; //通常用于在日志或调试信息中标识类名
+ private ModeCallback mModeCallBack;
- public static final int NOTES_LISTVIEW_SCROLL_RATE = 30; //表示便签列表视图的滚动速率
+ private static final String TAG = "NotesListActivity";
- private NoteItemData mFocusNoteDataItem; //用于表示当前焦点的便签数据项
+ public static final int NOTES_LISTVIEW_SCROLL_RATE = 30;
+
+ private NoteItemData mFocusNoteDataItem;
private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?";
@@ -165,10 +131,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
+ Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR ("
+ NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND "
+ NoteColumns.NOTES_COUNT + ">0)";
- //分别表示正常的选择条件和根文件夹的选择条件,
- //通常用于数据库查询的条件语句
+
private final static int REQUEST_CODE_OPEN_NODE = 102;
- private final static int REQUEST_CODE_NEW_NODE = 103; //分别表示启动Activity时用到的请求码,用于区分不同的启动请求
+ private final static int REQUEST_CODE_NEW_NODE = 103;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -182,17 +147,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
setAppInfoFromRawRes();
}
- /**
- * 被重写的一个方法
- * 这是一个用于处理Activity返回结果的方法。
- * 当通过startActivityForResult方法启动的Activity结束后,会回调到这个方法。
- * 参数requestCode是用于标识请求的整型值,
- * resultCode是用于标识返回结果的整型值,
- * data是用于携带返回数据的Intent对象。
- * @param requestCode
- * @param resultCode
- * @param data
- */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK
@@ -203,12 +157,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
- /**
- * 这是一个私有方法,用于从原始资源中获取应用信息并保存到SharedPreferences中。
- * 首先,它会检查SharedPreferences中是否已经添加了介绍信息,
- * 如果没有,则读取raw资源中的介绍信息,并创建一个新的WorkingNote对象。
- * 接着,将介绍信息保存到SharedPreferences中,标记已经添加了介绍信息。
- */
private void setAppInfoFromRawRes() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
@@ -255,22 +203,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
- /**
- * 这是一个重写的Activity生命周期方法,当Activity即将可见时会调用此方法。
- * 在这个方法中,首先调用了父类的onStart方法,然后调用了startAsyncNotesListQuery方法。
- */
@Override
protected void onStart() {
super.onStart();
startAsyncNotesListQuery();
}
- /**
- * 这是一个私有方法,用于初始化资源。在这个方法中,对一些成员变量进行了初始化,
- * 例如内容解析器、后台查询处理器、当前文件夹ID、便签列表视图、按钮的点击监听器等。
- * 这些初始化操作可以确保在Activity启动时,相关资源和状态都得到了正确的设置,
- * 以便后续的操作和交互能够正常进行。
- */
private void initResources() {
mContentResolver = this.getContentResolver();
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
@@ -291,25 +229,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mTitleBar = (TextView) findViewById(R.id.tv_title_bar);
mState = ListEditState.NOTE_LIST;
mModeCallBack = new ModeCallback();
+
+ editText = (EditText) findViewById(R.id.note_edit_view);
+ textView = (TextView) findViewById(R.id.text_num);
}
- /**
- * 这个 ModeCallback 类实现了
- * ListView.MultiChoiceModeListener
- * 和 OnMenuItemClickListener 接口,
- * 用于处理列表的多选模式操作和菜单项点击事件的监听。
- */
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
private DropdownMenu mDropDownMenu;
private ActionMode mActionMode;
private MenuItem mMoveMenu;
- /**
- * 当进入多选模式时被调用,在这个方法中设置多选模式的界面和菜单。
- * @param mode
- * @param menu
- * @return
- */
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
getMenuInflater().inflate(R.menu.note_list_options, menu);
menu.findItem(R.id.delete).setOnMenuItemClickListener(this);
@@ -343,9 +272,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
- /**
- * 更新下拉菜单的显示状态,包括选中项的数量和标题等。
- */
private void updateMenu() {
int selectedCount = mNotesListAdapter.getSelectedCount();
// Update dropdown menu
@@ -363,23 +289,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
- /**
- * 在准备多选模式时被调用,可以在这个方法中进行一些准备工作。
- * @param mode
- * @param menu
- * @return
- */
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// TODO Auto-generated method stub
return false;
}
- /**
- * 在选择操作项时被调用,可以在这个方法中处理操作项的点击事件。
- * @param mode
- * @param item
- * @return
- */
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// TODO Auto-generated method stub
return false;
@@ -408,26 +322,28 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
- int itemId = item.getItemId();
- if (itemId == R.id.delete) {
- AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- builder.setTitle(getString(R.string.alert_title_delete));
- builder.setIcon(android.R.drawable.ic_dialog_alert);
- builder.setMessage(getString(R.string.alert_message_delete_notes,
- mNotesListAdapter.getSelectedCount()));
- builder.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog,
- int which) {
- batchDelete();
- }
- });
- builder.setNegativeButton(android.R.string.cancel, null);
- builder.show();
- } else if (itemId == R.id.move) {
- startQueryDestinationFolders();
- } else {
- return false;
+ switch (item.getItemId()) {
+ case R.id.delete:
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
+ builder.setTitle(getString(R.string.alert_title_delete));
+ builder.setIcon(android.R.drawable.ic_dialog_alert);
+ builder.setMessage(getString(R.string.alert_message_delete_notes,
+ mNotesListAdapter.getSelectedCount()));
+ builder.setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ batchDelete();
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, null);
+ builder.show();
+ break;
+ case R.id.move:
+ startQueryDestinationFolders();
+ break;
+ default:
+ return false;
}
return true;
}
@@ -645,8 +561,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
public void onClick(View v) {
- if (v.getId() == R.id.btn_new_note) {
- createNewNote();
+ switch (v.getId()) {
+ case R.id.btn_new_note:
+ createNewNote();
+ break;
+ default:
+ break;
}
}
@@ -662,7 +582,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
- private void showCreateOrModifyFolderDialog(final boolean create) {
+ private void showCreateOrModifyFolderDialog(final boolean create) { //新建文件夹
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null);
final EditText etName = (EditText) view.findViewById(R.id.et_foler_name);
@@ -863,27 +783,45 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- int itemId = item.getItemId();
- if (itemId == R.id.menu_new_folder) {
- showCreateOrModifyFolderDialog(true);
- } else if (itemId == R.id.menu_export_text) {
- exportNoteToText();
- } else if (itemId == R.id.menu_sync) {
- if (isSyncMode()) {
- if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) {
- GTaskSyncService.startSync(this);
+ switch (item.getItemId()) {
+ case R.id.menu_new_folder: {
+ showCreateOrModifyFolderDialog(true);
+ break;
+ }
+ case R.id.menu_export_text: {
+ exportNoteToText();
+ break;
+ }
+ case R.id.menu_sync: {
+ if (isSyncMode()) {
+ if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) {
+ GTaskSyncService.startSync(this);
+ } else {
+ GTaskSyncService.cancelSync(this);
+ }
} else {
- GTaskSyncService.cancelSync(this);
+ startPreferenceActivity();
}
- } else {
+ break;
+ }
+ case R.id.menu_setting: {
startPreferenceActivity();
+ break;
+ }
+ case R.id.menu_new_note: {
+ createNewNote();
+ break;
}
- } else if (itemId == R.id.menu_setting) {
- startPreferenceActivity();
- } else if (itemId == R.id.menu_new_note) {
- createNewNote();
- } else if (itemId == R.id.menu_search) {
- onSearchRequested();
+ case R.id.menu_search:
+ onSearchRequested();
+ break;
+
+ case R.id.menu_countallNotes:
+ showNumberofNotes();
+ break;
+
+ default:
+ break;
}
return true;
}
@@ -1021,4 +959,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
return false;
}
+
+ private void showNumberofNotes() {
+ AlertDialog.Builder btr =new AlertDialog.Builder(this);
+ btr.setTitle("目前便签数");
+ btr.setMessage("目前有 "+Integer.toString(mNotesListAdapter.retCount())+"个便签");
+ btr.show();
+ }
+
+ private EditText editText;
+ private TextView textView;
}
diff --git a/src/Notes2/src/net/micode/notes/ui/NotesListAdapter.java b/src/Notes2/src/net/micode/notes/ui/NotesListAdapter.java
index 51c9cb9..6a293ce 100644
--- a/src/Notes2/src/net/micode/notes/ui/NotesListAdapter.java
+++ b/src/Notes2/src/net/micode/notes/ui/NotesListAdapter.java
@@ -181,4 +181,22 @@ public class NotesListAdapter extends CursorAdapter {
}
}
}
+
+ public int retCount(){
+ int NotesCount=mNotesCount;
+ int ItemCount=getCount();
+ for (int i = 0; i < ItemCount; i++) {
+ Cursor c = (Cursor) getItem(i);
+ if (c != null) {
+ if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) {
+ NoteItemData NoteItem=new NoteItemData(mContext,c);
+ NotesCount+=NoteItem.getNotesCount();
+ }
+ } else {
+ Log.e(TAG, "Invalid cursor");
+ return -1;
+ }
+ }
+ return NotesCount;
+ }
}
diff --git a/src/Notes2/src/net/micode/notes/ui/SplashActivity.java b/src/Notes2/src/net/micode/notes/ui/SplashActivity.java
new file mode 100644
index 0000000..e7db203
--- /dev/null
+++ b/src/Notes2/src/net/micode/notes/ui/SplashActivity.java
@@ -0,0 +1,32 @@
+package net.micode.notes.ui;
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowInsets;
+import net.micode.notes.R;
+public class SplashActivity extends AppCompatActivity {
+ Handler mHandler=new Handler();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState); //加载启动界面
+ setContentView(R.layout.activity_splash); //加载启动图片
+
+ // 当计时结束时,跳转至NotesListActivity
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ Intent intent=new Intent();
+ intent.setClass(SplashActivity.this, NotesListActivity.class);
+ startActivity(intent);
+ finish(); //销毁欢迎页面
+ }
+ }, 2000); // 2 秒后跳转
+ }
+}
\ No newline at end of file