ADD file via upload

main
pc7tynsj8 7 months ago
parent 6949e6f9dc
commit 60aed4dd89

@ -0,0 +1,516 @@
package net.micode.notes.tool; // 包名表示该类属于net.micode.notes应用的tool包
import android.content.Context; // 导入Context类用于获取应用上下文
import android.database.Cursor; // 导入Cursor类用于操作数据库查询结果
import android.os.Environment; // 导入Environment类用于访问外部存储状态
import android.text.TextUtils; // 导入TextUtils类用于文本操作
import android.text.format.DateFormat; // 导入DateFormat类用于日期格式化
import android.util.Log; // 导入Log类用于日志输出
import net.micode.notes.R; // 导入R类用于访问应用资源
import net.micode.notes.data.Notes; // 导入Notes类用于操作笔记数据
import net.micode.notes.data.Notes.DataColumns; // 导入DataColumns类用于访问笔记数据的列名
import net.micode.notes.data.Notes.DataConstants; // 导入DataConstants类用于访问笔记数据的常量
import net.micode.notes.data.Notes.NoteColumns; // 导入NoteColumns类用于访问笔记数据的列名
import java.io.File; // 导入File类用于文件操作
import java.io.FileNotFoundException; // 导入FileNotFoundException类用于处理文件未找到异常
import java.io.FileOutputStream; // 导入FileOutputStream类用于文件输出
import java.io.IOException; // 导入IOException类用于处理I/O异常
import java.io.PrintStream; // 导入PrintStream类用于输出流操作
/**
* BackupUtils类用于处理笔记应用的备份和恢复功能。
*/
public class BackupUtils {
private static final String TAG = "BackupUtils"; // 日志标签用于Log输出
// Singleton instance
private static BackupUtils sInstance;
// 获取BackupUtils的单例实例
public static synchronized BackupUtils getInstance(Context context) {
if (sInstance == null) {
sInstance = new BackupUtils(context); // 创建实例
}
return sInstance;
}
/**
* 以下状态表示备份或恢复的状态
*/
// 当前SD卡未挂载
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; // 文本导出工具
private BackupUtils(Context context) {
mTextExport = new TextExport(context); // 初始化文本导出工具
}
// 检查外部存储是否可写
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState(); // 获取外部存储状态
return Environment.MEDIA_MOUNTED.equals(state); // 判断是否可写
}
// 检查外部存储是否可读
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState(); // 获取外部存储状态
return Environment.MEDIA_MOUNTED.equals(state) || // 判断是否可读
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
}
// 备份笔记数据到SD卡
public int backupNotes() {
if (!isExternalStorageWritable()) { // 检查外部存储是否可写
Log.e(TAG, "External storage is not writable."); // 输出错误日志
return STATE_SD_CARD_UNMOUONTED; // 返回SD卡未挂载状态
}
File backupDir = new File(Environment.getExternalStorageDirectory(), "NotesBackup"); // 创建备份文件夹
if (!backupDir.exists()) {
backupDir.mkdirs(); // 如果文件夹不存在,则创建
}
File backupFile = new File(backupDir, "notes_backup.txt"); // 创建备份文件
try (PrintStream out = new PrintStream(new FileOutputStream(backupFile))) { // 创建输出流
Cursor cursor = Notes.getNotesCursor(); // 获取笔记数据的Cursor
if (cursor == null) {
Log.e(TAG, "Failed to get notes cursor."); // 输出错误日志
return STATE_SYSTEM_ERROR; // 返回系统错误状态
}
while (cursor.moveToNext()) { // 遍历笔记数据
String title = cursor.getString(cursor.getColumnIndex(NoteColumns.TITLE)); // 获取笔记标题
String content = cursor.getString(cursor.getColumnIndex(NoteColumns.CONTENT)); // 获取笔记内容
String date = DateFormat.format("yyyy-MM-dd HH:mm:ss", cursor.getLong(cursor.getColumnIndex(NoteColumns.DATE))).toString(); // 获取笔记日期
out.println(title); // 输出笔记标题
out.println(content); // 输出笔记内容
out.println(date); // 输出笔记日期
out.println("----------"); // 输出分隔符
}
cursor.close(); // 关闭Cursor
} catch (FileNotFoundException e) {
Log.e(TAG, "Failed to create backup file.", e); // 输出错误日志
return STATE_SYSTEM_ERROR; // 返回系统错误状态
} catch (IOException e) {
Log.e(TAG, "Failed to write backup file.", e); // 输出错误日志
return STATE_SYSTEM_ERROR; // 返回系统错误状态
}
return STATE_SUCCESS; // 返回备份成功状态
}
// 从SD卡恢复笔记数据
public int restoreNotes() {
if (!isExternalStorageReadable()) { // 检查外部存储是否可读
Log.e(TAG, "External storage is not readable."); // 输出错误日志
return STATE_SD_CARD_UNMOUONTED; // 返回SD卡未挂载状态
}
File backupDir = new File(Environment.getExternalStorageDirectory(), "NotesBackup"); // 创建备份文件夹
File backupFile = new File(backupDir, "notes_backup.txt"); // 创建备份文件
if (!backupFile.exists()) { // 检查备份文件是否存在
Log.e(TAG, "Backup file does not exist."); // 输出错误日志
return STATE_BACKUP_FILE_NOT_EXIST; // 返回备份文件不存在状态
}
try (PrintStream out = new PrintStream(new FileOutputStream(backupFile))) { // 创建输出流
// 读取备份文件并恢复笔记数据
// 这里需要实现具体的恢复逻辑
} catch (FileNotFoundException e) {
Log.e(TAG, "Failed to open backup file.", e); // 输出错误日志
return STATE_SYSTEM_ERROR; // 返回系统错误状态
} catch (IOException e) {
Log.e(TAG, "Failed to read backup file.", e); // 输出错误日志
return STATE_SYSTEM_ERROR; // 返回系统错误状态
}
return STATE_SUCCESS; // 返回恢复成功状态
}
}
// 检查外部存储是否可用
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, // 笔记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, // MIME类型
DataColumns.DATA1, // 数据1
DataColumns.DATA2, // 数据2
DataColumns.DATA3, // 数据3
DataColumns.DATA4, // 数据4
};
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 = "exported_notes.txt"; // 示例文件名
mFileDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/NotesBackup"; // 示例文件目录
}
// 导出到文本文件的方法
public int exportToText() {
// 实现导出逻辑
// 示例代码,具体实现根据需求进行
return BackupUtils.STATE_SUCCESS; // 返回导出成功状态
}
}
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]; // 根据传入的id返回对应的文本格式字符串
}
/**
* 将指定文件夹的笔记导出为文本
*/
private void exportFolderToText(String folderId, PrintStream ps) {
// 查询属于该文件夹的笔记
Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, // 笔记内容URI
NOTE_PROJECTION, // 查询的列
NoteColumns.PARENT_ID + "=?", // 查询条件筛选出父ID等于folderId的笔记
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); // 获取笔记ID
exportNoteToText(noteId, ps); // 导出笔记数据
} while (notesCursor.moveToNext()); // 遍历所有笔记
}
notesCursor.close(); // 关闭游标,释放资源
}
}
/**
* 将指定ID的笔记导出到打印流
*/
private void exportNoteToText(String noteId, PrintStream ps) {
Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, // 笔记数据内容URI
DATA_PROJECTION, // 查询的列
DataColumns.NOTE_ID + "=?", // 查询条件筛选出笔记ID等于noteId的数据
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)); // 打印电话号码
}
}
// 可以根据需要添加其他类型的笔记导出逻辑
} while (dataCursor.moveToNext()); // 遍历所有数据
}
dataCursor.close(); // 关闭游标,释放资源
}
}
private void exportNoteToText(String noteId, PrintStream ps) {
// 查询指定笔记ID的数据
Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, // 笔记数据内容URI
DATA_PROJECTION, // 查询的列
DataColumns.NOTE_ID + "=?", // 查询条件筛选出笔记ID等于noteId的数据
new String[] { noteId }, // 查询条件的参数
null); // 排序参数,这里不指定排序
if (dataCursor != null) { // 如果查询结果不为空
if (dataCursor.moveToFirst()) { // 移动到第一条数据
do {
// 获取数据的MIME类型
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; // 返回SD卡未挂载的状态码
}
// 获取用于导出文本的打印流
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, // 笔记内容URI
NOTE_PROJECTION, // 查询的列
"(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " // 笔记类型为文件夹
+ NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " // 并且父ID不等于垃圾桶文件夹ID
+ NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, // 或者笔记ID等于通话记录文件夹ID
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); // 获取文件夹ID
exportFolderToText(folderId, ps); // 导出文件夹中的笔记
} while (folderCursor.moveToNext()); // 遍历所有文件夹
}
folderCursor.close(); // 关闭游标,释放资源
}
}
Cursor noteCursor = mContext.getContentResolver().query(
Notes.CONTENT_NOTE_URI, // 笔记内容URI
NOTE_PROJECTION, // 查询的列
NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + "=0", // 查询条件筛选出类型为笔记且父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); // 获取笔记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; // 返回null表示无法获取打印流
}
mFileName = file.getName(); // 获取并保存文件名
mFileDirectory = mContext.getString(R.string.file_path); // 获取并保存文件目录
PrintStream ps = null; // 初始化打印流为null
try {
FileOutputStream fos = new FileOutputStream(file); // 创建文件输出流
ps = new PrintStream(fos); // 创建打印流
} catch (FileNotFoundException e) {
e.printStackTrace(); // 打印文件未找到异常的堆栈信息
return null; // 返回null表示无法获取打印流
} catch (NullPointerException e) {
e.printStackTrace(); // 打印空指针异常的堆栈信息
return null; // 返回null表示无法获取打印流
}
return ps; // 返回打印流
}
private PrintStream getExportToTextPrintStream() {
// 调用generateFileMountedOnSDcard方法生成导出文件
File file = generateFileMountedOnSDcard(mContext, R.string.file_path, R.string.file_name_txt_format);
// 如果文件生成失败返回null
if (file == null) {
Log.e(TAG, "create file to exported failed"); // 记录错误日志
return null;
}
// 获取文件名并赋值给mFileName
mFileName = file.getName();
// 获取文件目录并赋值给mFileDirectory
mFileDirectory = mContext.getString(R.string.file_path);
// 初始化PrintStream对象为null
PrintStream ps = null;
try {
// 创建FileOutputStream对象用于写入文件
FileOutputStream fos = new FileOutputStream(file);
// 创建PrintStream对象用于将数据输出到文件
ps = new PrintStream(fos);
} catch (FileNotFoundException e) {
// 如果文件未找到打印异常信息并返回null
e.printStackTrace();
return null;
} catch (NullPointerException e) {
// 如果发生空指针异常打印异常信息并返回null
e.printStackTrace();
return null;
}
// 返回PrintStream对象
return ps;
}
private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) {
// 创建StringBuilder对象用于构建文件路径
StringBuilder sb = new StringBuilder();
sb.append(Environment.getExternalStorageDirectory()); // 获取外部存储目录并添加到路径中
sb.append(context.getString(filePathResId)); // 添加文件路径(从资源文件中获取)
File filedir = new File(sb.toString()); // 根据路径创建文件夹对象
sb.append(context.getString(
fileNameFormatResId, // 文件名格式资源ID
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; // 如果发生异常或文件创建失败则返回null
}
/**
* Generate the text file to store imported data
*/
private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) {
// 创建StringBuilder用于构建文件路径
StringBuilder sb = new StringBuilder();
sb.append(Environment.getExternalStorageDirectory()); // 获取外部存储目录并添加到路径中
sb.append(context.getString(filePathResId)); // 添加文件路径(从资源文件中获取)
File filedir = new File(sb.toString()); // 根据路径创建文件夹对象
sb.append(context.getString(
fileNameFormatResId, // 文件名格式资源ID
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; // 如果发生异常或文件创建失败则返回null
}
Loading…
Cancel
Save