Merge branch 'develop_zhangshiyi' of git@bdgit.educoder.net:p67p8couq/minote.git into 饶天成

饶天成
rtc 2 years ago
commit a585c59851

Binary file not shown.

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--版本号和解码方式-->
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) <!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
@ -16,7 +16,16 @@
--> -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <selector> 是 Android 中的一个 XML 标签,用于定义在不同状态下(例如按下、选中等)如何显示视图。
一般用于按钮、标签等控件的背景、前景以及文本颜色等属性的设置。
android= 是 Android XML 文件中的命名空间声明,这里使用的andriod的官方配置-->
<item android:state_pressed="true" android:color="#88555555" /> <item android:state_pressed="true" android:color="#88555555" />
<item android:state_selected="true" android:color="#ff999999" /> <item android:state_selected="true" android:color="#ff999999" />
<item android:color="#ff000000" /> <item android:color="#ff000000" />
</selector> </selector>
<!-- 这段代码是一个XML文件用于定义一个颜色选择器selector。它包含了三个颜色项
第一个 <item> 元素定义了当状态为 pressed按下时的颜色为 #88555555这是一个半透明的深灰色。
第二个 <item> 元素定义了当状态为 selected选中时的颜色为 #ff999999这是一个较浅的灰色。
第三个 <item> 元素定义了默认情况下(即没有特定状态匹配)的颜色为 #ff000000即纯黑色。-->

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) <!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
@ -17,4 +17,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#50000000" /> <item android:color="#50000000" />
</selector> </selector>
<!-- 引入半透明黑色-->

@ -13,6 +13,17 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
这段代码是一个 Android XML 文件它定义了一个状态选择器selector用于根据控件的状态来显示不同的背景图片。
在这个 XML 文件中,<selector> 元素的命名空间被声明为 xmlns:android="http://schemas.android.com/apk/res/android"。
<selector> 元素内部,包含了两个 <item> 元素。每个 <item> 元素定义了一个状态和对应的背景图片。
第一个 <item> 元素使用了 android:state_pressed="true" 属性,表示当控件被按下时的状态,并指定了对应的背景图片为 @drawable/new_note_pressed。
第二个 <item> 元素没有指定任何状态,表示默认状态,并指定了对应的背景图片为 @drawable/new_note_normal。
根据 Android 系统的状态选择器机制,当将这个选择器应用到一个控件上时,如果控件处于对应的状态,那么它将使用相应的背景图片来呈现。
此外,该文件还包含了版权声明和 Apache 许可证信息,表明该代码是受 Apache License, Version 2.0 许可的开源代码,使用时需要遵循许可证中的规定。
--> -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) <!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)

@ -13,19 +13,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
//单个便签项提供了一个笔记模块的功能。包括管理和操作笔记的数据、插入、更新和查询笔记数据并将数据存储到ContentResolver中
package net.micode.notes.model; package net.micode.notes.model;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;//用于描述对内容提供者的单个操作,例如插入、更新或删除数据。
import android.content.ContentProviderResult; import android.content.ContentProviderResult;// 用于存储一组内容提供者操作的结果。
import android.content.ContentUris; import android.content.ContentUris;//包含用于处理内容URI的实用方法例如从URI中提取ID等。
import android.content.ContentValues; import android.content.ContentValues;// 用于存储键值对形式的数据,通常用于向内容提供者插入新数据或更新现有数据。
import android.content.Context; import android.content.Context;//用于访问应用程序全局的上下文信息,例如应用程序资源和类加载器等。
import android.content.OperationApplicationException; import android.content.OperationApplicationException;//当应用多个操作到内容提供者时,可能会抛出此异常,表示其中一个操作失败。
import android.net.Uri; import android.net.Uri;//代表一个统一资源标识符,用于定位数据的位置,常用于访问内容提供者中的数据。
import android.os.RemoteException; import android.os.RemoteException;//可能会在跨进程通信时抛出,表示远程过程调用发生错误。
import android.util.Log; import android.util.Log;//用于在Android系统中记录日志信息帮助开发者调试应用程序。
//上面为标准库下面为在notes.data包里的用法
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;//设置安卓应用程序中笔记和文件夹的一些基本参数和属性
import net.micode.notes.data.Notes.CallNote; import net.micode.notes.data.Notes.CallNote;
import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
@ -35,73 +35,79 @@ import java.util.ArrayList;
public class Note { public class Note {
private ContentValues mNoteDiffValues; private ContentValues mNoteDiffValues;//
private NoteData mNoteData; private NoteData mNoteData;//note数据
private static final String TAG = "Note"; private static final String TAG = "Note";
/** /**
* Create a new note id for adding a new note to databases * Create a new note id for adding a new note to databases
*/ */
public static synchronized long getNewNoteId(Context context, long folderId) { public static synchronized long getNewNoteId(Context context, long folderId) {
// Create a new note in the database // Create a new note in the database
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();//新建values来保存信息
long createdTime = System.currentTimeMillis(); long createdTime = System.currentTimeMillis();//以当前时间为创建时间
values.put(NoteColumns.CREATED_DATE, createdTime); values.put(NoteColumns.CREATED_DATE, createdTime);//创建时间
values.put(NoteColumns.MODIFIED_DATE, createdTime); values.put(NoteColumns.MODIFIED_DATE, createdTime);//修改时间
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);//类型
values.put(NoteColumns.LOCAL_MODIFIED, 1); values.put(NoteColumns.LOCAL_MODIFIED, 1);//本地修改标志
values.put(NoteColumns.PARENT_ID, folderId); values.put(NoteColumns.PARENT_ID, folderId);//将数据写入数据库表格
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
//ContentResolver()主要是实现外部应用对ContentProvider中的数据
//进行添加、删除、修改和查询操作
long noteId = 0; long noteId = 0;
try { try {
noteId = Long.valueOf(uri.getPathSegments().get(1)); noteId = Long.valueOf(uri.getPathSegments().get(1));
// uri.getPathSegments().get(1) 的作用是从 Uri 对象中获取路径的分段,并返回索引为 1 的分段内容。
// 在这段代码中,通过调用 uri.getPathSegments() 方法获取到一个 List<String> 对象,其中包含了 Uri 路径的各个分段内容。而后使用 get(1) 方法获取到索引为 1 的分段内容。
// 根据代码的上下文,可以推测索引为 1 的分段内容代表新生成的笔记的 ID 号。因此uri.getPathSegments().get(1) 的作用就是从 Uri 中解析出新生成的笔记的 ID 号,并将其作为一个长整型值返回给变量 noteId。
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
Log.e(TAG, "Get note id error :" + e.toString()); Log.e(TAG, "Get note id error :" + e.toString());
noteId = 0; noteId = 0;
} }//try-catch异常处理
if (noteId == -1) { if (noteId == -1) {
throw new IllegalStateException("Wrong note id:" + noteId); throw new IllegalStateException("Wrong note id:" + noteId);
} }
return noteId; return noteId;//生成的新笔记的 ID 号
} }
public Note() { public Note() {
mNoteDiffValues = new ContentValues(); mNoteDiffValues = new ContentValues();
mNoteData = new NoteData(); mNoteData = new NoteData();
} }//定义两个变量用来存储便签的数据,一个是存储便签属性、一个是存储便签内容
public void setNoteValue(String key, String value) { public void setNoteValue(String key, String value) {//接受两个参数key 和 value分别表示属性的键和值。
mNoteDiffValues.put(key, value); mNoteDiffValues.put(key, value);//将 key 和 value 存储到 mNoteDiffValues 对象中
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());//修改时间为当前时间
} }//设置数据库表格的标签属性数据
public void setTextData(String key, String value) { public void setTextData(String key, String value) {
mNoteData.setTextData(key, value); mNoteData.setTextData(key, value);
} }
//设置数据库表格的标签文本内容的数据
public void setTextDataId(long id) { public void setTextDataId(long id) {
mNoteData.setTextDataId(id); mNoteData.setTextDataId(id);
} }
//设置文本数据的ID
public long getTextDataId() { public long getTextDataId() {
return mNoteData.mTextDataId; return mNoteData.mTextDataId;
} }
//得到文本数据的ID
public void setCallDataId(long id) { public void setCallDataId(long id) {
mNoteData.setCallDataId(id); mNoteData.setCallDataId(id);
} }
//设置电话号码数据的ID
public void setCallData(String key, String value) { public void setCallData(String key, String value) {
mNoteData.setCallData(key, value); mNoteData.setCallData(key, value);
} }
//得到电话号码数据的ID
public boolean isLocalModified() { public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
} }//判断是否是本地修改
public boolean syncNote(Context context, long noteId) { public boolean syncNote(Context context, long noteId) {
if (noteId <= 0) { if (noteId <= 0) {//id<=0报错
throw new IllegalArgumentException("Wrong note id:" + noteId); throw new IllegalArgumentException("Wrong note id:" + noteId);
} }
@ -114,12 +120,12 @@ public class Note {
* {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the
* note data info * note data info
*/ */
if (context.getContentResolver().update( if (context.getContentResolver().update(//更新数据库中的笔记数据。
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) { null) == 0) {//笔记的 Uri通过 ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId) 获取到特定 ID 的笔记的 Uri。
Log.e(TAG, "Update note error, should not happen"); Log.e(TAG, "Update note error, should not happen");
// Do not return, fall through // Do not return, fall through
} }//如果更新操作返回的结果为 0表示没有进行更新操作则记录错误日志 "Update note error, should not happen",并且在注释中说明不要返回,而是继续执行后面的代码。
mNoteDiffValues.clear(); mNoteDiffValues.clear();
if (mNoteData.isLocalModified() if (mNoteData.isLocalModified()
@ -128,32 +134,32 @@ public class Note {
} }
return true; return true;
} }//判断是否同步
private class NoteData { private class NoteData {//定义一个基本的便签内容的数据类,主要包含文本数据和电话号码数据
private long mTextDataId; private long mTextDataId;
private ContentValues mTextDataValues; private ContentValues mTextDataValues;//文本数据
private long mCallDataId; private long mCallDataId;
private ContentValues mCallDataValues; private ContentValues mCallDataValues;//电话号码数据
private static final String TAG = "NoteData"; private static final String TAG = "NoteData";
public NoteData() { public NoteData() {//初始化NoteData
mTextDataValues = new ContentValues(); mTextDataValues = new ContentValues();
mCallDataValues = new ContentValues(); mCallDataValues = new ContentValues();
mTextDataId = 0; mTextDataId = 0;
mCallDataId = 0; mCallDataId = 0;
} }
// 函数实现部分
boolean isLocalModified() { boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
} }//判断是否本地修改,即是否有新电话号码数据或文本数据
void setTextDataId(long id) { void setTextDataId(long id) {
if(id <= 0) { if(id <= 0) {//id<=0报错
throw new IllegalArgumentException("Text data id should larger than 0"); throw new IllegalArgumentException("Text data id should larger than 0");
} }
mTextDataId = id; mTextDataId = id;
@ -178,23 +184,26 @@ public class Note {
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
} }
//下面函数的作用是将新的数据通过Uri的操作存储到数据库
Uri pushIntoContentResolver(Context context, long noteId) { Uri pushIntoContentResolver(Context context, long noteId) {
/** /**
* Check for safety * Check for safety
*/ */
if (noteId <= 0) { if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId); throw new IllegalArgumentException("Wrong note id:" + noteId);
} }//判断是否合法
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null; ContentProviderOperation.Builder builder = null;//数据库的操作列表
if(mTextDataValues.size() > 0) { if(mTextDataValues.size() > 0) {//有文本数据
mTextDataValues.put(DataColumns.NOTE_ID, noteId); mTextDataValues.put(DataColumns.NOTE_ID, noteId);//如果有文本数据,首先将笔记的 IDnoteId存储到 mTextDataValues 中
if (mTextDataId == 0) { if (mTextDataId == 0) {//如果是 0表示当前没有对应的文本数据记录需要进行插入操作。
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE);
//在插入操作中,设置 mTextDataValues 的 MIME 类型为 TextNote.CONTENT_ITEM_TYPE表示文本类型的数据。
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mTextDataValues); mTextDataValues);//通过 context.getContentResolver().insert() 方法将 mTextDataValues 插入到 DataColumns 表中,并返回插入数据的 Uri。
//尝试从插入返回的 Uri 中获取新插入数据的 ID并将其转换为 Long 类型,并存储到 mTextDataId 中。若转换失败,记录错误日志并清空 mTextDataValues然后返回 null。
try { try {
setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); setTextDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@ -202,21 +211,25 @@ public class Note {
mTextDataValues.clear(); mTextDataValues.clear();
return null; return null;
} }
} else { } else {//如果 mTextDataId 不为 0则表示已存在对应的文本数据记录需要进行更新操作。
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mTextDataId)); Notes.CONTENT_DATA_URI, mTextDataId));//通过 ContentUris.withAppendedId() 获取特定 ID 的文本数据记录的 Uri并设置更新值为 mTextDataValues。
builder.withValues(mTextDataValues); builder.withValues(mTextDataValues);
operationList.add(builder.build()); operationList.add(builder.build());//将更新操作添加到 operationList 中。
} }
mTextDataValues.clear(); mTextDataValues.clear();//清空 mTextDataValues。
} }//把文本数据存入DataColumns
if(mCallDataValues.size() > 0) { if(mCallDataValues.size() > 0) {//有电话号码。用于将电话号码数据存储到数据库的 DataColumns 表中
mCallDataValues.put(DataColumns.NOTE_ID, noteId); mCallDataValues.put(DataColumns.NOTE_ID, noteId);//如果有电话号码数据,首先将笔记的 IDnoteId存储到 mCallDataValues 中。
if (mCallDataId == 0) { if (mCallDataId == 0) {//判断 mCallDataId 是否为 0。如果是 0表示当前没有对应的电话号码数据记录需要进行插入操作。
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE);
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
mCallDataValues); mCallDataValues);
//在插入操作中,设置 mCallDataValues 的 MIME 类型为 CallNote.CONTENT_ITEM_TYPE表示电话号码类型的数据。
// 然后通过 context.getContentResolver().insert() 方法将 mCallDataValues 插入到 DataColumns 表中,并返回插入数据的 Uri。
//尝试从插入返回的 Uri 中获取新插入数据的 ID并将其转换为 Long 类型,并存储到 mCallDataId 中。若转换失败,记录错误日志并清空 mCallDataValues然后返回 null。
try { try {
setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); setCallDataId(Long.valueOf(uri.getPathSegments().get(1)));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@ -224,16 +237,19 @@ public class Note {
mCallDataValues.clear(); mCallDataValues.clear();
return null; return null;
} }
} else { } else {//如果 mCallDataId 不为 0则表示已存在对应的电话号码数据记录需要进行更新操作。
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
Notes.CONTENT_DATA_URI, mCallDataId)); Notes.CONTENT_DATA_URI, mCallDataId));//创建一个 ContentProviderOperation.Builder 对象,通过 ContentUris.withAppendedId() 获取特定 ID 的电话号码数据记录的 Uri并设置更新值为 mCallDataValues。
builder.withValues(mCallDataValues); builder.withValues(mCallDataValues);
operationList.add(builder.build()); operationList.add(builder.build());////将更新操作添加到 operationList 中。
} }
mCallDataValues.clear(); mCallDataValues.clear();//清空 mCallDataValues。
} }//把电话号码数据存入DataColumns
//将电话号码数据与笔记关联起来,方便后续读取和展示。
if (operationList.size() > 0) {
if (operationList.size() > 0) {//总长大于0
// 在 try-catch 块中,捕获可能发生的 RemoteException 和 OperationApplicationException 异常。
try { try {
ContentProviderResult[] results = context.getContentResolver().applyBatch( ContentProviderResult[] results = context.getContentResolver().applyBatch(
Notes.AUTHORITY, operationList); Notes.AUTHORITY, operationList);
@ -248,6 +264,6 @@ public class Note {
} }
} }
return null; return null;
} }//存储过程中的异常处理
} }
} }

@ -16,12 +16,12 @@
package net.micode.notes.model; package net.micode.notes.model;
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManager;//用于管理Android应用中的小部件。
import android.content.ContentUris; import android.content.ContentUris;//提供了用于处理内容URI的实用方法用于获取数据的URI。
import android.content.Context; import android.content.Context;//用于访问应用程序的全局信息和资源。
import android.database.Cursor; import android.database.Cursor;//用于在数据库查询结果集中进行遍历和操作。
import android.text.TextUtils; import android.text.TextUtils;//提供了一些处理文本的实用方法,如判断字符串是否为空或空白。
import android.util.Log; import android.util.Log;//用于在调试时输出日志信息。
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote; import net.micode.notes.data.Notes.CallNote;
@ -31,7 +31,7 @@ import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote; import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.tool.ResourceParser.NoteBgResources; import net.micode.notes.tool.ResourceParser.NoteBgResources;
//定义WorkingNote
public class WorkingNote { public class WorkingNote {
// Note for the working note // Note for the working note
private Note mNote; private Note mNote;
@ -41,27 +41,30 @@ public class WorkingNote {
private String mContent; private String mContent;
// Note mode // Note mode
private int mMode; private int mMode;
//模式值初始化为0
private long mAlertDate; private long mAlertDate;
//警戒值
private long mModifiedDate; private long mModifiedDate;
//修改值
private int mBgColorId; private int mBgColorId;
//颜色
private int mWidgetId; private int mWidgetId;
//宽 ID
private int mWidgetType; private int mWidgetType;
//宽大小
private long mFolderId; private long mFolderId;
//文件夹ID
private Context mContext; private Context mContext;
//内容
private static final String TAG = "WorkingNote"; private static final String TAG = "WorkingNote";
//标签
private boolean mIsDeleted; private boolean mIsDeleted;
//删除时改变
private NoteSettingChangedListener mNoteSettingStatusListener; private NoteSettingChangedListener mNoteSettingStatusListener;
//判断设置是否改变默认为0
// 声明 DATA_PROJECTION字符串数组
public static final String[] DATA_PROJECTION = new String[] { public static final String[] DATA_PROJECTION = new String[] {
DataColumns.ID, DataColumns.ID,
DataColumns.CONTENT, DataColumns.CONTENT,
@ -72,6 +75,9 @@ public class WorkingNote {
DataColumns.DATA4, DataColumns.DATA4,
}; };
// 声明 NOTE_PROJECTION字符串数组
public static final String[] NOTE_PROJECTION = new String[] { public static final String[] NOTE_PROJECTION = new String[] {
NoteColumns.PARENT_ID, NoteColumns.PARENT_ID,
NoteColumns.ALERTED_DATE, NoteColumns.ALERTED_DATE,
@ -101,17 +107,19 @@ public class WorkingNote {
private static final int NOTE_MODIFIED_DATE_COLUMN = 5; private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
// WorkingNote的构造函数
// New note construct // New note construct
private WorkingNote(Context context, long folderId) { private WorkingNote(Context context, long folderId) {
mContext = context; mContext = context;
mAlertDate = 0; mAlertDate = 0;
mModifiedDate = System.currentTimeMillis(); mModifiedDate = System.currentTimeMillis();//将修改日期设置为当前时间的毫秒数。
mFolderId = folderId; mFolderId = folderId;//将传入的文件夹 ID 赋值给 mFolderId。
mNote = new Note(); mNote = new Note();
mNoteId = 0; mNoteId = 0;
mIsDeleted = false; mIsDeleted = false;
mMode = 0; mMode = 0;
mWidgetType = Notes.TYPE_WIDGET_INVALIDE; mWidgetType = Notes.TYPE_WIDGET_INVALIDE;//将小部件类型设置为无效类型Notes.TYPE_WIDGET_INVALIDE
} }
// Existing note construct // Existing note construct
@ -124,11 +132,15 @@ public class WorkingNote {
loadNote(); loadNote();
} }
// 加载Note
// 通过数据库调用query函数找到第一个条目
private void loadNote() { private void loadNote() {
Cursor cursor = mContext.getContentResolver().query( Cursor cursor = mContext.getContentResolver().query(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null,
null, null); null, null);
// 若存在,储存相应信
if (cursor != null) { if (cursor != null) {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN);
@ -139,6 +151,7 @@ public class WorkingNote {
mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN);
} }
cursor.close(); cursor.close();
// 若不存在,报错
} else { } else {
Log.e(TAG, "No note with id:" + mNoteId); Log.e(TAG, "No note with id:" + mNoteId);
throw new IllegalArgumentException("Unable to find note with id " + mNoteId); throw new IllegalArgumentException("Unable to find note with id " + mNoteId);
@ -146,14 +159,18 @@ public class WorkingNote {
loadNoteData(); loadNoteData();
} }
// 加载NoteData
private void loadNoteData() { private void loadNoteData() {
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
DataColumns.NOTE_ID + "=?", new String[] { DataColumns.NOTE_ID + "=?", new String[] {
String.valueOf(mNoteId) String.valueOf(mNoteId)
}, null); }, null);
//根据ID加载note
if (cursor != null) { if (cursor != null) {
// 查到信息不为空
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
// 查看第一项是否存在
do { do {
String type = cursor.getString(DATA_MIME_TYPE_COLUMN); String type = cursor.getString(DATA_MIME_TYPE_COLUMN);
if (DataConstants.NOTE.equals(type)) { if (DataConstants.NOTE.equals(type)) {
@ -166,37 +183,45 @@ public class WorkingNote {
Log.d(TAG, "Wrong note type with type:" + type); Log.d(TAG, "Wrong note type with type:" + type);
} }
} while (cursor.moveToNext()); } while (cursor.moveToNext());
//查阅所有项,直到为空
} }
cursor.close(); cursor.close();
} else { } else {
//没有便签则报错
Log.e(TAG, "No data with id:" + mNoteId); Log.e(TAG, "No data with id:" + mNoteId);
throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId);
} }
} }
// 创建空的Note
// 传参context文件夹idwidget背景颜色
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
int widgetType, int defaultBgColorId) { int widgetType, int defaultBgColorId) {
WorkingNote note = new WorkingNote(context, folderId); WorkingNote note = new WorkingNote(context, folderId);
// 设定颜色widget
note.setBgColorId(defaultBgColorId); note.setBgColorId(defaultBgColorId);
note.setWidgetId(widgetId); note.setWidgetId(widgetId);
note.setWidgetType(widgetType); note.setWidgetType(widgetType);
return note; return note;
} }
//根据id加载note
public static WorkingNote load(Context context, long id) { public static WorkingNote load(Context context, long id) {
return new WorkingNote(context, id, 0); return new WorkingNote(context, id, 0);
} }
//保存Note
public synchronized boolean saveNote() { public synchronized boolean saveNote() {
if (isWorthSaving()) { if (isWorthSaving()) {
//是否值得保存
if (!existInDatabase()) { if (!existInDatabase()) {
//是否存在数据库中
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
//ID为0报错
Log.e(TAG, "Create new note fail with id:" + mNoteId); Log.e(TAG, "Create new note fail with id:" + mNoteId);
return false; return false;
} }
} }
mNote.syncNote(mContext, mNoteId); mNote.syncNote(mContext, mNoteId);//保存
/** /**
* Update widget content if there exist any widget of this note * Update widget content if there exist any widget of this note
@ -204,7 +229,7 @@ public class WorkingNote {
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mWidgetType != Notes.TYPE_WIDGET_INVALIDE
&& mNoteSettingStatusListener != null) { && mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onWidgetChanged(); mNoteSettingStatusListener.onWidgetChanged();// 状态变为已保存
} }
return true; return true;
} else { } else {
@ -212,11 +237,14 @@ public class WorkingNote {
} }
} }
//判断数据库是否存在该便签
public boolean existInDatabase() { public boolean existInDatabase() {
return mNoteId > 0; return mNoteId > 0;
} }
//是否值得保存
private boolean isWorthSaving() { private boolean isWorthSaving() {
// 被删除,或(不在数据库中 内容为空),或 本地已保存过
if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent))
|| (existInDatabase() && !mNote.isLocalModified())) { || (existInDatabase() && !mNote.isLocalModified())) {
return false; return false;
@ -225,9 +253,12 @@ public class WorkingNote {
} }
} }
// 设置mNoteSettingStatusListener
public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) {
mNoteSettingStatusListener = l; mNoteSettingStatusListener = l;
} }
// 设置AlertDate
// 若 mAlertDate与data不同则更改mAlertDate并设定NoteValue
public void setAlertDate(long date, boolean set) { public void setAlertDate(long date, boolean set) {
if (date != mAlertDate) { if (date != mAlertDate) {
@ -239,16 +270,20 @@ public class WorkingNote {
} }
} }
// 设定删除标记
public void markDeleted(boolean mark) { public void markDeleted(boolean mark) {
//设定标记
mIsDeleted = mark; mIsDeleted = mark;
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) { && mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onWidgetChanged(); mNoteSettingStatusListener.onWidgetChanged();
// 调用mNoteSettingStatusListener的 onWidgetChanged方法
} }
} }
// 设定背景颜色
public void setBgColorId(int id) { public void setBgColorId(int id) {
if (id != mBgColorId) { if (id != mBgColorId) {//设定条件 id != mBgColorId
mBgColorId = id; mBgColorId = id;
if (mNoteSettingStatusListener != null) { if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onBackgroundColorChanged(); mNoteSettingStatusListener.onBackgroundColorChanged();
@ -257,7 +292,10 @@ public class WorkingNote {
} }
} }
// 设定检查列表模式
// 参数mode
public void setCheckListMode(int mode) { public void setCheckListMode(int mode) {
//设定条件 mMode != mode才改变
if (mMode != mode) { if (mMode != mode) {
if (mNoteSettingStatusListener != null) { if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode); mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode);
@ -266,82 +304,107 @@ public class WorkingNote {
mNote.setTextData(TextNote.MODE, String.valueOf(mMode)); mNote.setTextData(TextNote.MODE, String.valueOf(mMode));
} }
} }
// 设定WidgetType
// 参数type
public void setWidgetType(int type) { public void setWidgetType(int type) {
if (type != mWidgetType) { if (type != mWidgetType) {//设定条件 type != mWidgetType
mWidgetType = type; mWidgetType = type;
mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType)); mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType));
// 调用Note的setNoteValue方法更改WidgetType
} }
} }
// 设定WidgetId
// 参数id
public void setWidgetId(int id) { public void setWidgetId(int id) {
if (id != mWidgetId) { if (id != mWidgetId) {
mWidgetId = id; mWidgetId = id;
mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId));
// 调用Note的setNoteValue方法更改WidgetId
} }
} }
// 设定WorkingText
// 参数更改的text
public void setWorkingText(String text) { public void setWorkingText(String text) {
if (!TextUtils.equals(mContent, text)) { if (!TextUtils.equals(mContent, text)) {//设定条件 mContent, text内容不同
mContent = text; mContent = text;
mNote.setTextData(DataColumns.CONTENT, mContent); mNote.setTextData(DataColumns.CONTENT, mContent);
// 调用Note的setTextData方法更改WorkingText
} }
} }
// 转变mNote的CallData及CallNote信息
// 参数String phoneNumber, long callDate
public void convertToCallNote(String phoneNumber, long callDate) { public void convertToCallNote(String phoneNumber, long callDate) {
mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate));
mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber);
mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER));
} }
// 判断是否有时钟题型
public boolean hasClockAlert() { public boolean hasClockAlert() {
return (mAlertDate > 0 ? true : false); return (mAlertDate > 0 ? true : false);
} }
// 获取Content
public String getContent() { public String getContent() {
return mContent; return mContent;
} }
// 获取AlertDate
public long getAlertDate() { public long getAlertDate() {
return mAlertDate; return mAlertDate;
} }
// 获取ModifiedDate
public long getModifiedDate() { public long getModifiedDate() {
return mModifiedDate; return mModifiedDate;
} }
// 获取背景颜色来源id
public int getBgColorResId() { public int getBgColorResId() {
return NoteBgResources.getNoteBgResource(mBgColorId); return NoteBgResources.getNoteBgResource(mBgColorId);
} }
// 获取背景颜色id
public int getBgColorId() { public int getBgColorId() {
return mBgColorId; return mBgColorId;
} }
// 获取标题背景颜色id
public int getTitleBgResId() { public int getTitleBgResId() {
return NoteBgResources.getNoteTitleBgResource(mBgColorId); return NoteBgResources.getNoteTitleBgResource(mBgColorId);
} }
// 获取CheckListMode
public int getCheckListMode() { public int getCheckListMode() {
return mMode; return mMode;
} }
// 获取便签id
public long getNoteId() { public long getNoteId() {
return mNoteId; return mNoteId;
} }
// 获取文件夹id
public long getFolderId() { public long getFolderId() {
return mFolderId; return mFolderId;
} }
// 获取WidgetId
public int getWidgetId() { public int getWidgetId() {
return mWidgetId; return mWidgetId;
} }
// 获取WidgetType
public int getWidgetType() { public int getWidgetType() {
return mWidgetType; return mWidgetType;
} }
// 创建接口 NoteSettingChangedListener,便签更新监视
// 为NoteEditActivity提供接口
// 提供函数有
public interface NoteSettingChangedListener { public interface NoteSettingChangedListener {
/** /**
* Called when the background color of current note has just changed * Called when the background color of current note has just changed

@ -16,12 +16,12 @@
package net.micode.notes.tool; package net.micode.notes.tool;
import android.content.Context; import android.content.Context;//导入 Android 应用程序上下文(Context)类。
import android.database.Cursor; import android.database.Cursor;//导入 Android 数据库查询结果集(Cursor)类。
import android.os.Environment; import android.os.Environment;//导入 Android 系统环境(Environment)类。
import android.text.TextUtils; import android.text.TextUtils;//导入 Android 文本工具(TextUtils)类。
import android.text.format.DateFormat; import android.text.format.DateFormat;//导入 Android 日期时间格式化(DateFormat)类。
import android.util.Log; import android.util.Log;//导入 Android 日志(Log)类。
import net.micode.notes.R; import net.micode.notes.R;
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
@ -29,68 +29,72 @@ import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants; import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.Notes.NoteColumns;
import java.io.File; import java.io.File;//导入 Java 的文件(File)类,用于表示文件和目录的抽象路径名。
import java.io.FileNotFoundException; import java.io.FileNotFoundException;//导入 Java 的文件找不到异常(FileNotFoundException)类,用于处理文件未找到的异常情况。
import java.io.FileOutputStream; import java.io.FileOutputStream;//导入 Java 的文件输出流(FileOutputStream)类,用于将数据写入文件。
import java.io.IOException; import java.io.IOException;//导入 Java 的输入输出异常(IOException)类,用于处理输入输出操作中可能发生的异常情况。
import java.io.PrintStream; import java.io.PrintStream;//导入 Java 的打印流(PrintStream)类,用于向标准输出流打印输出。
//备份的处理
public class BackupUtils { public class BackupUtils {
private static final String TAG = "BackupUtils"; private static final String TAG = "BackupUtils";//定义了一个私有的静态字符串常量 TAG用于日志输出。
// Singleton stuff // Singleton stuff
private static BackupUtils sInstance; private static BackupUtils sInstance;//定义了一个私有的静态成员变量 sInstance表示单例对象。
public static synchronized BackupUtils getInstance(Context context) { public static synchronized BackupUtils getInstance(Context context) {
if (sInstance == null) { if (sInstance == null) {
sInstance = new BackupUtils(context); //如果当前备份不存在,则新声明一个
sInstance = new BackupUtils(context);//并将传入的上下文参数赋值给它
} }
return sInstance; return sInstance;//。最后返回 sInstance。
} }
/** /**
* Following states are signs to represents backup or restore * Following states are signs to represents backup or restore
* status * status
*/ */
// Currently, the sdcard is not mounted // Currently, the sdcard is not mounted SD卡没有被装入手机
public static final int STATE_SD_CARD_UNMOUONTED = 0; 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; 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; 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; public static final int STATE_SYSTEM_ERROR = 3;
// Backup or restore success // Backup or restore success成功存储
public static final int STATE_SUCCESS = 4; public static final int STATE_SUCCESS = 4;
//备份或恢复成功。
private TextExport mTextExport;//声明了一个私有成员变量 mTextExport表示文本导出对象。
private TextExport mTextExport; //初始化函数
private BackupUtils(Context context) { private BackupUtils(Context context) {
mTextExport = new TextExport(context); mTextExport = new TextExport(context);
} }//用于初始化 BackupUtils 对象
private static boolean externalStorageAvailable() { //外部存储功能是否可用
private static boolean externalStorageAvailable() {//外部存储功能是否可用
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
} }//用于检查外部存储是否可用。它通过比较外部存储的状态是否为 Environment.MEDIA_MOUNTED 来判断外部存储是否可用,并返回布尔值。
//
public int exportToText() { public int exportToText() {
return mTextExport.exportToText(); return mTextExport.exportToText();
} }
//用于导出数据到文本文件。该方法调用了 mTextExport 对象的 exportToText() 方法,并返回结果。
public String getExportedTextFileName() { public String getExportedTextFileName() {
return mTextExport.mFileName; return mTextExport.mFileName;
} }
// 用于获取导出的文本文件名。该方法返回 mTextExport 对象的 mFileName 属性。
public String getExportedTextFileDir() { public String getExportedTextFileDir() {
return mTextExport.mFileDirectory; return mTextExport.mFileDirectory;
} }
// 用于获取导出的文本文件目录。该方法返回 mTextExport 对象的 mFileDirectory 属性。 private static class TextExport {
private static class TextExport {
private static final String[] NOTE_PROJECTION = { private static final String[] NOTE_PROJECTION = {
NoteColumns.ID, NoteColumns.ID,//表示笔记的唯一标识符。
NoteColumns.MODIFIED_DATE, NoteColumns.MODIFIED_DATE,//表示笔记的修改日期。
NoteColumns.SNIPPET, NoteColumns.SNIPPET,//表示笔记的摘要或片段。
NoteColumns.TYPE NoteColumns.TYPE//表示笔记的类型。
}; };
private static final int NOTE_COLUMN_ID = 0; private static final int NOTE_COLUMN_ID = 0;
@ -125,6 +129,7 @@ public class BackupUtils {
private String mFileName; private String mFileName;
private String mFileDirectory; private String mFileDirectory;
//导出文本功能,将其作为字符串形式导出
public TextExport(Context context) { public TextExport(Context context) {
TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note);
mContext = context; mContext = context;
@ -140,22 +145,22 @@ public class BackupUtils {
* Export the folder identified by folder id to text * Export the folder identified by folder id to text
*/ */
private void exportFolderToText(String folderId, PrintStream ps) { private void exportFolderToText(String folderId, PrintStream ps) {
// Query notes belong to this folder // Query notes belong to this folder通过查询parent id是文件夹id的note来选出制定ID文件夹下的Note
Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI,
NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] {
folderId folderId
}, null); }, null);
if (notesCursor != null) { if (notesCursor != null) {//有内容
if (notesCursor.moveToFirst()) { if (notesCursor.moveToFirst()) {
do { do {
// Print note's last modified date // Print note's last modified date ps里面保存有这份note的日期
ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format(
mContext.getString(R.string.format_datetime_mdhm), mContext.getString(R.string.format_datetime_mdhm),
notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE))));
// Query data belong to this note // Query data belong to this note
String noteId = notesCursor.getString(NOTE_COLUMN_ID); String noteId = notesCursor.getString(NOTE_COLUMN_ID);
exportNoteToText(noteId, ps); exportNoteToText(noteId, ps); //将文件导出到text
} while (notesCursor.moveToNext()); } while (notesCursor.moveToNext());
} }
notesCursor.close(); notesCursor.close();
@ -166,22 +171,26 @@ public class BackupUtils {
* Export note identified by id to a print stream * Export note identified by id to a print stream
*/ */
private void exportNoteToText(String noteId, PrintStream ps) { private void exportNoteToText(String noteId, PrintStream ps) {
// 通过 mContext.getContentResolver().query() 方法查询数据库,获取与指定笔记 ID 相关的数据。
Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI,
DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] {
noteId noteId
}, null); }, null);
if (dataCursor != null) { // if (dataCursor != null) { //利用光标来扫描内容区别为callnote和note两种靠ps.printline输出
// 如果类型为 DataConstants.CALL_NOTE则获取电话号码、通话时间、附件位置等信息并使用 ps.println() 方法输出到文本文件中。
// 如果类型为 DataConstants.NOTE则获取笔记内容信息并使用 ps.println() 方法输出到文本文件中。
// 在每个笔记结束后,输出一行分隔符(由 Character.LINE_SEPARATOR, Character.LETTER_NUMBER 组成),以便区分不同笔记的内容
if (dataCursor.moveToFirst()) { if (dataCursor.moveToFirst()) {
do { do {
String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE);
if (DataConstants.CALL_NOTE.equals(mimeType)) { if (DataConstants.CALL_NOTE.equals(mimeType)) {//是否类型相同
// Print phone number // Print phone number
String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER);
long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE);
String location = dataCursor.getString(DATA_COLUMN_CONTENT); String location = dataCursor.getString(DATA_COLUMN_CONTENT);
if (!TextUtils.isEmpty(phoneNumber)) { if (!TextUtils.isEmpty(phoneNumber)) {//判断是否为空字符
ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT),
phoneNumber)); phoneNumber));
} }
@ -206,7 +215,7 @@ public class BackupUtils {
dataCursor.close(); dataCursor.close();
} }
// print a line separator between note // print a line separator between note
try { try {//如果在输出时发生异常,则会记录日志。
ps.write(new byte[] { ps.write(new byte[] {
Character.LINE_SEPARATOR, Character.LETTER_NUMBER Character.LINE_SEPARATOR, Character.LETTER_NUMBER
}); });
@ -218,7 +227,7 @@ public class BackupUtils {
/** /**
* Note will be exported as text which is user readable * Note will be exported as text which is user readable
*/ */
public int exportToText() { public int exportToText() {//总函数调用上面的exportFolder和exportNote
if (!externalStorageAvailable()) { if (!externalStorageAvailable()) {
Log.d(TAG, "Media was not mounted"); Log.d(TAG, "Media was not mounted");
return STATE_SD_CARD_UNMOUONTED; return STATE_SD_CARD_UNMOUONTED;
@ -229,7 +238,7 @@ public class BackupUtils {
Log.e(TAG, "get print stream error"); 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 导出文件夹,就是导出里面包含的便签
Cursor folderCursor = mContext.getContentResolver().query( Cursor folderCursor = mContext.getContentResolver().query(
Notes.CONTENT_NOTE_URI, Notes.CONTENT_NOTE_URI,
NOTE_PROJECTION, NOTE_PROJECTION,
@ -257,7 +266,7 @@ public class BackupUtils {
folderCursor.close(); folderCursor.close();
} }
// Export notes in root's folder // Export notes in root's folder 将根目录里的便签导出(由于不属于任何文件夹,因此无法通过文件夹导出来实现这一部分便签的导出)
Cursor noteCursor = mContext.getContentResolver().query( Cursor noteCursor = mContext.getContentResolver().query(
Notes.CONTENT_NOTE_URI, Notes.CONTENT_NOTE_URI,
NOTE_PROJECTION, NOTE_PROJECTION,
@ -287,7 +296,7 @@ public class BackupUtils {
*/ */
private PrintStream getExportToTextPrintStream() { private PrintStream getExportToTextPrintStream() {
File file = generateFileMountedOnSDcard(mContext, R.string.file_path, File file = generateFileMountedOnSDcard(mContext, R.string.file_path,
R.string.file_name_txt_format); R.string.file_name_txt_format);//导出后的文件路径
if (file == null) { if (file == null) {
Log.e(TAG, "create file to exported failed"); Log.e(TAG, "create file to exported failed");
return null; return null;
@ -313,17 +322,17 @@ public class BackupUtils {
* 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) { private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();//创建一个 StringBuilder 对象 sb用于构建文件的路径。
sb.append(Environment.getExternalStorageDirectory()); sb.append(Environment.getExternalStorageDirectory()); //外部SD卡的存储路径
sb.append(context.getString(filePathResId)); sb.append(context.getString(filePathResId));//文件的存储路径
File filedir = new File(sb.toString()); File filedir = new File(sb.toString());//filedir应该就是用来存储路径信息
sb.append(context.getString( sb.append(context.getString(
fileNameFormatResId, fileNameFormatResId,
DateFormat.format(context.getString(R.string.format_date_ymd), DateFormat.format(context.getString(R.string.format_date_ymd),
System.currentTimeMillis()))); System.currentTimeMillis())));//将资源 ID 为 fileNameFormatResId 的字符串添加到 sb 中,该字符串是文件名的格式化模板,其中使用了当前时间进行格式化。
File file = new File(sb.toString()); File file = new File(sb.toString());
try { try { //如果这些文件不存在,则新建
if (!filedir.exists()) { if (!filedir.exists()) {
filedir.mkdir(); filedir.mkdir();
} }
@ -337,6 +346,7 @@ public class BackupUtils {
e.printStackTrace(); e.printStackTrace();
} }
// try catch 异常处理
return null; return null;
} }
} }

@ -16,15 +16,15 @@
package net.micode.notes.tool; package net.micode.notes.tool;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;//导入 Android 内容提供者操作(ContentProviderOperation)类,用于操作内容提供者中的数据。
import android.content.ContentProviderResult; import android.content.ContentProviderResult;//导入 Android 内容提供者结果(ContentProviderResult)类,用于存储内容提供者操作的结果。
import android.content.ContentResolver; import android.content.ContentResolver;//导入 Android 内容解析器(ContentResolver)类,用于访问应用程序中的各种内容提供者。
import android.content.ContentUris; import android.content.ContentUris;//导入 Android 内容 URI(ContentUris)类,用于处理内容提供者的 URI。
import android.content.ContentValues; import android.content.ContentValues;//导入 Android 内容值(ContentValues)类,用于封装要插入或更新到内容提供者中的数据。
import android.content.OperationApplicationException; import android.content.OperationApplicationException;//导入 Android 操作应用程序异常(OperationApplicationException)类,用于处理内容提供者操作时可能出现的异常情况。
import android.database.Cursor; import android.database.Cursor;//导入 Android 数据库查询结果集(Cursor)类,用于表示数据库查询结果集。
import android.os.RemoteException; import android.os.RemoteException;//导入 Android 远程操作异常(RemoteException)类,用于处理远程操作时可能出现的异常情况。
import android.util.Log; import android.util.Log;//导入 Android 日志(Log)类,用于记录调试信息。
import net.micode.notes.data.Notes; import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote; import net.micode.notes.data.Notes.CallNote;
@ -37,6 +37,8 @@ import java.util.HashSet;
public class DataUtils { public class DataUtils {
public static final String TAG = "DataUtils"; public static final String TAG = "DataUtils";
//删除多个note
public static boolean batchDeleteNotes(ContentResolver resolver, HashSet<Long> ids) { public static boolean batchDeleteNotes(ContentResolver resolver, HashSet<Long> ids) {
if (ids == null) { if (ids == null) {
Log.d(TAG, "the ids is null"); Log.d(TAG, "the ids is null");
@ -47,19 +49,20 @@ public class DataUtils {
return true; return true;
} }
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();//提供一个任务列表
for (long id : ids) { for (long id : ids) {
if(id == Notes.ID_ROOT_FOLDER) { if(id == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Don't delete system folder root"); Log.e(TAG, "Don't delete system folder root");
continue; continue;
} } //如果发现是根文件夹,则不删除
ContentProviderOperation.Builder builder = ContentProviderOperation ContentProviderOperation.Builder builder = ContentProviderOperation
.newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); //用newDelete实现删除功能
operationList.add(builder.build()); operationList.add(builder.build());
} }
try { try {
ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList);//主机名或叫Authority用于唯一标识这个ContentProvider外部调用者可以根据这个标识来找到它。
if (results == null || results.length == 0 || results[0] == null) { //数据库事务,数据库事务是由一组数据库操作序列组成,事务作为一个整体被执行
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 false;
} }
@ -72,14 +75,16 @@ public class DataUtils {
return false; 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) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(NoteColumns.PARENT_ID, desFolderId); values.put(NoteColumns.PARENT_ID, desFolderId);
values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId);
values.put(NoteColumns.LOCAL_MODIFIED, 1); values.put(NoteColumns.LOCAL_MODIFIED, 1);
resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null);//对需要移动的便签进行数据更新然后用update实现
} }
//批量移动
public static boolean batchMoveToFolder(ContentResolver resolver, HashSet<Long> ids, public static boolean batchMoveToFolder(ContentResolver resolver, HashSet<Long> ids,
long folderId) { long folderId) {
if (ids == null) { if (ids == null) {
@ -90,14 +95,14 @@ public class DataUtils {
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
for (long id : ids) { for (long id : ids) {
ContentProviderOperation.Builder builder = ContentProviderOperation ContentProviderOperation.Builder builder = ContentProviderOperation
.newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id));//通过withAppendedId方法为该Uri加上ID
builder.withValue(NoteColumns.PARENT_ID, folderId); builder.withValue(NoteColumns.PARENT_ID, folderId);
builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); builder.withValue(NoteColumns.LOCAL_MODIFIED, 1);
operationList.add(builder.build()); operationList.add(builder.build());
} }//将ids里包含的每一列的数据逐次加入到operationList中等待最后的批量处理
try { try {
ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); //applyBatch一次性处理一个操作列表
if (results == null || results.length == 0 || results[0] == null) { 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 false;
@ -114,12 +119,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) { public static int getUserFolderCount(ContentResolver resolver) {
Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI,
new String[] { "COUNT(*)" }, new String[] { "COUNT(*)" },
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?",
new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)},
null); null);//筛选条件源文件不为trash folder
int count = 0; int count = 0;
if(cursor != null) { if(cursor != null) {
@ -136,23 +143,24 @@ public class DataUtils {
return count; return count;
} }
//查看是否有指定ID的note可见
public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) {
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
null, null,
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER,
new String [] {String.valueOf(type)}, new String [] {String.valueOf(type)},
null); null);//查询条件type符合且不属于垃圾文件夹
boolean exist = false; boolean exist = false;
if (cursor != null) { if (cursor != null) {
if (cursor.getCount() > 0) { if (cursor.getCount() > 0) {//用getcount函数判断cursor是否为空
exist = true; exist = true;
} }
cursor.close(); cursor.close();
} }
return exist; return exist;
} }
///判定是否有指定note即不需条件条件type符合且不属于垃圾文件夹
public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) {
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
null, null, null, null); null, null, null, null);
@ -166,7 +174,7 @@ public class DataUtils {
} }
return exist; return exist;
} }
//判定是否有指定的data
public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { public static boolean existInDataDatabase(ContentResolver resolver, long dataId) {
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId),
null, null, null, null); null, null, null, null);
@ -180,13 +188,14 @@ public class DataUtils {
} }
return exist; return exist;
} }
//判定是否有指定的可见folder
public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { public static boolean checkVisibleFolderName(ContentResolver resolver, String name) {
Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null,
NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER +
" AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER +
" AND " + NoteColumns.SNIPPET + "=?", " AND " + NoteColumns.SNIPPET + "=?",
new String[] { name }, null); new String[] { name }, null);
//通过名字查询文件是否存在
boolean exist = false; boolean exist = false;
if(cursor != null) { if(cursor != null) {
if(cursor.getCount() > 0) { if(cursor.getCount() > 0) {
@ -197,12 +206,13 @@ public class DataUtils {
return exist; return exist;
} }
//文件夹工具
public static HashSet<AppWidgetAttribute> getFolderNoteWidget(ContentResolver resolver, long folderId) { public static HashSet<AppWidgetAttribute> getFolderNoteWidget(ContentResolver resolver, long folderId) {
Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, Cursor c = resolver.query(Notes.CONTENT_NOTE_URI,
new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE },
NoteColumns.PARENT_ID + "=?", NoteColumns.PARENT_ID + "=?",
new String[] { String.valueOf(folderId) }, new String[] { String.valueOf(folderId) },
null); null);//查询条件父ID是传入的folderId;
HashSet<AppWidgetAttribute> set = null; HashSet<AppWidgetAttribute> set = null;
if (c != null) { if (c != null) {
@ -211,8 +221,8 @@ public class DataUtils {
do { do {
try { try {
AppWidgetAttribute widget = new AppWidgetAttribute(); AppWidgetAttribute widget = new AppWidgetAttribute();
widget.widgetId = c.getInt(0); widget.widgetId = c.getInt(0);//0对应的NoteColumns.WIDGET_ID
widget.widgetType = c.getInt(1); widget.widgetType = c.getInt(1);//1对应的NoteColumns.WIDGET_TYPE
set.add(widget); set.add(widget);
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
Log.e(TAG, e.toString()); Log.e(TAG, e.toString());
@ -224,20 +234,21 @@ public class DataUtils {
return set; return set;
} }
//根据给定的便签ID(noteId)获取该便签中的电话号码(CallNote.PHONE_NUMBER)
public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) {
Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,
new String [] { CallNote.PHONE_NUMBER }, new String [] { CallNote.PHONE_NUMBER },
CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?",
new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE },
null); null);//在查询条件中限定了便签ID(NoteId)和便签类型(CallNote.MIME_TYPE),使用了占位符(?)和参数数组避免了SQL注入攻击
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {//如果查询结果非空且有记录,则尝试获取第一条记录的电话号码,并将其返回。
try { try {
return cursor.getString(0); return cursor.getString(0);
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
Log.e(TAG, "Get call number fails " + e.toString()); Log.e(TAG, "Get call number fails " + e.toString());//如果获取电话号码失败,则在日志中打印错误信息,并返回空字符串
} finally { } finally {
cursor.close(); cursor.close();//关闭游标(Cursor)对象
} }
} }
return ""; return "";
@ -249,19 +260,19 @@ public class DataUtils {
CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL("
+ CallNote.PHONE_NUMBER + ",?)", + CallNote.PHONE_NUMBER + ",?)",
new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber },
null); null);//在查询条件中限定了通话日期(CallNote.CALL_DATE)、便签类型(CallNote.MIME_TYPE)以及电话号码(CallNote.PHONE_NUMBER)。//使用了占位符(?)和参数数组来避免SQL注入攻击并使用PHONE_NUMBERS_EQUAL函数来比较电话号码。
//通过数据库操作查询条件是callDate和phoneNumber匹配传入参数的值
if (cursor != null) { if (cursor != null) {
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
try { try {
return cursor.getLong(0); return cursor.getLong(0);//0对应的CallNote.NOTE_ID
} catch (IndexOutOfBoundsException e) { } 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; return 0;//如果查询结果为空则返回0作为默认值。
} }
public static String getSnippetById(ContentResolver resolver, long noteId) { public static String getSnippetById(ContentResolver resolver, long noteId) {
@ -269,8 +280,8 @@ public class DataUtils {
new String [] { NoteColumns.SNIPPET }, new String [] { NoteColumns.SNIPPET },
NoteColumns.ID + "=?", NoteColumns.ID + "=?",
new String [] { String.valueOf(noteId)}, new String [] { String.valueOf(noteId)},
null); null);//查询条件noteId
//如果查询结果非空则尝试获取第一条记录的便签片段并将其赋值给变量snippet。
if (cursor != null) { if (cursor != null) {
String snippet = ""; String snippet = "";
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
@ -279,17 +290,17 @@ public class DataUtils {
cursor.close(); cursor.close();
return snippet; return snippet;
} }
throw new IllegalArgumentException("Note is not found with id: " + noteId); throw new IllegalArgumentException("Note is not found with id: " + noteId);//如果查询结果为空则抛出IllegalArgumentException异常提示便签ID不存在。
} }
public static String getFormattedSnippet(String snippet) { public static String getFormattedSnippet(String snippet) { //对字符串进行格式处理,将字符串两头的空格去掉,同时将换行符去掉
if (snippet != null) { if (snippet != null) {//首先判断传入的便签片段(snippet)是否为空。如果不为空,则执行下一步;否则直接返回空字符串
snippet = snippet.trim(); snippet = snippet.trim();//对便签片段进行trim操作去除字符串前后的空格。
int index = snippet.indexOf('\n'); int index = snippet.indexOf('\n');//查找便签片段中第一个换行符(\n)的索引位置,如果找到了,则截取从开头到该索引位置的子字符串;否则保留原始字符串。
if (index != -1) { if (index != -1) {
snippet = snippet.substring(0, index); snippet = snippet.substring(0, index);
} }
} }
return snippet; return snippet;//返回格式化后的便签片段。
} }
} }

@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
//定义了很多的静态字符串目的就是为了提供jsonObject中相应字符串的"key"。把这些静态的定义单独写到了一个类里面,这是非常好的编程规范
package net.micode.notes.tool; package net.micode.notes.tool;
//这个类就是定义了一堆static string实际就是为jsonObject提供Key把这些定义全部写到一个类里方便查看管理
public class GTaskStringUtils { public class GTaskStringUtils {
// 前面一部分常量名称都以"GTASK_JSON_"开头表示它们是Google Tasks API中JSON格式的字段名称。
public final static String GTASK_JSON_ACTION_ID = "action_id";//操作的ID
public final static String GTASK_JSON_ACTION_ID = "action_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";

@ -16,14 +16,30 @@
package net.micode.notes.tool; package net.micode.notes.tool;
import android.content.Context; import android.content.Context;//Context是一个Android系统级别的类它提供了访问应用程序资源和执行应用程序操作的方法。通过使用Context开发者可以获取应用程序的上下文环境例如访问应用程序的资源文件、启动活动、发送广播等。
import android.preference.PreferenceManager; import android.preference.PreferenceManager;//PreferenceManager是Android提供的一个管理应用程序偏好设置的类。偏好设置是一种存储和检索简单数据的机制例如用户首选项、应用程序设置等。PreferenceManager提供了一些方便的方法来读取和写入偏好设置并且可以自动处理数据类型转换和持久化存储。
import net.micode.notes.R; import net.micode.notes.R;
import net.micode.notes.ui.NotesPreferenceActivity; import net.micode.notes.ui.NotesPreferenceActivity;
public class ResourceParser {
////*简介:字面意义是资源分析器,实际上就是获取资源并且在程序中使用,比如颜色图片等
// * 实现方法主要利用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 YELLOW = 0;
public static final int BLUE = 1; public static final int BLUE = 1;
public static final int WHITE = 2; public static final int WHITE = 2;
@ -31,7 +47,7 @@ public class ResourceParser {
public static final int RED = 4; public static final int RED = 4;
public static final int BG_DEFAULT_COLOR = YELLOW; public static final int BG_DEFAULT_COLOR = YELLOW;
//定义大小编号
public static final int TEXT_SMALL = 0; public static final int TEXT_SMALL = 0;
public static final int TEXT_MEDIUM = 1; public static final int TEXT_MEDIUM = 1;
public static final int TEXT_LARGE = 2; public static final int TEXT_LARGE = 2;
@ -40,20 +56,21 @@ public class ResourceParser {
public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM;
public static class NoteBgResources { public static class NoteBgResources {
// 表示笔记编辑界面的不同背景颜色
private final static int [] BG_EDIT_RESOURCES = new int [] { private final static int [] BG_EDIT_RESOURCES = new int [] {
R.drawable.edit_yellow, R.drawable.edit_yellow,
R.drawable.edit_blue, R.drawable.edit_blue,
R.drawable.edit_white, R.drawable.edit_white,
R.drawable.edit_green, R.drawable.edit_green,
R.drawable.edit_red R.drawable.edit_red
}; };
//标题栏背景颜色
private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] {
R.drawable.edit_title_yellow, R.drawable.edit_title_yellow,
R.drawable.edit_title_blue, R.drawable.edit_title_blue,
R.drawable.edit_title_white, R.drawable.edit_title_white,
R.drawable.edit_title_green, R.drawable.edit_title_green,
R.drawable.edit_title_red R.drawable.edit_title_red
}; };
public static int getNoteBgResource(int id) { public static int getNoteBgResource(int id) {
@ -64,7 +81,9 @@ public class ResourceParser {
return BG_EDIT_TITLE_RESOURCES[id]; return BG_EDIT_TITLE_RESOURCES[id];
} }
} }
//直接获取默认的背景颜色。这个PREFERENCE_SET_BG_COLOR_KEY是个final string,也就是说getBoolean肯定执行else为什么要这么写
// getDefaultBgId方法是一个公共静态方法它接收一个Context对象作为参数并根据应用程序的偏好设置确定默认的背景颜色ID。如果偏好设置中设置了背景颜色则随机选择一个背景颜色ID否则返回一个默认的背景颜色ID。
public static int getDefaultBgId(Context context) { public static int getDefaultBgId(Context context) {
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) {
@ -74,37 +93,38 @@ public class ResourceParser {
} }
} }
// NoteItemBgResources类类似于NoteBgResources类它也包含一个私有的静态整型数组BG_FIRST_RESOURCES用于表示笔记列表项的不同背景颜色。这些资源文件ID代表了笔记列表项在不同状态下的背景样式。
public static class NoteItemBgResources { public static class NoteItemBgResources {
private final static int [] BG_FIRST_RESOURCES = new int [] { private final static int [] BG_FIRST_RESOURCES = new int [] {
R.drawable.list_yellow_up, R.drawable.list_yellow_up,
R.drawable.list_blue_up, R.drawable.list_blue_up,
R.drawable.list_white_up, R.drawable.list_white_up,
R.drawable.list_green_up, R.drawable.list_green_up,
R.drawable.list_red_up R.drawable.list_red_up
}; };
private final static int [] BG_NORMAL_RESOURCES = new int [] { private final static int [] BG_NORMAL_RESOURCES = new int [] {
R.drawable.list_yellow_middle, R.drawable.list_yellow_middle,
R.drawable.list_blue_middle, R.drawable.list_blue_middle,
R.drawable.list_white_middle, R.drawable.list_white_middle,
R.drawable.list_green_middle, R.drawable.list_green_middle,
R.drawable.list_red_middle R.drawable.list_red_middle
}; };
private final static int [] BG_LAST_RESOURCES = new int [] { private final static int [] BG_LAST_RESOURCES = new int [] {
R.drawable.list_yellow_down, R.drawable.list_yellow_down,
R.drawable.list_blue_down, R.drawable.list_blue_down,
R.drawable.list_white_down, R.drawable.list_white_down,
R.drawable.list_green_down, R.drawable.list_green_down,
R.drawable.list_red_down, R.drawable.list_red_down,
}; };
private final static int [] BG_SINGLE_RESOURCES = new int [] { private final static int [] BG_SINGLE_RESOURCES = new int [] {
R.drawable.list_yellow_single, R.drawable.list_yellow_single,
R.drawable.list_blue_single, R.drawable.list_blue_single,
R.drawable.list_white_single, R.drawable.list_white_single,
R.drawable.list_green_single, R.drawable.list_green_single,
R.drawable.list_red_single R.drawable.list_red_single
}; };
public static int getNoteBgFirstRes(int id) { public static int getNoteBgFirstRes(int id) {
@ -128,13 +148,14 @@ public class ResourceParser {
} }
} }
// 这些数组存储了一组资源文件的ID用于表示小部件widget的不同背景颜色。其中BG_2X_RESOURCES数组存储了用于2x尺寸的小部件背景颜色的资源文件ID而BG_4X_RESOURCES数组存储了用于4x尺寸的小部件背景颜色的资源文件ID。
public static class WidgetBgResources { public static class WidgetBgResources {
private final static int [] BG_2X_RESOURCES = new int [] { private final static int [] BG_2X_RESOURCES = new int [] {
R.drawable.widget_2x_yellow, R.drawable.widget_2x_yellow,
R.drawable.widget_2x_blue, R.drawable.widget_2x_blue,
R.drawable.widget_2x_white, R.drawable.widget_2x_white,
R.drawable.widget_2x_green, R.drawable.widget_2x_green,
R.drawable.widget_2x_red, R.drawable.widget_2x_red,
}; };
public static int getWidget2xBgResource(int id) { public static int getWidget2xBgResource(int id) {
@ -142,11 +163,11 @@ public class ResourceParser {
} }
private final static int [] BG_4X_RESOURCES = new int [] { private final static int [] BG_4X_RESOURCES = new int [] {
R.drawable.widget_4x_yellow, R.drawable.widget_4x_yellow,
R.drawable.widget_4x_blue, R.drawable.widget_4x_blue,
R.drawable.widget_4x_white, R.drawable.widget_4x_white,
R.drawable.widget_4x_green, R.drawable.widget_4x_green,
R.drawable.widget_4x_red R.drawable.widget_4x_red
}; };
public static int getWidget4xBgResource(int id) { public static int getWidget4xBgResource(int id) {
@ -154,14 +175,18 @@ public class ResourceParser {
} }
} }
// 用于存储一组文本外观TextAppearance的资源文件ID。这些资源文件ID代表了不同文本样式的设置如正常字体、中等字体、大号字体、超大号字体等
public static class TextAppearanceResources { public static class TextAppearanceResources {
// 可以根据给定的索引获取对应的文本样式的资源文件ID。注意这里有一个容错的函数当传入的索引大于等于资源数量时会返回默认的字体大小设置。
private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] {
R.style.TextAppearanceNormal, R.style.TextAppearanceNormal,
R.style.TextAppearanceMedium, R.style.TextAppearanceMedium,
R.style.TextAppearanceLarge, R.style.TextAppearanceLarge,
R.style.TextAppearanceSuper R.style.TextAppearanceSuper
}; };
//这里有一个容错的函数防止输入的id大于资源总量若如此则自动返回默认的设置结果
// getResourcesSize方法返回文本外观资源文件ID数组的长度也就是资源文件的总数。
public static int getTexAppearanceResource(int id) { public static int getTexAppearanceResource(int id) {
/** /**
* HACKME: Fix bug of store the resource id in shared preference. * HACKME: Fix bug of store the resource id in shared preference.
@ -179,3 +204,5 @@ public class ResourceParser {
} }
} }
} }

Loading…
Cancel
Save