You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gitProject/src/main/java/net/micode/notes/tool/BackupUtils.java

353 lines
15 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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;
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;
/*备份工具类,用于数据备份读取和显示*/
public class BackupUtils {
private static final String TAG = "BackupUtils";//定义类的名字标识
// Singleton stuff
private static BackupUtils sInstance;//定义实体对象
public static synchronized BackupUtils getInstance(Context context) {
//获取实体对象
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 {
//note映射数组存储note信息
private static final String[] NOTE_PROJECTION = {
NoteColumns.ID,
NoteColumns.MODIFIED_DATE,
NoteColumns.SNIPPET,
NoteColumns.TYPE
};
//以下几行定义note数组里的属性值
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) {
//从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通过文件夹id向文本输出文件夹
*/
private void exportFolderToText(String folderId, PrintStream ps) {
// Query notes belong to this folder查询该notes是否属于这个文件夹
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.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查询该note的数据
String noteId = notesCursor.getString(NOTE_COLUMN_ID);
exportNoteToText(noteId, ps);
} while (notesCursor.moveToNext());//对该note所有的数据
}
notesCursor.close();//关闭游标
}
}
/**
* Export note identified by id to a print stream输出note id向一个打印流
*/
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)) {
// 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打印一个线分隔两个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以text形式输出到外部设备SDcard
*/
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;//系统状态错误
}
// First export folder and its notes第一次输出文件夹和他的note
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输出notes到系统文件夹
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查询这个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() {
//create file to exported failed
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;//返回新文件的打印流
}
}
/**
* 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());//存储路径信息
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();////错误抛出异常
}
return null;
}
}