展会信息港展会大全

Android技术精髓-BackupActivity
来源:互联网   发布日期:2016-01-14 10:27:45   浏览:1308次  

导读:Android技术精髓-BackupActivity首先介绍下今天主题BackupActivity功能:在Android应用UI activity 中继承AsynTask 异步开启后...

Android技术精髓-BackupActivity

首先介绍下今天主题BackupActivity功能:在Android应用UI activity 中继承AsynTask 异步开启后台线程,实现数据库动态备份(backup)、恢复的功能(restore) 可方便的使我们的Android程序在onPause()暂停中备份数据库文件,在Onresume()恢复中恢复数据库。

介绍下代码,首先是BackupTask 这个备份帮助类。继承AsyncTask,为UI Activity 实现后台线程备份、恢复操作。

定义4种状态:备份成功、恢复成功、备份失败、未找到文件错误

public static final int BACKUP_SUCCESS = 1;

public static final int RESTORE_SUCCESS = 2;

public static final int BACKUP_ERROR = 3;

public static final int RESTORE_NOFILEERROR = 4;

以及定义两个命令: 数据库备份命令、数据库恢复命令

public static final String COMMAND_BACKUP = "backupDatabase";

public static final String COMMAND_RESTORE = "restoreDatabase";

设计外用listener接口CompletionListener,方便后续扩展完成后操作

public interface CompletionListener {

void onBackupComplete();

void onRestoreComplete();

void onError(int errorCode);

}

AsynTask的核心在于doInBackground()中后台运行我们备份以及恢复的工作,

当task后台收到 COMMAND_BACKUP 开始备份备份数据库

收到COMMAND_RESTORE 开始恢复数据库

if (command.equals(COMMAND_BACKUP)) {

try {

//执行备份

} catch (IOException e) {

return BACKUP_ERROR;

}

} else if (command.equals(COMMAND_RESTORE)) {

try {

//执行恢复

} catch (IOException e) {

return BACKUP_ERROR;

}

} else {

return BACKUP_ERROR;

}

因此我们动态的在UI activity 中使用task.execute()去执行我们定义好的命令COMMAND就可动态,在onpause()中使用备份,onresume()中使用恢复数据库。

请看代码:

package activitys;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.nio.channels.FileChannel;

import android.app.Activity;

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Environment;

import android.widget.Toast;

class BackupTask extends AsyncTask {

public interface CompletionListener {

void onBackupComplete();

void onRestoreComplete();

void onError(int errorCode);

}

public static final int BACKUP_SUCCESS = 1;

public static final int RESTORE_SUCCESS = 2;

public static final int BACKUP_ERROR = 3;

public static final int RESTORE_NOFILEERROR = 4;

public static final String COMMAND_BACKUP = "backupDatabase";

public static final String COMMAND_RESTORE = "restoreDatabase";

private Context mContext;

private CompletionListener listener;

public BackupTask(Context context) {

super();

mContext = context;

}

public void setCompletionListener(CompletionListener aListener) {

listener = aListener;

}

@Override

protected Integer doInBackground(String... params) {

File dbFile = mContext.getDatabasePath("mydb");

File exportDir = new File(Environment.getExternalStorageDirectory(),

"myAppBackups");

if (!exportDir.exists()) {

exportDir.mkdirs();

}

File backup = new File(exportDir, dbFile.getName());

String command = params[0];

if (command.equals(COMMAND_BACKUP)) {

try {

backup.createNewFile();

fileCopy(dbFile, backup);

return BACKUP_SUCCESS;

} catch (IOException e) {

return BACKUP_ERROR;

}

} else if (command.equals(COMMAND_RESTORE)) {

try {

if (!backup.exists()) {

return RESTORE_NOFILEERROR;

}

dbFile.createNewFile();

fileCopy(backup, dbFile);

return RESTORE_SUCCESS;

} catch (IOException e) {

return BACKUP_ERROR;

}

} else {

return BACKUP_ERROR;

}

}

@Override

protected void onPostExecute(Integer result) {

switch (result) {

case BACKUP_SUCCESS:

if (listener != null) {

listener.onBackupComplete();

}

break;

case RESTORE_SUCCESS:

if (listener != null) {

listener.onRestoreComplete();

}

break;

case RESTORE_NOFILEERROR:

if (listener != null) {

listener.onError(RESTORE_NOFILEERROR);

}

break;

default:

if (listener != null) {

listener.onError(BACKUP_ERROR);

}

}

}

private void fileCopy(File source, File dest) throws IOException {

FileChannel inChannel = new FileInputStream(source).getChannel();

FileChannel outChannel = new FileOutputStream(dest).getChannel();

try {

inChannel.transferTo(0, inChannel.size(), outChannel);

} finally {

if (inChannel != null)

inChannel.close();

if (outChannel != null)

outChannel.close();

}

}

}

接下来在BackupActivity 我们调用接口BackupTask,实现后台线程,分别在onpause()、onresume()执行task命令进行相应备份、恢复操作如下:

@Override

public void onResume() {

super.onResume();

if (Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)) {

BackupTask task = new BackupTask(this);

task.setCompletionListener(this);

task.execute(BackupTask.COMMAND_RESTORE);

}

}

@Override

public void onPause() {

super.onPause();

if (Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)) {

BackupTask task = new BackupTask(this);

task.execute(BackupTask.COMMAND_BACKUP);

}

}

请看代码:

package activitys;

import com.example.design_activitys.R;

import android.app.Activity;

import android.database.sqlite.SQLiteDatabase;

import android.os.Bundle;

import android.os.Environment;

import android.widget.Toast;

public class BackupActivity extends Activity implements BackupTask.CompletionListener {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

SQLiteDatabase db = openOrCreateDatabase("mydb", Activity.MODE_PRIVATE,

null);

db.close();

}

@Override

public void onResume() {

super.onResume();

if (Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)) {

BackupTask task = new BackupTask(this);

task.setCompletionListener(this);

task.execute(BackupTask.COMMAND_RESTORE);

}

}

@Override

public void onPause() {

super.onPause();

if (Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)) {

BackupTask task = new BackupTask(this);

task.execute(BackupTask.COMMAND_BACKUP);

}

}

@Override

public void onBackupComplete() {

Toast.makeText(this, "Backup Successful", Toast.LENGTH_SHORT).show();

}

@Override

public void onError(int errorCode) {

if (errorCode == BackupTask.RESTORE_NOFILEERROR) {

Toast.makeText(this, "No Backup to Restore", Toast.LENGTH_SHORT)

.show();

} else {

Toast.makeText(this, "Error: " + errorCode, Toast.LENGTH_SHORT)

.show();

}

}

@Override

public void onRestoreComplete() {

Toast.makeText(this, "Restore Successful", Toast.LENGTH_SHORT).show();

}

}

AsyncTask用户界面线程,允许执行后台操作而无需操作线程和/或处理程序发布在UI线程上的结果。

AsyncTask的设计是UI thread和Handler一个辅助类,并不构成一个通用线程框架。

这是一个后台下载,前台同步显示的例子,显示了asynctask的优势功能。代码如下:

private class DownloadFilesTask extends AsyncTask {

protected Long doInBackground(URL... urls) {

int count = urls.length;

long totalSize = 0;

for (int i = 0; i AsyncTask

实现AsyncTask中定义的下面一个或几个方法:

* onPreExecute(), 该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。

* doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。

* onProgressUpdate(Progress...),在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。

* onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户.

* onCancelled(),在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。

为了正确的使用AsyncTask类,以下是几条必须遵守的准则:

1) Task的实例必须在UI 线程中创建

2) execute方法必须在UI 线程中调用

3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。

4) 该task只能被执行一次,否则多次调用时将会出现异常

doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为 doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参 数。

//AsyncTask的参数类型由用户设定,这里设为三个String

//第一个String代表输入到任务的参数类型,也即是doInBackground()的参数类型

//第二个String代表处理过程中的参数类型,也就是doInBackground()执行过程中的产出参数类型,通过publishProgress()发消息

//传递给onProgressUpdate()一般用来更新界面

//第三个String代表任务结束的产出类型,也就是doInBackground()的返回值类型,和onPostExecute()的参数类型

private class task extends AsyncTask

AsyncTask 的执行分为四个步骤,每一步都对应一个回调方法,需要注意的是这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。在任务的执行过程中,这些方法被自动调用。

* onPreExecute() 当任务执行之前开始调用此方法,可以在这里显示进度对话框。

* doInBackground(Params...) 此方法在后台线程 执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress...)来更新任务的进度。

* onProgressUpdate(Progress...) 此方法在主线程 执行,用于显示任务执行的进度。

* onPostExecute(Result) 此方法在主线程 执行,任务执行的结果作为此方法的参数返回

AsyncTask的三个泛型参数说明(三个参数可以是任何类型)

第一个参数:传入doInBackground()方法的参数类型

第二个参数:传入onProgressUpdate()方法的参数类型

第三个参数:传入onPostExecute()方法的参数类型,也是doInBackground()方法返回的类型

FileChannel

FileChannel,是内存与磁盘文件的通道。

优势:

多线程并发读写,并发性;

IO读写性能提高(OS负责),也可引做共享内存,减少IO操作,提升并发性;

应用crash,保证这部分内容还能写的进去文件。在我们调用channel.write(bytebuffer)之后,具体何时写入磁盘、bytebuffer中内容暂存于哪里(os

cache)等相关一系列问题,就交由OS本身负责了。

基本使用例:

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

/**

* FileChannel的基本使用。

*/

public class AcquireChannel {

public static void main(String[] args) throws Exception {

// 根据FileOutputStream获得通道FileChannel

FileChannel channel = new FileOutputStream("D:/a.txt").getChannel();

// 字节方式写入

channel.write(ByteBuffer.wrap("hello, NIO world in java!".getBytes()));

channel.close();

// 根据FileInputStream获得通道FileChannel

channel = new FileInputStream("D:/a.txt").getChannel();

// ByteBuffer分配空间,16个字节

// 这里需要知道byte是1字节, short和char是2字节,int和float是4字节

//long和double是8字节1byte=8bit 。基本只是还是必须记住的。

ByteBuffer buff = ByteBuffer.allocate(16);

// 字节数组数据装入buff,

channel.read(buff);

// 反转此缓冲区

buff.flip();

// 逐个输出,因为分配了16,所以输出的时候只能输出hello, NIO world,剩下的

// 因为空间关系被截断。

while(buff.hasRemaining()){

System.out.print((char)buff.get());

}

channel.close();

}

}

Environment

Environment 是一个提供访问环境变量的类。

Environment 包含常量:

MEDIA_BAD_REMOVAL

解释:返回getExternalStorageState() ,表明SDCard 被卸载前己被移除

MEDIA_CHECKING

解释:返回getExternalStorageState() ,表明对象正在磁盘检查。

MEDIA_MOUNTED

解释:返回getExternalStorageState() ,表明对象是否存在并具有读/写权限

MEDIA_MOUNTED_READ_ONLY

解释:返回getExternalStorageState() ,表明对象权限为只读

MEDIA_NOFS

解释:返回getExternalStorageState() ,表明对象为空白或正在使用不受支持的文件系统。

MEDIA_REMOVED

解释:返回getExternalStorageState() ,如果不存在 SDCard 返回

MEDIA_SHARED

解释:返回getExternalStorageState() ,如果 SDCard 未安装 ,并通过 USB 大容量存储共享 返回

MEDIA_UNMOUNTABLE

解释:返回getExternalStorageState() ,返回 SDCard 不可被安装 如果 SDCard 是存在但不可以被安装

MEDIA_UNMOUNTED

解释:返回getExternalStorageState() ,返回 SDCard 已卸掉如果 SDCard是存在但是没有被安装

Environment 常用方法:

方法:getDataDirectory()

解释:返回 File ,获取 Android 数据目录。

方法:getDownloadCacheDirectory()

解释:返回 File ,获取 Android 下载/缓存内容目录。

方法:getExternalStorageDirectory()

解释:返回 File ,获取外部存储目录即 SDCard

方法:getExternalStoragePublicDirectory(String type)

解释:返回 File ,取一个高端的公用的外部存储器目录来摆放某些类型的文件

方法:getExternalStorageState()

解释:返回 File ,获取外部存储设备的当前状态

方法:getRootDirectory()

解释:返回 File ,获取 Android 的根目录

转载请注明出处:http://write.blog.csdn.net/postedit/18527347

谢谢!

2014.1.20

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港