Android數據庫備份和恢復
一定要加上權限,否則不能在sdcard中創建文件
<!--在sdcard中創建/刪除文件的權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--往sdcard中寫入數據的權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
直接調用 restoreDB 進行數據庫恢復,調用backupDB進行數據庫備份。
恢復的時候會顯示出可以恢復的數據庫文件列表
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.text.SimpleDateFormat; import java.util.Date;import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.os.AsyncTask; import android.os.Environment; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; import android.widget.ProgressBar; import android.widget.Toast;
public class BackupAndRestore { private Context mContext = null; private String[] fileList = null; // 數據庫文件列表 private int choicePostion = -3; // 選擇數據庫列表中的位置 private AlertDialog dialog = null; private String BACK_FOLDER = "backup"; private String appName = "myApp";
public BackupAndRestore(Context context) { mContext = context; } /** * 恢復數據的Dialog */ public void restoreDB() { fileList = getFileList(); AlertDialog.Builder builder = new AlertDialog.Builder(mContext); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setTitle("恢復"); builder.setSingleChoiceItems(getFileList(), -1, new DialogClick()); builder.setPositiveButton("確定", new DialogClick()); builder.setNegativeButton("取消", new DialogClick()); builder.show(); } /** * 備份數據庫 */ public void backupDB() { showDialog("是否備份數據庫", 'B'); } /** * 顯示一個Dialog * * @param title * 標題 ,必須引用資源ID resource ID * @param sign * 根據標示調用方法 I - 恢復默認設置 D - 恢復默認設置 H -選擇主機 */ private void showDialog(String title, char sign) { final char s = sign; new AlertDialog.Builder(mContext).setTitle(title) .setPositiveButton("確定", new OnClickListener() { @Override public void onClick(DialogInterface dialogI, int which) { switch (s) { case 'B': // 備份數據庫 if (dialog == null) { dialog = awaitDialog(mContext); } else { dialog.show(); } new ExecuteTask().execute('B'); break; default: break; } } }).setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }).show(); } /** * 備份操作 * * @return */ private boolean backUp() { boolean isOk = false; String sp = File.separator; File sdFile = sdCardOk(); if (sdFile != null) { try { String[] dbNames = { "數據庫名稱" }; // 創建日期文件夾 String folder_date = datePrefix(); File f = new File(sdFile.getAbsolutePath() + sp + folder_date); if (!f.exists()) { f.mkdirs(); } for (int i = 0; i < dbNames.length; i++) { String dbName = dbNames[i]; File dbFile = dbOk(dbName); if (dbFile != null) { File backFile = new File(f.getAbsolutePath() + sp + dbFile.getName()); backFile.createNewFile(); isOk = fileCopy(backFile, dbFile.getAbsoluteFile()); if (!isOk) { break; } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return isOk; } /** * 時間前綴 * * @return */ private String datePrefix() { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); Date date = new Date(System.currentTimeMillis()); String str = format.format(date); return str; } /** * 文件夾列表 * * @return */ private String[] getFileList() { String[] fileList = null; File file = sdCardOk(); if (file != null) { File[] list = file.listFiles(); if (list != null && list.length > 0) { fileList = new String[list.length]; for (int i = 0; i < list.length; i++) { fileList[i] = list[i].getName(); } } } return fileList; } /** * sdCard是否存在 備份的文件夾是否存在 * * @return null不能使用 */ private File sdCardOk() { File bkFile = null; String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { String sp = File.separator; String backUpPath = Environment.getExternalStorageDirectory() + sp + appName + sp + BACK_FOLDER; bkFile = new File(backUpPath); if (!bkFile.exists()) { bkFile.mkdirs(); } else return bkFile; } else Toast.makeText(mContext, "Sdcard 不存在", Toast.LENGTH_SHORT).show(); return bkFile; } /** * 恢復數據庫 * * @param name * 選擇的文件名稱 選中的數據庫名稱 * @param resoreDbName * 需要恢復的數據庫名稱 * @return */ public boolean restore(String name, File f) { boolean isOk = false; if (f != null) { File dbFile = dbOk(name); try { // System.out.println("覆蓋的名稱"+dbName); if (dbFile != null) { isOk = fileCopy(dbFile, f.getAbsoluteFile()); } else isOk = false; } catch (IOException e) { e.printStackTrace(); } } return isOk; } /** * 數據庫文件是否存在,并可以使用 * * @return */ private File dbOk(String dbName) { String sp = File.separator; String absPath = Environment.getDataDirectory().getAbsolutePath(); String pakName = mContext.getPackageName(); String dbPath = absPath + sp + "data" + sp + pakName + sp + "databases" + sp + dbName; File file = new File(dbPath); if (file.exists()) { return file; } else { return null; } } /** * 等候動畫 */ public AlertDialog awaitDialog(Context context) { ProgressBar bar = new ProgressBar(context); bar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); AlertDialog dialog = new AlertDialog.Builder(context).create(); dialog.setCancelable(false); dialog.show(); Window window = dialog.getWindow(); WindowManager.LayoutParams params = window.getAttributes(); params.width = 50; params.height = 50; window.setAttributes(params); window.setContentView(bar); return dialog; } /** * * @param outFile * 寫入 * @param inFile * 讀取 * @throws FileNotFoundException */ private boolean fileCopy(File outFile, File inFile) throws IOException { if (outFile == null || inFile == null) { return false; } boolean isOk = true; FileChannel inChannel = new FileInputStream(inFile).getChannel();// 只讀 FileChannel outChannel = new FileOutputStream(outFile).getChannel();// 只寫 try { long size = inChannel.transferTo(0, inChannel.size(), outChannel); if (size <= 0) { isOk = false; } } catch (IOException e) { isOk = false; e.printStackTrace(); } finally { if (inChannel != null) { inChannel.close(); } if (outChannel != null) { outChannel.close(); } } return isOk; } private class DialogClick implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { if (which == -1) {// 確定 if (choicePostion < 0) { Toast.makeText(mContext, "選擇數據庫", Toast.LENGTH_SHORT) .show(); return; } String sp = File.separator; String folderName = fileList[choicePostion]; String backUpPath = Environment.getExternalStorageDirectory() + sp + appName + sp + BACK_FOLDER + sp + folderName; File file = new File(backUpPath); if (file.isDirectory()) { File[] files = file.listFiles(); boolean isOk = false; for (int i = 0; i < files.length; i++) { File f = files[i]; isOk = restore(f.getName(), f); if (!isOk) { String fail_msg = "恢復失敗" + ":" + f.getName(); Toast.makeText(mContext, fail_msg, Toast.LENGTH_SHORT).show(); return; } } if (isOk) { // 如果有數據體現則需要刷新出新的數據 } } } else if (which == -2) {// 取消 } else if (which >= 0) { choicePostion = which; } } } /** * 執行任務 * * @author Administrator * */ private class ExecuteTask extends AsyncTask<Character, Void, Boolean> { @Override protected Boolean doInBackground(Character... params) { char c = params[0]; if (c == 'B') { backUp(); } return null; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (dialog != null) { dialog.dismiss(); } } }
}
</pre>