parent
14a1d54e47
commit
f85591f659
@ -0,0 +1,324 @@
|
||||
package net.micode.notes.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.***;
|
||||
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;
|
||||
|
||||
public class BackupUtils {
|
||||
private static final String TAG = "BackupUtils"; // 日志标签
|
||||
// Singleton instance
|
||||
private static BackupUtils sInstance;
|
||||
|
||||
// 获取 BackupUtils 的单例实例
|
||||
public static synchronized BackupUtils getInstance(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new BackupUtils(context); // 创建实例
|
||||
}
|
||||
return sInstance; // 返回实例
|
||||
}
|
||||
|
||||
/**
|
||||
* 备份或恢复状态的常量
|
||||
*/
|
||||
public static final int STATE_SD_CARD_UNMOUONTED = 0; // SD卡未挂载
|
||||
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; // 文本导出工具
|
||||
|
||||
// 构造函数
|
||||
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; // 笔记ID列索引
|
||||
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; // MIME类型列索引
|
||||
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];
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出指定文件夹的内容到文本
|
||||
*/
|
||||
private void exportFolderToText(String folderId, PrintStream ps) {
|
||||
// 查询属于该文件夹的笔记
|
||||
*** 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(); // 关闭游标
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出指定ID的笔记到打印流
|
||||
*/
|
||||
private void exportNoteToText(String noteId, PrintStream ps) {
|
||||
// 查询属于该笔记的数据
|
||||
*** 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); // 获取MIME类型
|
||||
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; // 返回SD卡未挂载状态
|
||||
}
|
||||
|
||||
PrintStream ps = getExportToTextPrintStream(); // 获取打印流
|
||||
if (ps == null) {
|
||||
Log.e(TAG, "get print stream error");
|
||||
return STATE_SYSTEM_ERROR; // 返回系统错误状态
|
||||
}
|
||||
// 首先导出文件夹及其笔记
|
||||
*** 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(); // 关闭游标
|
||||
}
|
||||
|
||||
// 导出根文件夹中的笔记
|
||||
*** 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; // 返回空
|
||||
}
|
||||
return ps; // 返回打印流
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成用于存储导入数据的文本文件
|
||||
*/
|
||||
private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(Environment.getExternalStorageDirectory()); // 获取外部存储目录
|
||||
sb.append(context.getString(filePathResId)); // 添加文件路径
|
||||
File filedir = new File(sb.toString()); // 创建文件夹对象
|
||||
sb.append(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(); // 打印IO异常
|
||||
}
|
||||
|
||||
return null; // 返回空
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package net.micode.notes.tool;
|
||||
|
||||
public class GTaskStringUtils {
|
||||
|
||||
// JSON字段常量定义
|
||||
public final static String GTASK_JSON_ACTION_ID = "action_id"; // 动作ID
|
||||
public final static String GTASK_JSON_ACTION_LIST = "action_list"; // 动作列表
|
||||
public final static String GTASK_JSON_ACTION_TYPE = "action_type"; // 动作类型
|
||||
public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; // 创建动作
|
||||
public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; // 获取所有动作
|
||||
public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; // 移动动作
|
||||
public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; // 更新动作
|
||||
public final static String GTASK_JSON_CREATOR_ID = "creator_id"; // 创建者ID
|
||||
public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; // 子实体
|
||||
public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; // 客户端版本
|
||||
public final static String GTASK_JSON_COMPLETED = "completed"; // 是否完成
|
||||
public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; // 当前列表ID
|
||||
public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; // 默认列表ID
|
||||
public final static String GTASK_JSON_DELETED = "deleted"; // 是否已删除
|
||||
public final static String GTASK_JSON_DEST_LIST = "dest_list"; // 目标列表
|
||||
public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; // 目标父级
|
||||
public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; // 目标父级类型
|
||||
public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; // 实体增量
|
||||
public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; // 实体类型
|
||||
public final static String GTASK_JSON_GET_DELETED = "get_deleted"; // 获取已删除项
|
||||
public final static String GTASK_JSON_ID = "id"; // ID
|
||||
public final static String GTASK_JSON_INDEX = "index"; // 索引
|
||||
public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; // 最后修改时间
|
||||
public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; // 最新同步点
|
||||
public final static String GTASK_JSON_LIST_ID = "list_id"; // 列表ID
|
||||
public final static String GTASK_JSON_LISTS = "lists"; // 列表集合
|
||||
public final static String GTASK_JSON_NAME = "name"; // 名称
|
||||
public final static String GTASK_JSON_NEW_ID = "new_id"; // 新ID
|
||||
public final static String GTASK_JSON_NOTES = "notes"; // 笔记
|
||||
public final static String GTASK_JSON_PARENT_ID = "parent_id"; // 父级ID
|
||||
public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; // 前一个兄弟ID
|
||||
public final static String GTASK_JSON_RESULTS = "results"; // 结果
|
||||
public final static String GTASK_JSON_SOURCE_LIST = "source_list"; // 源列表
|
||||
public final static String GTASK_JSON_TASKS = "tasks"; // 任务集合
|
||||
public final static String GTASK_JSON_TYPE = "type"; // 类型
|
||||
public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; // 组类型
|
||||
public final static String GTASK_JSON_TYPE_TASK = "TASK"; // 任务类型
|
||||
public final static String GTASK_JSON_USER = "user"; // 用户
|
||||
|
||||
// 文件夹相关常量
|
||||
public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; // MIUI笔记文件夹前缀
|
||||
public final static String FOLDER_DEFAULT = "Default"; // 默认文件夹
|
||||
public final static String FOLDER_CALL_NOTE = "Call_Note"; // 通话笔记文件夹
|
||||
public final static String FOLDER_META = "METADATA"; // 元数据文件夹
|
||||
|
||||
// 元数据相关常量
|
||||
public final static String META_HEAD_GTASK_ID = "meta_gid"; // 元数据头 - GTASK ID
|
||||
public final static String META_HEAD_NOTE = "meta_note"; // 元数据头 - 笔记
|
||||
public final static String META_HEAD_DATA = "meta_data"; // 元数据头 - 数据
|
||||
public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE"; // 元笔记名称
|
||||
}
|
||||
@ -0,0 +1,182 @@
|
||||
package net.micode.notes.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import net.micode.notes.R;
|
||||
import net.micode.notes.ui.NotesPreferenceActivity;
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
// 获取默认背景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 {
|
||||
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,
|
||||
};
|
||||
|
||||
// 获取2x小部件背景资源
|
||||
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
|
||||
};
|
||||
|
||||
// 获取4x小部件背景资源
|
||||
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
|
||||
};
|
||||
|
||||
// 获取文本外观资源
|
||||
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]; // 返回指定ID的资源
|
||||
}
|
||||
|
||||
// 获取资源数量
|
||||
public static int getResourcesSize() {
|
||||
return TEXTAPPEARANCE_RESOURCES.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,271 @@
|
||||
package net.micode.notes.model;
|
||||
|
||||
import android.content.ContentProviderOperation;
|
||||
import android.content.ContentProviderResult;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.OperationApplicationException;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import net.micode.notes.data.Notes;
|
||||
import net.micode.notes.data.Notes.CallNote;
|
||||
import net.micode.notes.data.Notes.DataColumns;
|
||||
import net.micode.notes.data.Notes.NoteColumns;
|
||||
import net.micode.notes.data.Notes.TextNote;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Note {
|
||||
private ContentValues mNoteDiffValues; // 存储笔记的修改值
|
||||
private NoteData mNoteData; // 存储笔记的文本和通话数据
|
||||
private static final String TAG = "Note"; // 日志标签
|
||||
|
||||
/**
|
||||
* 为新笔记创建一个新的 ID
|
||||
* @param context 上下文
|
||||
* @param folderId 文件夹 ID
|
||||
* @return 新笔记的 ID
|
||||
*/
|
||||
public static synchronized long getNewNoteId(Context context, long folderId) {
|
||||
// 创建一个新的笔记并插入到数据库中
|
||||
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); // 设置父文件夹 ID
|
||||
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values); // 插入笔记
|
||||
|
||||
long noteId = 0; // 初始化笔记 ID
|
||||
try {
|
||||
noteId = Long.valueOf(uri.getPathSegments().get(1)); // 从 URI 中获取笔记 ID
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Get note id error :" + e.toString()); // 记录错误
|
||||
noteId = 0; // 设置为 0 表示错误
|
||||
}
|
||||
if (noteId == -1) {
|
||||
throw new IllegalStateException("Wrong note id:" + noteId); // 抛出异常
|
||||
}
|
||||
return noteId; // 返回新笔记 ID
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
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); // 将文本数据设置到 NoteData 中
|
||||
}
|
||||
|
||||
// 设置文本数据 ID
|
||||
public void setTextDataId(long id) {
|
||||
mNoteData.setTextDataId(id); // 设置文本数据 ID
|
||||
}
|
||||
|
||||
// 获取文本数据 ID
|
||||
public long getTextDataId() {
|
||||
return mNoteData.mTextDataId; // 返回文本数据 ID
|
||||
}
|
||||
|
||||
// 设置通话数据 ID
|
||||
public void setCallDataId(long id) {
|
||||
mNoteData.setCallDataId(id); // 设置通话数据 ID
|
||||
}
|
||||
|
||||
// 设置通话数据
|
||||
public void setCallData(String key, String value) {
|
||||
mNoteData.setCallData(key, value); // 将通话数据设置到 NoteData 中
|
||||
}
|
||||
|
||||
// 检查笔记是否被本地修改
|
||||
public boolean isLocalModified() {
|
||||
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); // 如果有修改则返回 true
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步笔记到内容提供者
|
||||
* @param context 上下文
|
||||
* @param noteId 笔记 ID
|
||||
* @return 同步是否成功
|
||||
*/
|
||||
public boolean syncNote(Context context, long noteId) {
|
||||
if (noteId <= 0) {
|
||||
throw new IllegalArgumentException("Wrong note id:" + noteId); // 检查笔记 ID
|
||||
}
|
||||
|
||||
if (!isLocalModified()) {
|
||||
return true; // 如果没有本地修改,直接返回成功
|
||||
}
|
||||
|
||||
// 更新笔记的本地修改和修改日期
|
||||
if (context.getContentResolver().update(
|
||||
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
|
||||
null) == 0) {
|
||||
Log.e(TAG, "Update note error, should not happen"); // 记录更新错误
|
||||
// 不返回,继续执行
|
||||
}
|
||||
mNoteDiffValues.clear(); // 清空修改值
|
||||
|
||||
// 如果有本地修改的笔记数据,推送到内容提供者
|
||||
if (mNoteData.isLocalModified()
|
||||
&& (mNoteData.pushIntoContentResolver(context, noteId) == null)) {
|
||||
return false; // 如果推送失败,返回 false
|
||||
}
|
||||
|
||||
return true; // 返回成功
|
||||
}
|
||||
|
||||
// 内部类,用于管理笔记的文本和通话数据
|
||||
private class NoteData {
|
||||
private long mTextDataId; // 文本数据 ID
|
||||
private ContentValues mTextDataValues; // 存储文本数据的修改值
|
||||
private long mCallDataId; // 通话数据 ID
|
||||
private ContentValues mCallDataValues; // 存储通话数据的修改值
|
||||
private static final String TAG = "NoteData"; // 日志标签
|
||||
|
||||
// 构造函数
|
||||
public NoteData() {
|
||||
mTextDataValues = new ContentValues(); // 初始化文本数据值
|
||||
mCallDataValues = new ContentValues(); // 初始化通话数据值
|
||||
mTextDataId = 0; // 初始化文本数据 ID
|
||||
mCallDataId = 0; // 初始化通话数据 ID
|
||||
}
|
||||
|
||||
// 检查文本和通话数据是否被本地修改
|
||||
boolean isLocalModified() {
|
||||
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; // 如果有修改则返回 true
|
||||
}
|
||||
|
||||
// 设置文本数据 ID
|
||||
void setTextDataId(long id) {
|
||||
if(id <= 0) {
|
||||
throw new IllegalArgumentException("Text data id should larger than 0"); // 检查 ID
|
||||
}
|
||||
mTextDataId = id; // 设置文本数据 ID
|
||||
}
|
||||
|
||||
// 设置通话数据 ID
|
||||
void setCallDataId(long id) {
|
||||
if (id <= 0) {
|
||||
throw new IllegalArgumentException("Call data id should larger than 0"); // 检查 ID
|
||||
}
|
||||
mCallDataId = id; // 设置通话数据 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()); // 更新修改日期
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数据推送到内容提供者
|
||||
* @param context 上下文
|
||||
* @param noteId 笔记 ID
|
||||
* @return 推送结果的 URI
|
||||
*/
|
||||
Uri pushIntoContentResolver(Context context, long noteId) {
|
||||
// 检查安全性
|
||||
if (noteId <= 0) {
|
||||
throw new IllegalArgumentException("Wrong note id:" + noteId); // 检查笔记 ID
|
||||
}
|
||||
|
||||
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); // 操作列表
|
||||
ContentProviderOperation.Builder builder = null; // 操作构建器
|
||||
|
||||
// 如果有文本数据需要推送
|
||||
if(mTextDataValues.size() > 0) {
|
||||
mTextDataValues.put(DataColumns.NOTE_ID, noteId); // 设置笔记 ID
|
||||
if (mTextDataId == 0) {
|
||||
mTextDataValues.put(DataColumns.MIME_TYPE, TextNote.CONTENT_ITEM_TYPE); // 设置 MIME 类型
|
||||
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
|
||||
mTextDataValues); // 插入文本数据
|
||||
try {
|
||||
setTextDataId(Long.valueOf(uri.getPathSegments().get(1))); // 获取并设置文本数据 ID
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Insert new text data fail with noteId" + noteId); // 记录插入错误
|
||||
mTextDataValues.clear(); // 清空文本数据值
|
||||
return null; // 返回 null 表示失败
|
||||
}
|
||||
} else {
|
||||
// 更新已有的文本数据
|
||||
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
|
||||
Notes.CONTENT_DATA_URI, mTextDataId));
|
||||
builder.withValues(mTextDataValues); // 设置更新值
|
||||
operationList.add(builder.build()); // 添加到操作列表
|
||||
}
|
||||
mTextDataValues.clear(); // 清空文本数据值
|
||||
}
|
||||
|
||||
// 如果有通话数据需要推送
|
||||
if(mCallDataValues.size() > 0) {
|
||||
mCallDataValues.put(DataColumns.NOTE_ID, noteId); // 设置笔记 ID
|
||||
if (mCallDataId == 0) {
|
||||
mCallDataValues.put(DataColumns.MIME_TYPE, CallNote.CONTENT_ITEM_TYPE); // 设置 MIME 类型
|
||||
Uri uri = context.getContentResolver().insert(Notes.CONTENT_DATA_URI,
|
||||
mCallDataValues); // 插入通话数据
|
||||
try {
|
||||
setCallDataId(Long.valueOf(uri.getPathSegments().get(1))); // 获取并设置通话数据 ID
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Insert new call data fail with noteId" + noteId); // 记录插入错误
|
||||
mCallDataValues.clear(); // 清空通话数据值
|
||||
return null; // 返回 null 表示失败
|
||||
}
|
||||
} else {
|
||||
// 更新已有的通话数据
|
||||
builder = ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
|
||||
Notes.CONTENT_DATA_URI, mCallDataId));
|
||||
builder.withValues(mCallDataValues); // 设置更新值
|
||||
operationList.add(builder.build()); // 添加到操作列表
|
||||
}
|
||||
mCallDataValues.clear(); // 清空通话数据值
|
||||
}
|
||||
|
||||
// 如果有操作需要执行
|
||||
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); // 返回结果 URI
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); // 记录远程异常
|
||||
return null; // 返回 null 表示失败
|
||||
} catch (OperationApplicationException e) {
|
||||
Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); // 记录操作应用异常
|
||||
return null; // 返回 null 表示失败
|
||||
}
|
||||
}
|
||||
return null; // 返回 null 表示没有操作
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
总结:
|
||||
类 Note: 主要用于创建和管理笔记,包括设置笔记的值、同步笔记到内容提供者等功能。
|
||||
内部类 NoteData: 负责管理笔记的文本和通话数据,提供设置和推送数据到内容提供者的方法。
|
||||
异常处理: 代码中包含了多处异常处理,确保在操作失败时能够记录错误并返回适当的结果。
|
||||
内容提供者操作: 通过 ContentResolver 与内容提供者进行交互,插入和更新笔记数据。
|
||||
Loading…
Reference in new issue