某android平板项目开发笔记---计划任务备份
2012-02-23 19:09 youxiachai 阅读(3991) 评论(0) 编辑 收藏 举报前言:
很久,都没更新过这个系列了…因为,除了图表以外,然后就是数据库了,调试了一个多星期的Ormlite数据库,在最新版本中(orm 4.3.3)发现了几个比较严重的bug(例如,查找id的时候无法使用Long类型),不过,还好,ormlite社区还算活跃,bug,已经在预览中修复了.关于Ormlite数据库的话,园子里面已经有了写得很不错的教程了,我就不重复他们的劳动了.然后,数据库搞定了,就是写业务了,有这么一个业务,就是,要求,在某个时间点,对插入的数据进行后台更新,然后,就涉及到了使用计划任务这么一块知识,觉得有必要做下笔记,这块,以后应该也能用到
业务说明:
在某时某刻进行数据库的备份.
相关知识:
1,时间操作
(1) 熟悉使用Calendar
1,作为定时任务,我们需要一个具体的定时时间,以前,我是用Date 类取毫秒数,然后进行计数的操作
1.1例如
1234567891011121314151617181920212223//以下为以前的某项目算相隔天数的演示代码
String startDate = mDateStart.getText().toString();
String endDate = year +
"-"
+ (month + 1) +
"-"
+ day;
Log.d(
"soap"
, startDate +
"---"
+ endDate);
DateFormat df =
new
SimpleDateFormat(
"yyyy-MM-dd"
);
// long day=(startC.getTime()-endC.getTime())/(24*60*60*1000);
try
{
Date start = df.parse(startDate);
Date end = df.parse(endDate);
Long d = (end.getTime() - start.getTime()) / (24 * 60 * 60 * 1000);
Log.d(
"soap"
,
"相隔天数"
+ d);
if
(d > 60) {
return
false
;
}
else
{
return
true
;
}
}
catch
(ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
以前这样写,感觉挺傻的,希望大家不要学习了,这次的业务需求,如果,是以前的话,我会一个创建具体时间字符串,然后用SimpleDateFormat,获取毫秒数,这样个人感觉,很不直观,也麻烦,也不方便国际化,我们用Calendar做就非常简单了.
1.2 定时23:00 执行备份操作
竟然是定时任务,我们就要熟悉一个android的一个用于做定时任务的类
AlarmManager
各位,先去看一下官方文档,在接着看下去吧…
这个类是的初始化是必须要用Context.getSystemService(Context.ALARM_SERVICE).
以下为定时代码块
1234567891011121314//初始化定时类
AlarmManager am = (AlarmManager)
this
.getSystemService(Context.ALARM_SERVICE);
//设置定时时间,1分钟后执行
Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, 1);
//设置时间到了执行的services
Intent intent =
new
Intent();
//创建一个servcies
intent.setClass(
this
, UpdateStatics.
class
);
PendingIntent pi = PendingIntent.getService(
this
, 0, intent, 0);
//设置定时
//需要android.permission.SET_TIME 权限
//第一个参数为定时类型(一共有四种,具体参见官方文档),第二个参数为设置的定时时间为long类型,第三个为执行的目标
am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);
以上代码就会在,1分钟后,系统执行UpdateStatics 类.
如果,我们要设置具体的时间,只要具体设置Calendar的对象即可,例如23:00分执行
123c.set(Calendar.HOUR_OF_DAY, 23);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
总结:
使用Calendar类操作时间,和进行时间计算,设置,是十分方便的事情,
2,备份操作
1, 建一个接口类用于,监听操作.
12345public
interface
CompletionListener {
void onBackupComplete();
void onRestoreComplete();
void onError(int errorCode);
}
2,创建一个异步备份的类
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110public
class
BackupTask
extends
AsyncTask<String, Void, Integer>
implements
CompletionListener{
//定义常量
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_NOFLEERROR = 4;
public
static
final String COMMAND_BACKUP =
"backupDatabase"
;
public
static
final String COMMAND_RESTORE =
"restroeDatabase"
;
private
Context mContext;
public BackupTask(Context context){
this
.mContext = context;
}
@Override
protected
Integer doInBackground(String... params) {
//1,获得数据库路径
File dbFile = mContext.getDatabasePath(
"xxx.db"
);
//2,创建保存的数据库的路径
File exportDir =
new
File(Environment.getExternalStorageDirectory(),
"shopBackup"
);
if
(!exportDir.exists()){
exportDir.mkdirs();
}
File backup =
new
File(exportDir, dbFile.getName());
//3,检查操作
String command = params[0];
if
(command.equals(COMMAND_BACKUP)){
//复制文件
try
{
backup.createNewFile();
fileCopy(dbFile, backup);
return
BACKUP_SUCCESS;
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return
BACKUP_ERROR;
}
}
else
{
return
BACKUP_ERROR;
}
}
private
void fileCopy(File source, File dest) throws IOException {
FileChannel inChannel =
new
FileInputStream(source).getChannel();
FileChannel outChannel =
new
FileOutputStream(dest).getChannel();
// FileInputStream fis = new FileInputStream(dbFile);
// FileOutputStream fos = new FileOutputStream(backup);
// byte buffer[] = new byte[4 * 1024];
// while(fis.read(buffer) != -1){
// fos.write(buffer);
// }
// fos.flush();
//
long size = inChannel.size();
try
{
inChannel.transferTo(0, inChannel.size(), outChannel);
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if
(inChannel !=
null
){
inChannel.close();
}
if
(outChannel !=
null
){
outChannel.close();
}
}
}
@Override
protected
void onPostExecute(Integer result) {
// TODO Auto-generated method stub
super
.onPostExecute(result);
switch
(result) {
case
BACKUP_SUCCESS:
onBackupComplete();
break
;
default
:
break
;
}
}
@Override
public void onBackupComplete() {
Log.d(
"backup"
,
"ok"
);
}
@Override
public void onRestoreComplete() {
// TODO Auto-generated method stub
}
@Override
public void onError(int errorCode) {
// TODO Auto-generated method stub
}
}
记得,设置好权限:
android.permission.WRITE_EXTERNAL_STORAGE
AsyncTask<Params,Progress,Result> 这个类的用法,官方文档已经解释的很详细了,这里也不做重复解释.
关于:fileCopy(File source, File dest) 这个方法,我这里改用了Nio 的方式进行操作.用注释注释的代码是一般的方式,这个两者有什么区别呢?
文档
java.nio.channels
类 FileChanneltransferTo
里面有这么一句话
与从此通道读取并将内容写入目标通道的简单循环语句相比,此方法可能高效得多。很多操作系统可将字节直接从文件系统缓存传输到目标通道,而无需实际复制各字节。
看到这句话我就使用了这个方法了,然后,为了搞清楚实现的方式,我查看了一下transferTo 的源码只是一个抽象方法,然后,在的FileInputSteam里面找的了channel 的实现方法,不过可惜的,具体的实现代码,我的源码包没有.
然后我顺便比较了java 和 android java 对于获取,channel的区别
java jdk_1.6_u30 默认的fileChannel是用sun包进行实现,然后,关于实现的部分,应该要下个sun包的源码了吧,因为,没找的,就贴不出来了.
123456789101112131415public FileChannel getChannel() {
synchronized (
this
) {
if
(channel ==
null
) {
channel = FileChannelImpl.open(fd,
true
,
false
,
this
);
/*
* Increment fd's use count. Invoking the channel's close()
* method will result in decrementing the use count set for
* the channel.
*/
fd.incrementAndGetUseCount();
}
return
channel;
}
android java getChannel的代码部分
1234567891011public FileChannel getChannel() {
// BEGIN android-changed
synchronized(
this
) {
if
(channel ==
null
) {
channel = FileChannelFactory.getFileChannel(
this
, fd.descriptor,
IFileSystem.O_RDONLY);
}
return
channel;
}
// END android-changed
}
android java同样,我的源码包到实现filechannel 部分的代码就没了,对于获取filechannel ,google 是重写了sun那部分的代码了.至于两者的区别,我就不清楚了.有知道的朋友,望告知
作者:游戏阿柴
出处:http://www.cnblogs.com/youxilua
本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
微博联系:新浪微博
用支付宝赞助博主:http://me.alipay.com/youxilua
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂