From fd0f50e45acec47afbfdde1c0f366a1c40637789 Mon Sep 17 00:00:00 2001 From: wangze <1872095572@qq.com> Date: Mon, 26 May 2025 18:42:51 +0800 Subject: [PATCH] src-daima --- src/Notes/Notes.txt | 232 +++++++++++++++++ src/Notes/Notes精读.doc | Bin 0 -> 14848 bytes src/Notes/Workingnotes.txt | 374 ++++++++++++++++++++++++++++ src/Notes/Workingnotes精读.doc | Bin 0 -> 23552 bytes src/NotesDatabaseHelper.txt | 349 ++++++++++++++++++++++++++ src/NotesProvider.txt | 320 ++++++++++++++++++++++++ src/Tool/BackupUtils.txt | 311 +++++++++++++++++++++++ src/Tool/BackupUtils精读.doc | Bin 0 -> 19968 bytes src/Tool/DataUtils.txt | 263 +++++++++++++++++++ src/Tool/DataUtils精读.doc | Bin 0 -> 22016 bytes src/Tool/GTaskStringUtils.txt | 99 ++++++++ src/Tool/GTaskStringUtils精读.doc | Bin 0 -> 19456 bytes src/Tool/ResourceParser.txt | 175 +++++++++++++ src/Tool/ResourceParser精读.doc | Bin 0 -> 22016 bytes src/UI/AlarmAlertActivity.txt | 192 ++++++++++++++ src/UI/AlarmAlertActivity精读.doc | Bin 0 -> 18944 bytes src/UI/AlarmInitReceiver.txt | 56 +++++ src/UI/AlarmInitReceiver精读.doc | Bin 0 -> 19456 bytes src/UI/AlarmReceiver.txt | 20 ++ src/UI/AlarmReceiver精读.doc | Bin 0 -> 14848 bytes src/UI/DateTimePicker.txt | 0 src/UI/DateTimePicker精读.doc | Bin 0 -> 19456 bytes src/contact.txt | 69 +++++ src/notes.txt | 303 ++++++++++++++++++++++ src/充实文本编辑功能.txt | 142 +++++++++++ src/描述文档.txt | 118 +++++++++ src/界面设计.txt | 150 +++++++++++ src/登陆界面.txt | 116 +++++++++ 28 files changed, 3289 insertions(+) create mode 100644 src/Notes/Notes.txt create mode 100644 src/Notes/Notes精读.doc create mode 100644 src/Notes/Workingnotes.txt create mode 100644 src/Notes/Workingnotes精读.doc create mode 100644 src/NotesDatabaseHelper.txt create mode 100644 src/NotesProvider.txt create mode 100644 src/Tool/BackupUtils.txt create mode 100644 src/Tool/BackupUtils精读.doc create mode 100644 src/Tool/DataUtils.txt create mode 100644 src/Tool/DataUtils精读.doc create mode 100644 src/Tool/GTaskStringUtils.txt create mode 100644 src/Tool/GTaskStringUtils精读.doc create mode 100644 src/Tool/ResourceParser.txt create mode 100644 src/Tool/ResourceParser精读.doc create mode 100644 src/UI/AlarmAlertActivity.txt create mode 100644 src/UI/AlarmAlertActivity精读.doc create mode 100644 src/UI/AlarmInitReceiver.txt create mode 100644 src/UI/AlarmInitReceiver精读.doc create mode 100644 src/UI/AlarmReceiver.txt create mode 100644 src/UI/AlarmReceiver精读.doc create mode 100644 src/UI/DateTimePicker.txt create mode 100644 src/UI/DateTimePicker精读.doc create mode 100644 src/contact.txt create mode 100644 src/notes.txt create mode 100644 src/充实文本编辑功能.txt create mode 100644 src/描述文档.txt create mode 100644 src/界面设计.txt create mode 100644 src/登陆界面.txt diff --git a/src/Notes/Notes.txt b/src/Notes/Notes.txt new file mode 100644 index 0000000..f4f5021 --- /dev/null +++ b/src/Notes/Notes.txt @@ -0,0 +1,232 @@ +package net.micode.notes.model; + +import android.content.ContentProviderOperation;//批量的更新、插入、删除数据。 +import android.content.ContentProviderResult;//操作的结果 +import android.content.ContentUris;//用于添加和获取Uri后面的ID +import android.content.ContentValues;//一种用来存储基本数据类型数据的存储机制 +import android.content.Context;//需要用该类来弄清楚调用者的实例 +import android.content.OperationApplicationException;//操作应用程序容错 +import android.net.Uri;//表示待操作的数据 +import android.os.RemoteException;//远程容错 +import android.util.Log;//输出日志,比如说出错、警告等 + +public class Note { + // private ContentValues mNoteDiffValues; + ContentValues mNoteDiffValues;// + private NoteData mNoteData; + private static final String TAG = "Note"; + + /** + * Create a new note id for adding a new note to databases + */ + public static synchronized long getNewNoteId(Context context, long folderId) { + // Create a new note in the database + ContentValues values = new ContentValues(); + long createdTime = System.currentTimeMillis(); + values.put(NoteColumns.CREATED_DATE, createdTime); + values.put(NoteColumns.MODIFIED_DATE, createdTime); + values.put(NoteColumns.TYPE, Notes.TYPE_NOTE); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + values.put(NoteColumns.PARENT_ID, folderId);//将数据写入数据库表格 + Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); + //ContentResolver()主要是实现外部应用对ContentProvider中的数据 + //进行添加、删除、修改和查询操作 + long noteId = 0; + try { + noteId = Long.valueOf(uri.getPathSegments().get(1)); + } catch (NumberFormatException e) { + Log.e(TAG, "Get note id error :" + e.toString()); + noteId = 0; + }//try-catch异常处理 + if (noteId == -1) { + throw new IllegalStateException("Wrong note id:" + noteId); + } + return noteId; + } + + public Note() { + mNoteDiffValues = new ContentValues(); + mNoteData = new NoteData(); + }//定义两个变量用来存储便签的数据,一个是存储便签属性、一个是存储便签内容 + + public void setNoteValue(String key, String value) { + mNoteDiffValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + }//设置数据库表格的标签属性数据 + + public void setTextData(String key, String value) { + mNoteData.setTextData(key, value); + }//设置数据库表格的标签文本内容的数据 + + public void setTextDataId(long id) { + mNoteData.setTextDataId(id); + }//设置文本数据的ID + + public long getTextDataId() { + return mNoteData.mTextDataId; + }//得到文本数据的ID + + public void setCallDataId(long id) { + mNoteData.setCallDataId(id); + }//设置电话号码数据的ID + + public void setCallData(String key, String value) { + mNoteData.setCallData(key, value); + }//得到电话号码数据的ID + + public boolean isLocalModified() { + return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); + }//判断是否是本地修改 + + public boolean syncNote(Context context, long noteId) { + if (noteId <= 0) { + throw new IllegalArgumentException("Wrong note id:" + noteId); + } + + if (!isLocalModified()) { + return true; + } + + /** + * In theory, once data changed, the note should be updated on {@link NoteColumns#LOCAL_MODIFIED} and + * {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the + * note data info + */ + if (context.getContentResolver().update( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null, + null) == 0) { + Log.e(TAG, "Update note error, should not happen"); + // Do not return, fall through + } + mNoteDiffValues.clear(); + + if (mNoteData.isLocalModified() + && (mNoteData.pushIntoContentResolver(context, noteId) == null)) { + return false; + } + + return true; + }//判断数据是否同步 + + private class NoteData {//定义一个基本的便签内容的数据类,主要包含文本数据和电话号码数据 + private long mTextDataId; + + private ContentValues mTextDataValues;//文本数据 + + private long mCallDataId; + + private ContentValues mCallDataValues;//电话号码数据 + + private static final String TAG = "NoteData"; + + public NoteData() { + mTextDataValues = new ContentValues(); + mCallDataValues = new ContentValues(); + mTextDataId = 0; + mCallDataId = 0; + } + //下面是上述几个函数的具体实现 + boolean isLocalModified() { + return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; + } + + void setTextDataId(long id) { + if(id <= 0) { + throw new IllegalArgumentException("Text data id should larger than 0"); + } + mTextDataId = id; + } + + void setCallDataId(long id) { + if (id <= 0) { + throw new IllegalArgumentException("Call data id should larger than 0"); + } + mCallDataId = id; + } + + void setCallData(String key, String value) { + mCallDataValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + + void setTextData(String key, String value) { + mTextDataValues.put(key, value); + mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); + mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + } + //下面函数的作用是将新的数据通过Uri的操作存储到数据库 + Uri pushIntoContentResolver(Context context, long noteId) { + /** + * Check for safety + */ + if (noteId <= 0) { + throw new IllegalArgumentException("Wrong note id:" + noteId); + }//判断数据是否合法 + + ArrayList operationList = new ArrayList(); + ContentProviderOperation.Builder builder = null;//数据库的操作列表 + + if(mTextDataValues.size() > 0) { + mTextDataValues.put(DataColumns.NOTE_ID, noteId); + if (mTextDataId == 0) { + mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, + mTextDataValues); + try { + setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); + } catch (NumberFormatException e) { + Log.e(TAG, "Insert new text data fail with noteId" + noteId); + mTextDataValues.clear(); + return null; + } + } else { + builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mTextDataId)); + builder.withValues(mTextDataValues); + operationList.add(builder.build()); + } + mTextDataValues.clear(); + }//把文本数据存入DataColumns + + if(mCallDataValues.size() > 0) { + mCallDataValues.put(DataColumns.NOTE_ID, noteId); + if (mCallDataId == 0) { + mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); + Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI, + mCallDataValues); + try { + setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); + } catch (NumberFormatException e) { + Log.e(TAG, "Insert new call data fail with noteId" + noteId); + mCallDataValues.clear(); + return null; + } + } else { + builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId( + Notes.CONTENT_DATA_URI, mCallDataId)); + builder.withValues(mCallDataValues); + operationList.add(builder.build()); + } + mCallDataValues.clear(); + }//把电话号码数据存入DataColumns + + if (operationList.size() > 0) { + try { + ContentProviderResult[] results = context.getContentResolver().applyBatch( + Notes.AUTHORITY, operationList); + return (results == null || results.length == 0 || results[0] == null) ? null + : ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId); + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + return null; + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + return null; + } + }//存储过程中的异常处理 + return null; + } + } +} \ No newline at end of file diff --git a/src/Notes/Notes精读.doc b/src/Notes/Notes精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..e0c0c690d1018577a2e357c7878bee7c0725f19d GIT binary patch literal 14848 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 H0wetoK1>u< literal 0 HcmV?d00001 diff --git a/src/Notes/Workingnotes.txt b/src/Notes/Workingnotes.txt new file mode 100644 index 0000000..f67a01f --- /dev/null +++ b/src/Notes/Workingnotes.txt @@ -0,0 +1,374 @@ +package net.micode.notes.model; + +public class WorkingNote { + // Note for the working note + private Note mNote; + // Note Id + private long mNoteId; + // Note content + private String mContent; + // Note mode + private int mMode; + + private long mAlertDate; + private long mModifiedDate; + private int mBgColorId; + private int mWidgetId; + private int mWidgetType; + private long mFolderId; + private Context mContext; + + private static final String TAG = "WorkingNote"; + + private boolean mIsDeleted; + + private NoteSettingChangedListener mNoteSettingStatusListener; + + // 声明 DATA_PROJECTION字符串数组 + public static final String[] DATA_PROJECTION = new String[] { + DataColumns.ID, + DataColumns.CONTENT, + DataColumns.MIME_TYPE, + DataColumns.DATA1, + DataColumns.DATA2, + DataColumns.DATA3, + DataColumns.DATA4, + }; + + // 声明 NOTE_PROJECTION字符串数组 + public static final String[] NOTE_PROJECTION = new String[] { + NoteColumns.PARENT_ID, + NoteColumns.ALERTED_DATE, + NoteColumns.BG_COLOR_ID, + NoteColumns.WIDGET_ID, + NoteColumns.WIDGET_TYPE, + NoteColumns.MODIFIED_DATE + }; + + private static final int DATA_ID_COLUMN = 0; + private static final int DATA_CONTENT_COLUMN = 1; + private static final int DATA_MIME_TYPE_COLUMN = 2; + private static final int DATA_MODE_COLUMN = 3; + private static final int NOTE_PARENT_ID_COLUMN = 0; + private static final int NOTE_ALERTED_DATE_COLUMN = 1; + private static final int NOTE_BG_COLOR_ID_COLUMN = 2; + private static final int NOTE_WIDGET_ID_COLUMN = 3; + private static final int NOTE_WIDGET_TYPE_COLUMN = 4; + private static final int NOTE_MODIFIED_DATE_COLUMN = 5; + + // New note construct + public WorkingNote(Context context, long folderId) { + mContext = context; + mAlertDate = 0; + mModifiedDate = System.currentTimeMillis(); + mFolderId = folderId; + mNote = new Note(); + mNoteId = 0; + mIsDeleted = false; + mMode = 0; + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; + } + + // WorkingNote的构造函数 + // Existing note construct + private WorkingNote(Context context, long noteId, long folderId) { + mContext = context; + mNoteId = noteId; + mFolderId = folderId; + mIsDeleted = false; + mNote = new Note(); + loadNote(); + } + + // 加载Note + // 通过数据库调用query函数找到第一个条目 + private void loadNote() { + Cursor cursor = mContext.getContentResolver().query( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null, + null, null); + + // 若存在,储存相应信息 + if (cursor != null) { + if (cursor.moveToFirst()) { + mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN); + mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN); + mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN); + mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN); + mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN); + mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); + } + cursor.close(); + // 若不存在,报错 + } else { + Log.e(TAG, "No note with id:" + mNoteId); + throw new IllegalArgumentException("Unable to find note with id " + mNoteId); + } + loadNoteData(); + } + + // 加载NoteData + private void loadNoteData() { + Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, + DataColumns.NOTE_ID + "=?", new String[] { + String.valueOf(mNoteId) + }, null); + + if (cursor != null) { + // 查到信息不为空 + if (cursor.moveToFirst()) { // 查看第一项是否存在 + do { + String type = cursor.getString(DATA_MIME_TYPE_COLUMN); + if (DataConstants.NOTE.equals(type)) { + mContent = cursor.getString(DATA_CONTENT_COLUMN); + mMode = cursor.getInt(DATA_MODE_COLUMN); + mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN)); + } else if (DataConstants.CALL_NOTE.equals(type)) { + mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); + } else { + Log.d(TAG, "Wrong note type with type:" + type); + } + } while (cursor.moveToNext());//查阅所有项,直到为空 + } + cursor.close(); + } else { + Log.e(TAG, "No data with id:" + mNoteId); + throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId); + } + } + + // 创建空的Note + // 传参:context,文件夹id,widget,背景颜色 + public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, + int widgetType, int defaultBgColorId) { + WorkingNote note = new WorkingNote(context, folderId); + // 设定相关属性 + note.setBgColorId(defaultBgColorId); + note.setWidgetId(widgetId); + note.setWidgetType(widgetType); + return note; + } + + public static WorkingNote load(Context context, long id) { + return new WorkingNote(context, id, 0); + } + + // 保存Note + public synchronized boolean saveNote() { + if (isWorthSaving()) { //是否值得保存 + if (!existInDatabase()) { // 是否存在数据库中 + if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) { + Log.e(TAG, "Create new note fail with id:" + mNoteId); + return false; + } + } + + mNote.syncNote(mContext, mNoteId); + + /** + * Update widget content if there exist any widget of this note + */ + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE + && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + } + return true; + } else { + return false; + } + } + + // 是否在数据库中存在 + public boolean existInDatabase() { + return mNoteId > 0; + } + + // 是否值得保存 + private boolean isWorthSaving() { + // 被删除,或(不在数据库中 内容为空),或 本地已保存过 + if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent)) + || (existInDatabase() && !mNote.isLocalModified())) { + return false; + } else { + return true; + } + } + + + // 设置mNoteSettingStatusListener + public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) { + mNoteSettingStatusListener = l; + } + + // 设置AlertDate + // 若 mAlertDate与data不同,则更改mAlertDate并设定NoteValue + public void setAlertDate(long date, boolean set) { + if (date != mAlertDate) { + mAlertDate = date; + mNote.setNoteValue(NoteColumns.ALERTED_DATE, String.valueOf(mAlertDate)); + } + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onClockAlertChanged(date, set); + } + } + + // 设定删除标记 + public void markDeleted(boolean mark) { + // 设定标记 + mIsDeleted = mark; + if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onWidgetChanged(); + // 调用mNoteSettingStatusListener的 onWidgetChanged方法 + } + } + + // 设定背景颜色 + public void setBgColorId(int id) { + if (id != mBgColorId) { //设定条件 id != mBgColorId + mBgColorId = id; + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onBackgroundColorChanged(); + } + mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id)); + } + } + + // 设定检查列表模式 + // 参数:mode + public void setCheckListMode(int mode) { + if (mMode != mode) { //设定条件 mMode != mode + if (mNoteSettingStatusListener != null) { + mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode); + } + mMode = mode; + mNote.setTextData(TextNote.MODE, String.valueOf(mMode)); + } + } + + + // 设定WidgetType + // 参数:type + public void setWidgetType(int type) { + if (type != mWidgetType) {//设定条件 type != mWidgetType + mWidgetType = type; + mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType)); + // 调用Note的setNoteValue方法更改WidgetType + } + } + + // 设定WidgetId + // 参数:id + public void setWidgetId(int id) { + if (id != mWidgetId) {//设定条件 id != mWidgetId + mWidgetId = id; + mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId)); + // 调用Note的setNoteValue方法更改WidgetId + } + } + + // 设定WorkingTex + // 参数:更改的text + public void setWorkingText(String text) { + if (!TextUtils.equals(mContent, text)) {//设定条件 mContent, text内容不同 + mContent = text; + mNote.setTextData(DataColumns.CONTENT, mContent); + // 调用Note的setTextData方法更改WorkingText + } + } + + // 转变mNote的CallData及CallNote信息 + // 参数:String phoneNumber, long callDate + public void convertToCallNote(String phoneNumber, long callDate) { + mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate)); + mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber); + mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER)); + } + + // 判断是否有时钟题型 + public boolean hasClockAlert() { + return (mAlertDate > 0 ? true : false); + } + + // 获取Content + public String getContent() { + return mContent; + } + + // 获取AlertDate + public long getAlertDate() { + return mAlertDate; + } + + // 获取ModifiedDate + public long getModifiedDate() { + return mModifiedDate; + } + + // 获取背景颜色来源id + public int getBgColorResId() { + return NoteBgResources.getNoteBgResource(mBgColorId); + } + + // 获取背景颜色id + public int getBgColorId() { + return mBgColorId; + } + + // 获取标题背景颜色id + public int getTitleBgResId() { + return NoteBgResources.getNoteTitleBgResource(mBgColorId); + } + + // 获取CheckListMode + public int getCheckListMode() { + return mMode; + } + + // 获取便签id + public long getNoteId() { + return mNoteId; + } + + // 获取文件夹id + public long getFolderId() { + return mFolderId; + } + + // 获取WidgetId + public int getWidgetId() { + return mWidgetId; + } + + // 获取WidgetType + public int getWidgetType() { + return mWidgetType; + } + + // 创建接口 NoteSettingChangedListener,便签更新监视 + // 为NoteEditActivity提供接口 + // 提供函数有 + public interface NoteSettingChangedListener { + /** + * Called when the background color of current note has just changed + */ + void onBackgroundColorChanged(); + + /** + * Called when user set clock + */ + void onClockAlertChanged(long date, boolean set); + + /** + * Call when user create note from widget + */ + void onWidgetChanged(); + + /** + * Call when switch between check list mode and normal mode + * @param oldMode is previous mode before change + * @param newMode is new mode + */ + void onCheckListModeChanged(int oldMode, int newMode); + } +} \ No newline at end of file diff --git a/src/Notes/Workingnotes精读.doc b/src/Notes/Workingnotes精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..499184595c6740b9923319e85827107cff665c0c GIT binary patch literal 23552 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" + ";" + + " END";//在文件夹中移出一个Note之后需要更改的数据的表格。 + + /** + * Increase folder's note count when insert new note to the folder + */ + private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER = + "CREATE TRIGGER increase_folder_count_on_insert " + + " AFTER INSERT ON " + TABLE.NOTE + + " BEGIN " + + " UPDATE " + TABLE.NOTE + + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" + + " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" + + " END";//在文件夹中插入一个Note之后需要更改的数据的表格。 + + /** + * Decrease folder's note count when delete note from the folder + */ + private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER = + "CREATE TRIGGER decrease_folder_count_on_delete " + + " AFTER DELETE ON " + TABLE.NOTE + + " BEGIN " + + " UPDATE " + TABLE.NOTE + + " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" + + " WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID + + " AND " + NoteColumns.NOTES_COUNT + ">0;" + + " END";//在文件夹中删除一个Note之后需要更改的数据的表格。 + + /** + * Update note's content when insert data with type {@link DataConstants#NOTE} + */ + private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER = + "CREATE TRIGGER update_note_content_on_insert " + + " AFTER INSERT ON " + TABLE.DATA + + " WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + + " BEGIN" + + " UPDATE " + TABLE.NOTE + + " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + + " END";//在文件夹中对一个Note导入新的数据之后需要更改的数据的表格。 + + /** + * Update note's content when data with {@link DataConstants#NOTE} type has changed + */ + private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER = + "CREATE TRIGGER update_note_content_on_update " + + " AFTER UPDATE ON " + TABLE.DATA + + " WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + + " BEGIN" + + " UPDATE " + TABLE.NOTE + + " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT + + " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" + + " END";//Note数据被修改后需要更改的数据的表格。 + + /** + * Update note's content when data with {@link DataConstants#NOTE} type has deleted + */ + private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER = + "CREATE TRIGGER update_note_content_on_delete " + + " AFTER delete ON " + TABLE.DATA + + " WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" + + " BEGIN" + + " UPDATE " + TABLE.NOTE + + " SET " + NoteColumns.SNIPPET + "=''" + + " WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" + + " END";//Note数据被删除后需要更改的数据的表格。 + + /** + * Delete datas belong to note which has been deleted + */ + private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER = + "CREATE TRIGGER delete_data_on_delete " + + " AFTER DELETE ON " + TABLE.NOTE + + " BEGIN" + + " DELETE FROM " + TABLE.DATA + + " WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" + + " END";//删除已删除的便签的数据后需要更改的数据的表格。 + + /** + * Delete notes belong to folder which has been deleted + */ + private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER = + "CREATE TRIGGER folder_delete_notes_on_delete " + + " AFTER DELETE ON " + TABLE.NOTE + + " BEGIN" + + " DELETE FROM " + TABLE.NOTE + + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + + " END";//删除已删除的文件夹的便签后需要更改的数据的表格。 + + /** + * Move notes belong to folder which has been moved to trash folder + */ + private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER = + "CREATE TRIGGER folder_move_notes_on_trash " + + " AFTER UPDATE ON " + TABLE.NOTE + + " WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + + " BEGIN" + + " UPDATE " + TABLE.NOTE + + " SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER + + " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" + + " END";//还原垃圾桶中便签后需要更改的数据的表格。 + + public NotesDatabaseHelper(Context context) { + super(context, DB_NAME, null, DB_VERSION); + }//构造函数,传入数据库的名称和版本 + + public void createNoteTable(SQLiteDatabase db) { + db.execSQL(CREATE_NOTE_TABLE_SQL); + reCreateNoteTableTriggers(db); + createSystemFolder(db); + Log.d(TAG, "note table has been created"); + }//创建表格(用来存储标签属性) + + private void reCreateNoteTableTriggers(SQLiteDatabase db) { + db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update"); + db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update"); + db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete"); + db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete"); + db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert"); + db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete"); + db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash"); + + db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); + db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER); + db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER); + db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER); + db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER); + db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER); + db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER); + }//execSQL是数据库操作的API,主要是更改行为的SQL语句。 + //在这里主要是用来重新创建上述定义的表格用的,先删除原来有的数据库的触发器再重新创建新的数据库 + + private void createSystemFolder(SQLiteDatabase db) { + ContentValues values = new ContentValues(); + + /** + * call record foler for call notes + */ + values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER); + values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); + db.insert(TABLE.NOTE, null, values); + + /** + * root folder which is default folder + */ + values.clear(); + values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER); + values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); + db.insert(TABLE.NOTE, null, values); + + /** + * temporary folder which is used for moving note + */ + values.clear(); + values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER); + values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); + db.insert(TABLE.NOTE, null, values); + + /** + * create trash folder + */ + values.clear(); + values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); + values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); + db.insert(TABLE.NOTE, null, values); + }//创建几个系统文件夹 + + public void createDataTable(SQLiteDatabase db) { + db.execSQL(CREATE_DATA_TABLE_SQL); + reCreateDataTableTriggers(db); + db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); + Log.d(TAG, "data table has been created"); + }//创建表格(用来存储标签内容) + + private void reCreateDataTableTriggers(SQLiteDatabase db) { + db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert"); + db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update"); + db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete"); + + db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER); + db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER); + db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER); + }//同上面的execSQL + + static synchronized NotesDatabaseHelper getInstance(Context context) { + if (mInstance == null) { + mInstance = new NotesDatabaseHelper(context); + } + return mInstance; + }//上网查是为解决同一时刻只能有一个线程执行. + //在写程序库代码时,有时有一个类需要被所有的其它类使用, + //但又要求这个类只能被实例化一次,是个服务类,定义一次,其它类使用同一个这个类的实例 + + @Override + public void onCreate(SQLiteDatabase db) { + createNoteTable(db); + createDataTable(db); + }//实现两个表格(上面创建的两个表格) + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + boolean reCreateTriggers = false; + boolean skipV2 = false; + + if (oldVersion == 1) { + upgradeToV2(db); + skipV2 = true; // this upgrade including the upgrade from v2 to v3 + oldVersion++; + } + + if (oldVersion == 2 && !skipV2) { + upgradeToV3(db); + reCreateTriggers = true; + oldVersion++; + } + + if (oldVersion == 3) { + upgradeToV4(db); + oldVersion++; + } + + if (reCreateTriggers) { + reCreateNoteTableTriggers(db); + reCreateDataTableTriggers(db); + } + + if (oldVersion != newVersion) { + throw new IllegalStateException("Upgrade notes database to version " + newVersion + + "fails"); + } + }//数据库版本的更新(数据库内容的更改) + + private void upgradeToV2(SQLiteDatabase db) { + db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE); + db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA); + createNoteTable(db); + createDataTable(db); + }//更新到V2版本 + + private void upgradeToV3(SQLiteDatabase db) { + // drop unused triggers + db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert"); + db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete"); + db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update"); + // add a column for gtask id + db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID + + " TEXT NOT NULL DEFAULT ''"); + // add a trash system folder + ContentValues values = new ContentValues(); + values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER); + values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); + db.insert(TABLE.NOTE, null, values); + }//更新到V3版本 + + private void upgradeToV4(SQLiteDatabase db) { + db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION + + " INTEGER NOT NULL DEFAULT 0"); + }//更新到V4版本,但是不知道V2、V3、V4是什么意思 +} \ No newline at end of file diff --git a/src/NotesProvider.txt b/src/NotesProvider.txt new file mode 100644 index 0000000..8764365 --- /dev/null +++ b/src/NotesProvider.txt @@ -0,0 +1,320 @@ +package net.micode.notes.data; + +import android.app.SearchManager; +import android.content.ContentProvider; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Intent; +import android.content.UriMatcher; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.text.TextUtils; +import android.util.Log; + +import net.micode.notes.R; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.data.NotesDatabaseHelper.TABLE; +//为存储和获取数据提供接口。可以在不同的应用程序之间共享数据 +//ContentProvider提供的方法 +//query:查询 +//insert:插入 +//update:更新 +//delete:删除 +//getType:得到数据类型 +public class NotesProvider extends ContentProvider { + // UriMatcher用于匹配Uri + private static final UriMatcher mMatcher; + + private NotesDatabaseHelper mHelper; + + private static final String TAG = "NotesProvider"; + + private static final int URI_NOTE = 1; + private static final int URI_NOTE_ITEM = 2; + private static final int URI_DATA = 3; + private static final int URI_DATA_ITEM = 4; + + private static final int URI_SEARCH = 5; + private static final int URI_SEARCH_SUGGEST = 6; + + static { + // 创建UriMatcher时,调用UriMatcher(UriMatcher.NO_MATCH)表示不匹配任何路径的返回码 + mMatcher = new UriMatcher(UriMatcher.NO_MATCH); + // 把需要匹配Uri路径全部给注册上 + mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); + mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); + mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); + mMatcher.addURI(Notes.AUTHORITY, "data/#", URI_DATA_ITEM); + mMatcher.addURI(Notes.AUTHORITY, "search", URI_SEARCH); + mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, URI_SEARCH_SUGGEST); + mMatcher.addURI(Notes.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", URI_SEARCH_SUGGEST); + } + + /** + * x'0A' represents the '\n' character in sqlite. For title and content in the search result, + * we will trim '\n' and white space in order to show more information. + */ + // 声明 NOTES_SEARCH_PROJECTION + private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," + + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," + + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," + + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; + // 声明NOTES_SNIPPET_SEARCH_QUERY + private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION + + " FROM " + TABLE.NOTE + + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" + + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; + + @Override + // Context只有在onCreate()中才被初始化 + // 对mHelper进行实例化 + public boolean onCreate() { + mHelper = NotesDatabaseHelper.getInstance(getContext()); + return true; + } + + @Override + // 查询uri在数据库中对应的位置 + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { + Cursor c = null; + // 获取可读数据库 + SQLiteDatabase db = mHelper.getReadableDatabase(); + String id = null; + // 匹配查找uri + switch (mMatcher.match(uri)) { + // 对于不同的匹配值,在数据库中查找相应的条目 + case URI_NOTE: + c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, + sortOrder); + break; + case URI_NOTE_ITEM: + id = uri.getPathSegments().get(1); + c = db.query(TABLE.NOTE, projection, NoteColumns.ID + "=" + id + + parseSelection(selection), selectionArgs, null, null, sortOrder); + break; + case URI_DATA: + c = db.query(TABLE.DATA, projection, selection, selectionArgs, null, null, + sortOrder); + break; + case URI_DATA_ITEM: + id = uri.getPathSegments().get(1); + c = db.query(TABLE.DATA, projection, DataColumns.ID + "=" + id + + parseSelection(selection), selectionArgs, null, null, sortOrder); + break; + case URI_SEARCH: + case URI_SEARCH_SUGGEST: + if (sortOrder != null || projection != null) { + // 不合法的参数异常 + throw new IllegalArgumentException( + "do not specify sortOrder, selection, selectionArgs, or projection" + "with this query"); + } + + String searchString = null; + if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) { + if (uri.getPathSegments().size() > 1) { + // getPathSegments()方法得到一个String的List, + // 在uri.getPathSegments().get(1)为第2个元素 + searchString = uri.getPathSegments().get(1); + } + } else { + searchString = uri.getQueryParameter("pattern"); + } + + if (TextUtils.isEmpty(searchString)) { + return null; + } + + try { + searchString = String.format("%%%s%%", searchString); + c = db.rawQuery(NOTES_SNIPPET_SEARCH_QUERY, + new String[] { searchString }); + } catch (IllegalStateException ex) { + Log.e(TAG, "got exception: " + ex.toString()); + } + break; + default: + // 抛出异常 + throw new IllegalArgumentException("Unknown URI " + uri); + } + if (c != null) { + c.setNotificationUri(getContext().getContentResolver(), uri); + } + return c; + } + + @Override + // 插入一个uri + public Uri insert(Uri uri, ContentValues values) { + // 获得可写的数据库 + SQLiteDatabase db = mHelper.getWritableDatabase(); + long dataId = 0, noteId = 0, insertedId = 0; + switch (mMatcher.match(uri)) { + // 新增一个条目 + case URI_NOTE: + insertedId = noteId = db.insert(TABLE.NOTE, null, values); + break; + // 如果存在,查找NOTE_ID + case URI_DATA: + if (values.containsKey(DataColumns.NOTE_ID)) { + noteId = values.getAsLong(DataColumns.NOTE_ID); + } else { + Log.d(TAG, "Wrong data format without note id:" + values.toString()); + } + insertedId = dataId = db.insert(TABLE.DATA, null, values); + break; + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + // Notify the note uri + // notifyChange获得一个ContextResolver对象并且更新里面的内容 + if (noteId > 0) { + getContext().getContentResolver().notifyChange( + ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null); + } + + // Notify the data uri + if (dataId > 0) { + getContext().getContentResolver().notifyChange( + ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null); + } + + // 返回插入的uri的路径 + return ContentUris.withAppendedId(uri, insertedId); + } + + @Override + // 删除一个uri + public int delete(Uri uri, String selection, String[] selectionArgs) { + //Uri代表要操作的数据,Android上可用的每种资源 -包括 图像、视频片段、音频资源等都可以用Uri来表示。 + int count = 0; + String id = null; + // 获得可写的数据库 + SQLiteDatabase db = mHelper.getWritableDatabase(); + boolean deleteData = false; + switch (mMatcher.match(uri)) { + case URI_NOTE: + selection = "(" + selection + ") AND " + NoteColumns.ID + ">0 "; + count = db.delete(TABLE.NOTE, selection, selectionArgs); + break; + case URI_NOTE_ITEM: + id = uri.getPathSegments().get(1); + /** + * ID that smaller than 0 is system folder which is not allowed to + * trash + */ + long noteId = Long.valueOf(id); + if (noteId <= 0) { + break; + } + count = db.delete(TABLE.NOTE, + NoteColumns.ID + "=" + id + parseSelection(selection), selectionArgs); + break; + case URI_DATA: + count = db.delete(TABLE.DATA, selection, selectionArgs); + deleteData = true; + break; + case URI_DATA_ITEM: + id = uri.getPathSegments().get(1); + count = db.delete(TABLE.DATA, + DataColumns.ID + "=" + id + parseSelection(selection), selectionArgs); + deleteData = true; + break; + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + if (count > 0) { + if (deleteData) { + getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); + } + getContext().getContentResolver().notifyChange(uri, null); + } + return count; + } + + @Override + // 更新一个uri + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + int count = 0; + String id = null; + SQLiteDatabase db = mHelper.getWritableDatabase(); + boolean updateData = false; + switch (mMatcher.match(uri)) { + case URI_NOTE: + increaseNoteVersion(-1, selection, selectionArgs); + count = db.update(TABLE.NOTE, values, selection, selectionArgs); + break; + case URI_NOTE_ITEM: + id = uri.getPathSegments().get(1); + increaseNoteVersion(Long.valueOf(id), selection, selectionArgs); + count = db.update(TABLE.NOTE, values, NoteColumns.ID + "=" + id + + parseSelection(selection), selectionArgs); + break; + case URI_DATA: + count = db.update(TABLE.DATA, values, selection, selectionArgs); + updateData = true; + break; + case URI_DATA_ITEM: + id = uri.getPathSegments().get(1); + count = db.update(TABLE.DATA, values, DataColumns.ID + "=" + id + + parseSelection(selection), selectionArgs); + updateData = true; + break; + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + + if (count > 0) { + if (updateData) { + getContext().getContentResolver().notifyChange(Notes.CONTENT_NOTE_URI, null); + } + getContext().getContentResolver().notifyChange(uri, null); + } + return count; + } + + // 将字符串解析成规定格式 + private String parseSelection(String selection) { + return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); + } + + //增加一个noteVersion + private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { + StringBuilder sql = new StringBuilder(120); + sql.append("UPDATE "); + sql.append(TABLE.NOTE); + sql.append(" SET "); + sql.append(NoteColumns.VERSION); + sql.append("=" + NoteColumns.VERSION + "+1 "); + + if (id > 0 || !TextUtils.isEmpty(selection)) { + sql.append(" WHERE "); + } + if (id > 0) { + sql.append(NoteColumns.ID + "=" + String.valueOf(id)); + } + if (!TextUtils.isEmpty(selection)) { + String selectString = id > 0 ? parseSelection(selection) : selection; + for (String args : selectionArgs) { + selectString = selectString.replaceFirst("\\?", args); + } + sql.append(selectString); + } + + // execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句 + mHelper.getWritableDatabase().execSQL(sql.toString()); + } + + @Override + public String getType(Uri uri) { + // TODO Auto-generated method stub + return null; + } + +} \ No newline at end of file diff --git a/src/Tool/BackupUtils.txt b/src/Tool/BackupUtils.txt new file mode 100644 index 0000000..177eeb3 --- /dev/null +++ b/src/Tool/BackupUtils.txt @@ -0,0 +1,311 @@ +package net.micode.notes.tool; + +public class BackupUtils { + private static final String TAG = "BackupUtils"; + // Singleton stuff + private static BackupUtils sInstance; //类里面为什么可以定义自身类的对象? + + public static synchronized BackupUtils getInstance(Context context) { + //ynchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A) + //运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。 + //它包括两种用法:synchronized 方法和 synchronized 块。 + if (sInstance == null) { + //如果当前备份不存在,则新声明一个 + sInstance = new BackupUtils(context); + } + return sInstance; + } + + /** + * Following states are signs to represents backup or restore + * status + */ + // Currently, the sdcard is not mounted SD卡没有被装入手机 + public static final int STATE_SD_CARD_UNMOUONTED = 0; + // The backup file not exist 备份文件夹不存在 + public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; + // The data is not well formated, may be changed by other programs 数据已被破坏,可能被修改 + public static final int STATE_DATA_DESTROIED = 2; + // Some run-time exception which causes restore or backup fails 超时异常 + public static final int STATE_SYSTEM_ERROR = 3; + // Backup or restore success 成功存储 + public static final int STATE_SUCCESS = 4; + + private TextExport mTextExport; + + private BackupUtils(Context context) { //初始化函数 + mTextExport = new TextExport(context); + } + + private static boolean externalStorageAvailable() { //外部存储功能是否可用 + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); + } + + public int exportToText() { + return mTextExport.exportToText(); + } + + public String getExportedTextFileName() { + return mTextExport.mFileName; + } + + public String getExportedTextFileDir() { + return mTextExport.mFileDirectory; + } + + private static class TextExport { + private static final String[] NOTE_PROJECTION = { + NoteColumns.ID, + NoteColumns.MODIFIED_DATE, + NoteColumns.SNIPPET, + NoteColumns.TYPE + }; + + private static final int NOTE_COLUMN_ID = 0; + + private static final int NOTE_COLUMN_MODIFIED_DATE = 1; + + private static final int NOTE_COLUMN_SNIPPET = 2; + + private static final String[] DATA_PROJECTION = { + DataColumns.CONTENT, + DataColumns.MIME_TYPE, + DataColumns.DATA1, + DataColumns.DATA2, + DataColumns.DATA3, + DataColumns.DATA4, + }; + + private static final int DATA_COLUMN_CONTENT = 0; + + private static final int DATA_COLUMN_MIME_TYPE = 1; + + private static final int DATA_COLUMN_CALL_DATE = 2; + + private static final int DATA_COLUMN_PHONE_NUMBER = 4; + + private final String [] TEXT_FORMAT; + private static final int FORMAT_FOLDER_NAME = 0; + private static final int FORMAT_NOTE_DATE = 1; + private static final int FORMAT_NOTE_CONTENT = 2; + + private Context mContext; + private String mFileName; + private String mFileDirectory; + + public TextExport(Context context) { + TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); + mContext = context; + mFileName = ""; //为什么为空? + mFileDirectory = ""; + } + + private String getFormat(int id) { //获取文本的组成部分 + return TEXT_FORMAT[id]; + } + + /** + * Export the folder identified by folder id to text + */ + private void exportFolderToText(String folderId, PrintStream ps) { + // Query notes belong to this folder 通过查询parent id是文件夹id的note来选出制定ID文件夹下的Note + Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { + folderId + }, null); + + if (notesCursor != null) { + if (notesCursor.moveToFirst()) { + do { + // Print note's last modified date ps里面保存有这份note的日期 + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); + // Query data belong to this note + String noteId = notesCursor.getString(NOTE_COLUMN_ID); + exportNoteToText(noteId, ps); //将文件导出到text + } while (notesCursor.moveToNext()); + } + notesCursor.close(); + } + } + + /** + * Export note identified by id to a print stream + */ + private void exportNoteToText(String noteId, PrintStream ps) { + Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, + DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { + noteId + }, null); + + if (dataCursor != null) { //利用光标来扫描内容,区别为callnote和note两种,靠ps.printline输出 + if (dataCursor.moveToFirst()) { + do { + String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); + if (DataConstants.CALL_NOTE.equals(mimeType)) { + // Print phone number + String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); + long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); + String location = dataCursor.getString(DATA_COLUMN_CONTENT); + + if (!TextUtils.isEmpty(phoneNumber)) { //判断是否为空字符 + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + phoneNumber)); + } + // Print call date + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat + .format(mContext.getString(R.string.format_datetime_mdhm), + callDate))); + // Print call attachment location + if (!TextUtils.isEmpty(location)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + location)); + } + } else if (DataConstants.NOTE.equals(mimeType)) { + String content = dataCursor.getString(DATA_COLUMN_CONTENT); + if (!TextUtils.isEmpty(content)) { + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + content)); + } + } + } while (dataCursor.moveToNext()); + } + dataCursor.close(); + } + // print a line separator between note + try { + ps.write(new byte[] { + Character.LINE_SEPARATOR, Character.LETTER_NUMBER + }); + } catch (IOException e) { + Log.e(TAG, e.toString()); + } + } + + /** + * Note will be exported as text which is user readable + */ + public int exportToText() { //总函数,调用上面的exportFolder和exportNote + if (!externalStorageAvailable()) { + Log.d(TAG, "Media was not mounted"); + return STATE_SD_CARD_UNMOUONTED; + } + + PrintStream ps = getExportToTextPrintStream(); + if (ps == null) { + Log.e(TAG, "get print stream error"); + return STATE_SYSTEM_ERROR; + } + // First export folder and its notes 导出文件夹,就是导出里面包含的便签 + Cursor folderCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + "(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, null, null); + + if (folderCursor != null) { + if (folderCursor.moveToFirst()) { + do { + // Print folder's name + String folderName = ""; + if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { + folderName = mContext.getString(R.string.call_record_folder_name); + } else { + folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET); + } + if (!TextUtils.isEmpty(folderName)) { + ps.println(String.format(getFormat(FORMAT_FOLDER_NAME), folderName)); + } + String folderId = folderCursor.getString(NOTE_COLUMN_ID); + exportFolderToText(folderId, ps); + } while (folderCursor.moveToNext()); + } + folderCursor.close(); + } + + // Export notes in root's folder 将根目录里的便签导出(由于不属于任何文件夹,因此无法通过文件夹导出来实现这一部分便签的导出) + Cursor noteCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + NoteColumns.TYPE + "=" + +Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + + "=0", null, null); + + if (noteCursor != null) { + if (noteCursor.moveToFirst()) { + do { + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); + // Query data belong to this note + String noteId = noteCursor.getString(NOTE_COLUMN_ID); + exportNoteToText(noteId, ps); + } while (noteCursor.moveToNext()); + } + noteCursor.close(); + } + ps.close(); + + return STATE_SUCCESS; + } + + /** + * Get a print stream pointed to the file {@generateExportedTextFile} + */ + private PrintStream getExportToTextPrintStream() { + File file = generateFileMountedOnSDcard(mContext, R.string.file_path, + R.string.file_name_txt_format); + if (file == null) { + Log.e(TAG, "create file to exported failed"); + return null; + } + mFileName = file.getName(); + mFileDirectory = mContext.getString(R.string.file_path); + PrintStream ps = null; + try { + FileOutputStream fos = new FileOutputStream(file); + ps = new PrintStream(fos); //将ps输出流输出到特定的文件,目的就是导出到文件,而不是直接输出 + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } catch (NullPointerException e) { + e.printStackTrace(); + return null; + } + return ps; + } + } + + /** + * Generate the text file to store imported data + */ + private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { + StringBuilder sb = new StringBuilder(); + sb.append(Environment.getExternalStorageDirectory()); //外部(SD卡)的存储路径 + sb.append(context.getString(filePathResId)); //文件的存储路径 + File filedir = new File(sb.toString()); //filedir应该就是用来存储路径信息 + sb.append(context.getString( + fileNameFormatResId, + DateFormat.format(context.getString(R.string.format_date_ymd), + System.currentTimeMillis()))); + File file = new File(sb.toString()); + + try { //如果这些文件不存在,则新建 + if (!filedir.exists()) { + filedir.mkdir(); + } + if (!file.exists()) { + file.createNewFile(); + } + return file; + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } +// try catch 异常处理 + return null; + } +} + \ No newline at end of file diff --git a/src/Tool/BackupUtils精读.doc b/src/Tool/BackupUtils精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..13db99709b68fef0f4f34cb6b6ef8f8c7822ed4b GIT binary patch literal 19968 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 BkUszb literal 0 HcmV?d00001 diff --git a/src/Tool/DataUtils.txt b/src/Tool/DataUtils.txt new file mode 100644 index 0000000..df7a068 --- /dev/null +++ b/src/Tool/DataUtils.txt @@ -0,0 +1,263 @@ +package net.micode.notes.tool; + +public class DataUtils { + public static final String TAG = "DataUtils"; + public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { //直接删除多个笔记 + if (ids == null) { + Log.d(TAG, "the ids is null"); + return true; + } + if (ids.size() == 0) { + Log.d(TAG, "no id is in the hashset"); + return true; + } + + ArrayList operationList = new ArrayList(); //提供一个任务列表 + for (long id : ids) { + if(id == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Don't delete system folder root"); + continue; + } //如果发现是根文件夹,则不删除 + ContentProviderOperation.Builder builder = ContentProviderOperation + .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); //用newDelete实现删除功能 + operationList.add(builder.build()); // + } + try { + ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList);//主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。 + //数据库事务,数据库事务是由一组数据库操作序列组成,事务作为一个整体被执行 + if (results == null || results.length == 0 || results[0] == null) { + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); + return false; + } + return true; + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } + return false; + } + + public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.PARENT_ID, desFolderId); + values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); //对需要移动的便签进行数据更新,然后用update实现 + } + + public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, + long folderId) { + if (ids == null) { + Log.d(TAG, "the ids is null"); + return true; + } + + ArrayList operationList = new ArrayList(); + for (long id : ids) { + ContentProviderOperation.Builder builder = ContentProviderOperation + .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); //通过withAppendedId方法,为该Uri加上ID + builder.withValue(NoteColumns.PARENT_ID, folderId); + builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); + operationList.add(builder.build()); + }//将ids里包含的每一列的数据逐次加入到operationList中,等待最后的批量处理 + + try { + ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList); //applyBatch一次性处理一个操作列表 + if (results == null || results.length == 0 || results[0] == null) { + Log.d(TAG, "delete notes failed, ids:" + ids.toString()); + return false; + } + return true; + } catch (RemoteException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } catch (OperationApplicationException e) { + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); + } + return false; + } + + /** + * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} + */ + public static int getUserFolderCount(ContentResolver resolver) { + Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, + new String[] { "COUNT(*)" }, + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", + new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, + null); //筛选条件:源文件不为trash folder + + int count = 0; + if(cursor != null) { + if(cursor.moveToFirst()) { + try { + count = cursor.getInt(0); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "get folder count failed:" + e.toString()); + } finally { + cursor.close(); + } + } + } + return count; + } + + public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), //通过withAppendedId方法,为该Uri加上ID + null, + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, + new String [] {String.valueOf(type)}, + null); //查询条件:type符合,且不属于垃圾文件夹 + + boolean exist = false; + if (cursor != null) { + if (cursor.getCount() > 0) {//用getcount函数判断cursor是否为空 + exist = true; + } + cursor.close(); + } + 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); + + boolean exist = false; + if (cursor != null) { + if (cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + 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); + + boolean exist = false; + if (cursor != null) { + if (cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist; + } + + public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.SNIPPET + "=?", + new String[] { name }, null); + //通过名字查询文件是否存在 + boolean exist = false; + if(cursor != null) { + if(cursor.getCount() > 0) { + exist = true; + } + cursor.close(); + } + return exist; + } + + public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) { + Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, + new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, + NoteColumns.PARENT_ID + "=?", + new String[] { String.valueOf(folderId) }, + null); //查询条件:父ID是传入的folderId; + + HashSet set = null; + if (c != null) { + if (c.moveToFirst()) { + set = new HashSet(); + do { + try { + AppWidgetAttribute widget = new AppWidgetAttribute(); + widget.widgetId = c.getInt(0); //0对应的NoteColumns.WIDGET_ID + widget.widgetType = c.getInt(1); //1对应的NoteColumns.WIDGET_TYPE + set.add(widget); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, e.toString()); + } + } while (c.moveToNext()); //查询下一条 + } + c.close(); + } + return set; + } + + public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.PHONE_NUMBER }, + CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", + new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, + null); + + if (cursor != null && cursor.moveToFirst()) { + try { + return cursor.getString(0); + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "Get call number fails " + e.toString()); + } finally { + cursor.close(); + } + } + return ""; + } + + public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.NOTE_ID }, + CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" + + CallNote.PHONE_NUMBER + ",?)", + new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, + null); + //通过数据库操作,查询条件是(callDate和phoneNumber匹配传入参数的值) + + if (cursor != null) { + if (cursor.moveToFirst()) { + try { + return cursor.getLong(0); //0对应的CallNote.NOTE_ID + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, "Get call note id fails " + e.toString()); + } + } + cursor.close(); + } + return 0; + } + + public static String getSnippetById(ContentResolver resolver, long noteId) { + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, + new String [] { NoteColumns.SNIPPET }, + NoteColumns.ID + "=?", + new String [] { String.valueOf(noteId)}, + null);//查询条件:noteId + + if (cursor != null) { + String snippet = ""; + if (cursor.moveToFirst()) { + snippet = cursor.getString(0); + } + cursor.close(); + return snippet; + } + throw new IllegalArgumentException("Note is not found with id: " + noteId); + } + public static String getFormattedSnippet(String snippet) { //对字符串进行格式处理,将字符串两头的空格去掉,同时将换行符去掉 + if (snippet != null) { + snippet = snippet.trim(); + int index = snippet.indexOf('\n'); + if (index != -1) { + snippet = snippet.substring(0, index); + } + } + return snippet; + } + +} \ No newline at end of file diff --git a/src/Tool/DataUtils精读.doc b/src/Tool/DataUtils精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..8c41f3639381df0b40d60ba209b74c77cba9566b GIT binary patch literal 22016 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 m24Rt#R_oRxq%US2(mM8ad}EH7 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 R6^m1amI;9e!dJcp{tq2kwMqa0 literal 0 HcmV?d00001 diff --git a/src/Tool/ResourceParser.txt b/src/Tool/ResourceParser.txt new file mode 100644 index 0000000..3528455 --- /dev/null +++ b/src/Tool/ResourceParser.txt @@ -0,0 +1,175 @@ +package net.micode.notes.tool; + +/*简介:字面意义是资源分析器,实际上就是获取资源并且在程序中使用,比如颜色图片等 + * 实现方法:主要利用R.java这个类,其中包括 + * R.id 组件资源引用 + * R.drawable 图片资源 (被使用) + * R.layout 布局资源 + * R.menu 菜单资源 + * R.String 文字资源 + * R.style 主题资源 (被使用) + * 在按顺序设置好相应的id后,就可以编写简单的getXXX函数获取需要的资源 + * + * 特殊的变量 : + * @BG_DEFAULT_COLOR 默认背景颜色(黄) + * BG_DEFAULT_FONT_SIZE 默认文本大小(中) + */ + +public class ResourceParser { + + public static final int YELLOW = 0; + public static final int BLUE = 1; + public static final int WHITE = 2; + public static final int GREEN = 3; + public static final int RED = 4; + + public static final int BG_DEFAULT_COLOR = YELLOW; + + public static final int TEXT_SMALL = 0; + public static final int TEXT_MEDIUM = 1; + public static final int TEXT_LARGE = 2; + public static final int TEXT_SUPER = 3; + + public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; + + public static class NoteBgResources { + private final static int [] BG_EDIT_RESOURCES = new int [] { + R.drawable.edit_yellow, + R.drawable.edit_blue, + R.drawable.edit_white, + R.drawable.edit_green, + R.drawable.edit_red + }; + + private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { + R.drawable.edit_title_yellow, + R.drawable.edit_title_blue, + R.drawable.edit_title_white, + R.drawable.edit_title_green, + R.drawable.edit_title_red + }; + + public static int getNoteBgResource(int id) { + return BG_EDIT_RESOURCES[id]; + } + + public static int getNoteTitleBgResource(int id) { + return BG_EDIT_TITLE_RESOURCES[id]; + } + } + //直接获取默认的背景颜色。看不太懂,这个PREFERENCE_SET_BG_COLOR_KEY是个final string,也就是说getBoolean肯定执行else,为什么要这么写 + public static int getDefaultBgId(Context context) { + if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( + NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { + return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length); + } else { + return BG_DEFAULT_COLOR; + } + } + + public static class NoteItemBgResources { + private final static int [] BG_FIRST_RESOURCES = new int [] { + R.drawable.list_yellow_up, + R.drawable.list_blue_up, + R.drawable.list_white_up, + R.drawable.list_green_up, + R.drawable.list_red_up + }; + + private final static int [] BG_NORMAL_RESOURCES = new int [] { + R.drawable.list_yellow_middle, + R.drawable.list_blue_middle, + R.drawable.list_white_middle, + R.drawable.list_green_middle, + R.drawable.list_red_middle + }; + + private final static int [] BG_LAST_RESOURCES = new int [] { + R.drawable.list_yellow_down, + R.drawable.list_blue_down, + R.drawable.list_white_down, + R.drawable.list_green_down, + R.drawable.list_red_down, + }; + + private final static int [] BG_SINGLE_RESOURCES = new int [] { + R.drawable.list_yellow_single, + R.drawable.list_blue_single, + R.drawable.list_white_single, + R.drawable.list_green_single, + R.drawable.list_red_single + }; + + public static int getNoteBgFirstRes(int id) { + return BG_FIRST_RESOURCES[id]; + } + + public static int getNoteBgLastRes(int id) { + return BG_LAST_RESOURCES[id]; + } + + public static int getNoteBgSingleRes(int id) { + return BG_SINGLE_RESOURCES[id]; + } + + public static int getNoteBgNormalRes(int id) { + return BG_NORMAL_RESOURCES[id]; + } + + public static int getFolderBgRes() { + return R.drawable.list_folder; + } + } + + public static class WidgetBgResources { + private final static int [] BG_2X_RESOURCES = new int [] { + R.drawable.widget_2x_yellow, + R.drawable.widget_2x_blue, + R.drawable.widget_2x_white, + R.drawable.widget_2x_green, + R.drawable.widget_2x_red, + }; + + public static int getWidget2xBgResource(int id) { + return BG_2X_RESOURCES[id]; + } + + private final static int [] BG_4X_RESOURCES = new int [] { + R.drawable.widget_4x_yellow, + R.drawable.widget_4x_blue, + R.drawable.widget_4x_white, + R.drawable.widget_4x_green, + R.drawable.widget_4x_red + }; + + public static int getWidget4xBgResource(int id) { + return BG_4X_RESOURCES[id]; + } + } + + public static class TextAppearanceResources { + private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { + R.style.TextAppearanceNormal, + R.style.TextAppearanceMedium, + R.style.TextAppearanceLarge, + R.style.TextAppearanceSuper + }; + + //这里有一个容错的函数,防止输入的id大于资源总量,若如此,则自动返回默认的设置结果 + public static int getTexAppearanceResource(int id) { + /** + * HACKME: Fix bug of store the resource id in shared preference. + * The id may larger than the length of resources, in this case, + * return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE} + */ + if (id >= TEXTAPPEARANCE_RESOURCES.length) { + return BG_DEFAULT_FONT_SIZE; + } + return TEXTAPPEARANCE_RESOURCES[id]; + } + + public static int getResourcesSize() { + return TEXTAPPEARANCE_RESOURCES.length; + } + } +} \ No newline at end of file diff --git a/src/Tool/ResourceParser精读.doc b/src/Tool/ResourceParser精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..a67cc6402646235216364189898df0df89843260 GIT binary patch literal 22016 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 literal 0 HcmV?d00001 diff --git a/src/UI/AlarmAlertActivity.txt b/src/UI/AlarmAlertActivity.txt new file mode 100644 index 0000000..e3327bd --- /dev/null +++ b/src/UI/AlarmAlertActivity.txt @@ -0,0 +1,192 @@ +package net.micode.notes.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.DialogInterface.OnDismissListener; +import android.content.Intent; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.PowerManager; +import android.provider.Settings; +import android.view.Window; +import android.view.WindowManager; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.DataUtils; + +import java.io.IOException; + +public class AlarmAlertActivity extends Activity implements OnClickListener, OnDismissListener { + private long mNoteId; //文本在数据库存储中的ID号 + private String mSnippet; //闹钟提示时出现的文本片段 + private static final int SNIPPET_PREW_MAX_LEN = 60; + MediaPlayer mPlayer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + //Bundle类型的数据与Map类型的数据相似,都是以key-value的形式存储数据的 + //onsaveInstanceState方法是用来保存Activity的状态的 + //能从onCreate的参数savedInsanceState中获得状态数据 + requestWindowFeature(Window.FEATURE_NO_TITLE); + //界面显示——无标题 + + final Window win = getWindow(); + win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + + if (!isScreenOn()) { + win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + //保持窗体点亮 + | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + //将窗体点亮 + | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON + //允许窗体点亮时锁屏 + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); + }//在手机锁屏后如果到了闹钟提示时间,点亮屏幕 + + Intent intent = getIntent(); + + try { + mNoteId = Long.valueOf(intent.getData().getPathSegments().get(1)); + mSnippet = DataUtils.getSnippetById(this.getContentResolver(), mNoteId); + //根据ID从数据库中获取标签的内容; + //getContentResolver()是实现数据共享,实例存储。 + mSnippet = mSnippet.length() > SNIPPET_PREW_MAX_LEN ? mSnippet.substring(0, + SNIPPET_PREW_MAX_LEN) + getResources().getString(R.string.notelist_string_info) + : mSnippet; + //判断标签片段是否达到符合长度 + } catch (IllegalArgumentException e) { + e.printStackTrace(); + return; + } + /* + try + { + // 代码区 + } + catch(Exception e) + { + // 异常处理 + } + 代码区如果有错误,就会返回所写异常的处理。*/ + mPlayer = new MediaPlayer(); + if (DataUtils.visibleInNoteDatabase(getContentResolver(), mNoteId, Notes.TYPE_NOTE)) { + showActionDialog(); + //弹出对话框 + playAlarmSound(); + //闹钟提示音激发 + } else { + finish(); + //完成闹钟动作 + } + } + + private boolean isScreenOn() { + //判断屏幕是否锁屏,调用系统函数判断,最后返回值是布尔类型 + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + return pm.isScreenOn(); + } + + private void playAlarmSound() { + //闹钟提示音激发 + Uri url = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_ALARM); + //调用系统的铃声管理URI,得到闹钟提示音 + int silentModeStreams = Settings.System.getInt(getContentResolver(), + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + + if ((silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0) { + mPlayer.setAudioStreamType(silentModeStreams); + } else { + mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM); + } + try { + mPlayer.setDataSource(this, url); + //方法:setDataSource(Context context, Uri uri) + //解释:无返回值,设置多媒体数据来源【根据 Uri】 + mPlayer.prepare(); + //准备同步 + mPlayer.setLooping(true); + //设置是否循环播放 + mPlayer.start(); + //开始播放 + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + //e.printStackTrace()函数功能是抛出异常, 还将显示出更深的调用信息 + //System.out.println(e),这个方法打印出异常,并且输出在哪里出现的异常 + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalStateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private void showActionDialog() { + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + //AlertDialog的构造方法全部是Protected的 + //所以不能直接通过new一个AlertDialog来创建出一个AlertDialog。 + //要创建一个AlertDialog,就要用到AlertDialog.Builder中的create()方法 + //如这里的dialog就是新建了一个AlertDialog + dialog.setTitle(R.string.app_name); + //为对话框设置标题 + dialog.setMessage(mSnippet); + //为对话框设置内容 + dialog.setPositiveButton(R.string.notealert_ok, this); + //给对话框添加"Yes"按钮 + if (isScreenOn()) { + dialog.setNegativeButton(R.string.notealert_enter, this); + }//对话框添加"No"按钮 + dialog.show().setOnDismissListener(this); + } + + public void onClick(DialogInterface dialog, int which) { + switch (which) { + //用which来选择click后下一步的操作 + case DialogInterface.BUTTON_NEGATIVE: + //这是取消操作 + Intent intent = new Intent(this, NoteEditActivity.class); + //实现两个类间的数据传输 + intent.setAction(Intent.ACTION_VIEW); + //设置动作属性 + intent.putExtra(Intent.EXTRA_UID, mNoteId); + //实现key-value对 + //EXTRA_UID为key;mNoteId为键 + startActivity(intent); + //开始动作 + break; + default: + //这是确定操作 + break; + } + } + + public void onDismiss(DialogInterface dialog) { + //忽略 + stopAlarmSound(); + //停止闹钟声音 + finish(); + //完成该动作 + } + + private void stopAlarmSound() { + if (mPlayer != null) { + mPlayer.stop(); + //停止播放 + mPlayer.release(); + //释放MediaPlayer对象 + mPlayer = null; + } + } +} \ No newline at end of file diff --git a/src/UI/AlarmAlertActivity精读.doc b/src/UI/AlarmAlertActivity精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..f18a1bbea08edd72ff035dceffc8a83fe2c720cd GIT binary patch literal 18944 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 AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE, + new String[] { String.valueOf(currentDate) }, + //将long变量currentDate转化为字符串 + null); + //Cursor在这里的作用是通过查找数据库中的标签内容,找到和当前系统时间相等的标签 + + if (c != null) { + if (c.moveToFirst()) { + do { + long alertDate = c.getLong(COLUMN_ALERTED_DATE); + Intent sender = new Intent(context, AlarmReceiver.class); + sender.setData(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(COLUMN_ID))); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, sender, 0); + AlarmManager alermManager = (AlarmManager) context + .getSystemService(Context.ALARM_SERVICE); + alermManager.set(AlarmManager.RTC_WAKEUP, alertDate, pendingIntent); + } while (c.moveToNext()); + } + c.close(); + } + //然而通过网上查找资料发现,对于闹钟机制的启动,通常需要上面的几个步骤 + //如新建Intent、PendingIntent以及AlarmManager等 + //这里就是根据数据库里的闹钟时间创建一个闹钟机制 + } +} \ No newline at end of file diff --git a/src/UI/AlarmInitReceiver精读.doc b/src/UI/AlarmInitReceiver精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..c215b8061951628020cf9849718e943ad0fb8acb GIT binary patch literal 19456 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 R)m+2J$)dtt;V)hS{|9DI#asXY literal 0 HcmV?d00001 diff --git a/src/UI/AlarmReceiver.txt b/src/UI/AlarmReceiver.txt new file mode 100644 index 0000000..f35ed7b --- /dev/null +++ b/src/UI/AlarmReceiver.txt @@ -0,0 +1,20 @@ +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); + //启动AlarmAlertActivity + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + //activity要存在于activity的栈中,而非activity的途径启动activity时必然不存在一个activity的栈 + //所以要新起一个栈装入启动的activity + context.startActivity(intent); + } +} +//这是实现alarm这个功能最接近用户层的包,基于上面的两个包, +//作用还需要深究但是对于setClass和addFlags的 + \ No newline at end of file diff --git a/src/UI/AlarmReceiver精读.doc b/src/UI/AlarmReceiver精读.doc new file mode 100644 index 0000000000000000000000000000000000000000..560f62d2025b600fbd9664f75671eee053c9e733 GIT binary patch literal 14848 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

N`IG<^2(8-gp5t>|X=T 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 literal 0 HcmV?d00001 diff --git a/src/contact.txt b/src/contact.txt new file mode 100644 index 0000000..af9e28b --- /dev/null +++ b/src/contact.txt @@ -0,0 +1,69 @@ +package net.micode.notes.data; + +import android.content.Context; + +import android.database.Cursor; +import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Data; +import android.telephony.PhoneNumberUtils; +import android.util.Log; + +import java.util.HashMap; +//change +public class Contact { //联系人 + private static HashMap sContactCache; + private static final String TAG = "Contact"; + + // 定义字符串CALLER_ID_SELECTION + private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + ++ Phone.NUMBER + + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + + " AND " + Data.RAW_CONTACT_ID + " IN " + + "(SELECT raw_contact_id " + + " FROM phone_lookup" + + " WHERE min_match = '+')"; + + // 获取联系人 + public static String getContact(Context context, String phoneNumber) { + if(sContactCache == null) { + sContactCache = new HashMap(); + } + + // 查找HashMap中是否已有phoneNumber信息 + if(sContactCache.containsKey(phoneNumber)) { + return sContactCache.get(phoneNumber); + } + + String selection = CALLER_ID_SELECTION.replace("+", + PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); + // 查找数据库中phoneNumber的信息 + Cursor cursor = context.getContentResolver().query( + Data.CONTENT_URI, + new String [] { Phone.DISPLAY_NAME }, + selection, + new String[] { phoneNumber }, + null); + + // 判定查询结果 + // moveToFirst()返回第一条 + if (cursor != null && cursor.moveToFirst()) { + try { + // 找到相关信息 + String name = cursor.getString(0); + sContactCache.put(phoneNumber, name); + return name; + // 异常 + } catch (IndexOutOfBoundsException e) { + Log.e(TAG, " Cursor get string error " + e.toString()); + return null; + } finally { + cursor.close(); + } + // 未找到相关信息 + } else { + Log.d(TAG, "No contact matched with number:" + phoneNumber); + return null; + } + } +} \ No newline at end of file diff --git a/src/notes.txt b/src/notes.txt new file mode 100644 index 0000000..6a486f9 --- /dev/null +++ b/src/notes.txt @@ -0,0 +1,303 @@ +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"; + 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; + + /** + * Following IDs are system folders' identifiers + * {@link Notes#ID_ROOT_FOLDER } is default folder + * {@link Notes#ID_TEMPARAY_FOLDER } is for notes belonging no folder + * {@link Notes#ID_CALL_RECORD_FOLDER} is to store call records + */ + 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; + } + + /** + * Uri to query all notes and folders + */ + 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");//定义查找数据的指针。 + + // 定义NoteColumns的常量,用于后面创建数据库的表头 + public interface NoteColumns { + /** + * The unique ID for a row + *

Type: INTEGER (long)

+ */ + public static final String ID = "_id"; + + /** + * The parent's id for note or folder + *

Type: INTEGER (long)

+ */ + public static final String PARENT_ID = "parent_id";//为什么会有parent_id + + /** + * Created data for note or folder + *

Type: INTEGER (long)

+ */ + public static final String CREATED_DATE = "created_date"; + + /** + * Latest modified date + *

Type: INTEGER (long)

+ */ + public static final String MODIFIED_DATE = "modified_date"; + + + /** + * Alert date + *

Type: INTEGER (long)

+ */ + public static final String ALERTED_DATE = "alert_date"; + + /** + * Folder's name or text content of note + *

Type: TEXT

+ */ + public static final String SNIPPET = "snippet"; + + /** + * Note's widget id + *

Type: INTEGER (long)

+ */ + public static final String WIDGET_ID = "widget_id"; + + /** + * Note's widget type + *

Type: INTEGER (long)

+ */ + public static final String WIDGET_TYPE = "widget_type"; + + /** + * Note's background color's id + *

Type: INTEGER (long)

+ */ + public static final String BG_COLOR_ID = "bg_color_id"; + + /** + * For text note, it doesn't has attachment, for multi-media + * note, it has at least one attachment + *

Type: INTEGER

+ */ + public static final String HAS_ATTACHMENT = "has_attachment"; + + /** + * Folder's count of notes + *

Type: INTEGER (long)

+ */ + public static final String NOTES_COUNT = "notes_count"; + + /** + * The file type: folder or note + *

Type: INTEGER

+ */ + public static final String TYPE = "type"; + + /** + * The last sync id + *

Type: INTEGER (long)

+ */ + public static final String SYNC_ID = "sync_id";//同步 + + /** + * Sign to indicate local modified or not + *

Type: INTEGER

+ */ + public static final String LOCAL_MODIFIED = "local_modified"; + + /** + * Original parent id before moving into temporary folder + *

Type : INTEGER

+ */ + public static final String ORIGIN_PARENT_ID = "origin_parent_id"; + + /** + * The gtask id + *

Type : TEXT

+ */ + public static final String GTASK_ID = "gtask_id"; + + /** + * The version code + *

Type : INTEGER (long)

+ */ + public static final String VERSION = "version"; + }//这些常量主要是定义便签的属性的。 + + // 定义DataColumns的常量,用于后面创建数据库的表头 + public interface DataColumns { + /** + * The unique ID for a row + *

Type: INTEGER (long)

+ */ + public static final String ID = "_id"; + + /** + * The MIME type of the item represented by this row. + *

Type: Text

+ */ + public static final String MIME_TYPE = "mime_type"; + + /** + * The reference id to note that this data belongs to + *

Type: INTEGER (long)

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

Type: INTEGER (long)

+ */ + public static final String CREATED_DATE = "created_date"; + + /** + * Latest modified date + *

Type: INTEGER (long)

+ */ + public static final String MODIFIED_DATE = "modified_date"; + + /** + * Data's content + *

Type: TEXT

+ */ + public static final String CONTENT = "content"; + + + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific, +used for + * integer data type + *

Type: INTEGER

+ */ + public static final String DATA1 = "data1"; + + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific, +used for + * integer data type + *

Type: INTEGER

+ */ + public static final String DATA2 = "data2"; + + /** + * 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 + * TEXT data type + *

Type: TEXT

+ */ + public static final String DATA4 = "data4"; + + /** + * 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 int MODE_CHECK_LIST = 1; + + public static final String CONTENT_TYPE = + +"vnd.android.cursor.dir/text_note"; + + public static final String CONTENT_ITEM_TYPE = + +"vnd.android.cursor.item/text_note"; + + public static final Uri CONTENT_URI = Uri.parse("content://" + + +AUTHORITY + "/text_note"); + }//文本内容的数据结构 + + public static final class CallNote implements DataColumns { + /** + * Call date for this record + *

Type: INTEGER (long)

+ */ + public static final String CALL_DATE = DATA1; + + /** + * Phone number for this record + *

Type: TEXT

+ */ + public static final String PHONE_NUMBER = DATA3; + + public static final String CONTENT_TYPE = + +"vnd.android.cursor.dir/call_note"; + + public static final String CONTENT_ITEM_TYPE = + +"vnd.android.cursor.item/call_note"; + + public static final Uri CONTENT_URI = Uri.parse("content://" + + +AUTHORITY + "/call_note"); + }//电话内容的数据结构 +} \ No newline at end of file diff --git a/src/充实文本编辑功能.txt b/src/充实文本编辑功能.txt new file mode 100644 index 0000000..8b8a521 --- /dev/null +++ b/src/充实文本编辑功能.txt @@ -0,0 +1,142 @@ +在编辑主界面note_edit.xml中添加布局,添加各种装饰文本的按钮 + + + + +