diff --git a/tool/BackupUtils.java b/tool/BackupUtils.java new file mode 100644 index 0000000..e8fd59f --- /dev/null +++ b/tool/BackupUtils.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * 根据Apache License, Version 2.0(以下简称“许可证”)授权; + * 您可能不会使用此文件,除非遵守许可证。 + * 您可以在以下网址获得许可证的副本: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 除非适用法律要求或书面同意,否则按照许可证分发的软件 + * 按“原样”分发,不附带任何明示或暗示的保证或条件。 + * 请参阅控制权限和许可证下的限制的具体语言的许可证。 + */ + +package net.micode.notes.tool; + +import android.content.Context; +import android.database.Cursor; +import android.os.Environment; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.util.Log; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.DataColumns; +import net.micode.notes.data.Notes.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; + + +// BackupUtils 类提供备份和恢复便签数据的功能。 +public class BackupUtils { + private static final String TAG = "BackupUtils"; + // 单例模式 + private static BackupUtils sInstance; + + // 获取 BackupUtils 单例对象 + public static synchronized BackupUtils getInstance(Context context) { + if (sInstance == null) { + sInstance = new BackupUtils(context); + } + return sInstance; + } + + /** + * 以下状态用于表示备份或恢复的状态 + */ + // 当前 sdcard 没有挂载 + public static final int STATE_SD_CARD_UNMOUONTED = 0; + // 备份文件不存在 + public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; + // 数据格式不正确,可能被其他程序修改 + public static final int STATE_DATA_DESTROIED = 2; + // 一些运行时异常导致恢复或备份失败 + public static final int STATE_SYSTEM_ERROR = 3; + // 备份或恢复成功 + public static final int STATE_SUCCESS = 4; + + private TextExport mTextExport; + + // BackupUtils 构造函数 + 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; + } + + // TextExport 内部类,处理文本导出 + private static class TextExport { + // 省略部分代码... + + // TextExport 构造函数 + 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]; + } + + // 导出文件夹到文本 + private void exportFolderToText(String folderId, PrintStream ps) { + // 查询属于此文件夹的便签 + 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 { + // 打印便签的最后修改日期 + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); + // 查询属于此便签的数据 + String noteId = notesCursor.getString(NOTE_COLUMN_ID); + exportNoteToText(noteId, ps); + } while (notesCursor.moveToNext()); + } + notesCursor.close(); + } + } + + // 导出便签到打印流 + 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) { + if (dataCursor.moveToFirst()) { + do { + String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); + if (DataConstants.CALL_NOTE.equals(mimeType)) { + // 打印电话号码 + 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)); + } + // 打印通话日期 + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat + .format(mContext.getString(R.string.format_datetime_mdhm), + callDate))); + // 打印通话附件位置 + 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(); + } + // 在便签之间打印分隔线 + try { + ps.write(new byte[] { + Character.LINE_SEPARATOR, Character.LETTER_NUMBER + }); + } catch (IOException e) { + Log.e(TAG, e.toString()); + } + } + + // 导出文本,用户可读 + public int exportToText() { + 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; + } + // 首先导出文件夹及其便签 + 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 { + // 打印文件夹名称 + 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(); + } + + // 导出根文件夹中的便签 + 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)))); + // 查询属于此便签的数据 + String noteId = noteCursor.getString(NOTE_COLUMN_ID); + exportNoteToText(noteId, ps); + } while (noteCursor.moveToNext()); + } + noteCursor.close(); + } + ps.close(); + + return STATE_SUCCESS; + } + + // 获取指向导出文本文件的打印流 + 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); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } catch (NullPointerException e) { + e.printStackTrace();} + + return null; + } +} + + + \ No newline at end of file diff --git a/tool/GTaskStringUtils.java b/tool/GTaskStringUtils.java new file mode 100644 index 0000000..807e47d --- /dev/null +++ b/tool/GTaskStringUtils.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.micode.notes.tool; // 包声明,表示该类位于 net.micode.notes.tool 包中 + +// 定义 GTaskStringUtils 类,用于管理 Google Tasks 或类似任务相关的常量字符串 +public class GTaskStringUtils { + + // 这些常量字符串用于表示任务数据的各个字段名 + + // Action ID + public final static String GTASK_JSON_ACTION_ID = "action_id"; // "action_id" 用于表示任务的操作标识符 + + // 操作列表 + public final static String GTASK_JSON_ACTION_LIST = "action_list"; // "action_list" 用于表示操作列表 + + // 操作类型 + public final static String GTASK_JSON_ACTION_TYPE = "action_type"; // "action_type" 用于表示操作的类型 + + // 创建操作类型 + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; // "create" 表示创建操作 + + // 获取所有操作类型 + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; // "get_all" 表示获取所有操作 + + // 移动操作类型 + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; // "move" 表示移动操作 + + // 更新操作类型 + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; // "update" 表示更新操作 + + // 创建者ID + public final static String GTASK_JSON_CREATOR_ID = "creator_id"; // "creator_id" 表示任务创建者的ID + + // 子实体 + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; // "child_entity" 用于表示子实体 + + // 客户端版本 + public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; // "client_version" 表示客户端的版本 + + // 任务是否完成 + public final static String GTASK_JSON_COMPLETED = "completed"; // "completed" 表示任务是否完成 + + // 当前列表ID + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; // "current_list_id" 表示当前任务列表的ID + + // 默认列表ID + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; // "default_list_id" 表示默认任务列表的ID + + // 是否删除 + public final static String GTASK_JSON_DELETED = "deleted"; // "deleted" 表示任务是否被删除 + + // 目标列表 + public final static String GTASK_JSON_DEST_LIST = "dest_list"; // "dest_list" 表示目标任务列表 + + // 目标父级任务 + public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; // "dest_parent" 表示目标任务的父级任务 + + // 目标父级类型 + public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; // "dest_parent_type" 表示目标父级任务的类型 + + // 实体增量 + public final static String GTASK_JSON_ENTITY_DELTA = "entity"; // "entity" 表示实体数据的增量部分 + + // 实体类型 + public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; // "entity_type" 用于表示实体类型(任务、列表等) + + // 获取已删除任务 + public final static String GTASK_JSON_GET_DELETED = "get_deleted"; // "get_deleted" 表示获取已删除的任务 + + // 任务ID + public final static String GTASK_JSON_ID = "id"; // "id" 用于表示任务的唯一标识符 + + // 任务索引 + public final static String GTASK_JSON_INDEX = "index"; // "index" 用于表示任务的索引位置 + + // 最后修改时间 + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; // "last_modified" 用于表示任务的最后修改时间 + + // 最新同步点 + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; // "latest_sync_point" 表示任务的最新同步点 + + // 列表ID + public final static String GTASK_JSON_LIST_ID = "list_id"; // "list_id" 用于表示任务列表的ID + + // 列表字段 + public final static String GTASK_JSON_LISTS = "lists"; // "lists" 用于表示多个任务列表 + + // 任务名称 + public final static String GTASK_JSON_NAME = "name"; // "name" 表示任务或任务列表的名称 + + // 新的ID + public final static String GTASK_JSON_NEW_ID = "new_id"; // "new_id" 用于表示任务的新ID + + // 任务备注 + public final static String GTASK_JSON_NOTES = "notes"; // "notes" 表示任务的备注信息 + + // 父任务ID + public final static String GTASK_JSON_PARENT_ID = "parent_id"; // "parent_id" 表示父任务的ID + + // 之前的兄弟任务ID + public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; // "prior_sibling_id" 用于表示之前的兄弟任务ID + + // 任务结果 + public final static String GTASK_JSON_RESULTS = "results"; // "results" 用于表示任务操作的结果 + + // 源列表 + public final static String GTASK_JSON_SOURCE_LIST = "source_list"; // "source_list" 用于表示源任务列表 + + // 任务列表 + public final static String GTASK_JSON_TASKS = "tasks"; // "tasks" 用于表示任务数据 + + // 任务类型 + public final static String GTASK_JSON_TYPE = "type"; // "type" 表示任务的类型 + + // 任务组类型 + public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; // "GROUP" 表示任务组类型 + + // 任务类型 + public final static String GTASK_JSON_TYPE_TASK = "TASK"; // "TASK" 表示单一任务类型 + + // 用户字段 + public final static String GTASK_JSON_USER = "user"; // "user" 用于表示任务所属用户的信息 + + // MIUI 文件夹前缀 + public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; // "[MIUI_Notes]" 用于表示 MIUI 系统中的笔记文件夹前缀 + + // 默认文件夹 + public final static String FOLDER_DEFAULT = "Default"; // "Default" 表示默认的文件夹名称 + + // 通话记录笔记文件夹 + public final static String FOLDER_CALL_NOTE = "Call_Note"; // "Call_Note" 用于表示通话记录的笔记文件夹 + + // 元数据文件夹 + public final static String FOLDER_META = "METADATA"; // "METADATA" 用于表示存储元数据的文件夹 + + // 元数据头部: GTASK ID + public final static String META_HEAD_GTASK_ID = "meta_gid"; // "meta_gid" 用于表示任务的 Google Task ID 的元数据字段 + + // 元数据头部: 笔记 + public final static String META_HEAD_NOTE = "meta_note"; // "meta_note" 用于表示与任务相关的元数据笔记字段 + + // 元数据头部: 数据 + public final static String META_HEAD_DATA = "meta_data"; // "meta_data" 用于表示与任务相关的其他元数据字段 + + // 元数据笔记名称 + public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE"; // "[META INFO] DON'T UPDATE AND DELETE" 是一条标记元数据的警告信息,表示不要更新或删除该元数据 +} diff --git a/tool/ResourceParser.java b/tool/ResourceParser.java new file mode 100644 index 0000000..64293eb --- /dev/null +++ b/tool/ResourceParser.java @@ -0,0 +1,208 @@ +/* + * 版权所有 (c) 2010-2011, MiCode 开源社区 (www.micode.net) + * + * 本文件根据 Apache License, Version 2.0 (以下简称“许可证”)授权使用; + * 除非符合许可证的规定,否则您不得使用此文件。 + * 您可以在以下网址获取许可证的副本: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 除非适用法律要求或以书面形式同意,根据许可证分发的软件将按“现状”分发, + * 不提供任何明示或暗示的保证或条件。 + * 请参阅许可证以了解控制权限和许可证下限制的特定语言。 + */ + +package net.micode.notes.tool; + +import android.content.Context; // 引入Android上下文类,用于访问应用的资源和类以及调用应用级操作 +import android.preference.PreferenceManager; // 引入Android偏好设置管理器类,用于访问应用的偏好设置 + +import net.micode.notes.R; // 引入应用的资源类,用于访问应用资源 +import net.micode.notes.ui.NotesPreferenceActivity; // 引入应用的偏好设置活动类 + +// ResourceParser类,用于解析和管理应用的资源 +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; + + // NoteBgResources内部类,用于管理笔记背景资源 + 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 + }; + + // 获取指定ID的编辑背景资源 + public static int getNoteBgResource(int id) { + return BG_EDIT_RESOURCES[id]; + } + + // 获取指定ID的编辑标题背景资源 + public static int getNoteTitleBgResource(int id) { + return BG_EDIT_TITLE_RESOURCES[id]; + } + } + + // 获取默认背景颜色ID + public static int getDefaultBgId(Context context) { + // 检查用户是否设置了背景颜色偏好 + if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( + NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { + // 如果设置了,则随机返回一个背景颜色ID + return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length); + } else { + // 否则返回默认背景颜色ID + return BG_DEFAULT_COLOR; + } + } + + // NoteItemBgResources内部类,用于管理笔记条目背景资源 + 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 + }; + + // 获取指定ID的第一项背景资源 + public static int getNoteBgFirstRes(int id) { + return BG_FIRST_RESOURCES[id]; + } + + // 获取指定ID的最后一项背景资源 + public static int getNoteBgLastRes(int id) { + return BG_LAST_RESOURCES[id]; + } + + // 获取指定ID的单个项背景资源 + public static int getNoteBgSingleRes(int id) { + return BG_SINGLE_RESOURCES[id]; + } + + // 获取指定ID的中间项背景资源 + public static int getNoteBgNormalRes(int id) { + return BG_NORMAL_RESOURCES[id]; + } + + // 获取文件夹背景资源 + public static int getFolderBgRes() { + return R.drawable.list_folder; + } + } + + // WidgetBgResources内部类,用于管理小部件背景资源 + public static class WidgetBgResources { + // 定义2x大小的小部件背景资源数组 + 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, + }; + + // 获取指定ID的2x大小小部件背景资源 + public static int getWidget2xBgResource(int id) { + return BG_2X_RESOURCES[id]; + } + + // 定义4x大小的小部件背景资源数组 + 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 + }; + + // 获取指定ID的4x大小小部件背景资源 + public static int getWidget4xBgResource(int id) { + return BG_4X_RESOURCES[id]; + } + } + + // TextAppearanceResources内部类,用于管理文本外观资源 + 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的文本外观资源 + // 注意:这里有一个修正(HACKME),用于处理存储在偏好设置中的资源ID可能超出资源数组长度的情况 + public static int getTexAppearanceResource(int id) { + 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