某android平板项目开发笔记---计划任务备份

简介:

前言:

很久,都没更新过这个系列了…因为,除了图表以外,然后就是数据库了,调试了一个多星期的Ormlite数据库,在最新版本中(orm 4.3.3)发现了几个比较严重的bug(例如,查找id的时候无法使用Long类型),不过,还好,ormlite社区还算活跃,bug,已经在预览中修复了.关于Ormlite数据库的话,园子里面已经有了写得很不错的教程了,我就不重复他们的劳动了.然后,数据库搞定了,就是写业务了,有这么一个业务,就是,要求,在某个时间点,对插入的数据进行后台更新,然后,就涉及到了使用计划任务这么一块知识,觉得有必要做下笔记,这块,以后应该也能用到

业务说明:

   在某时某刻进行数据库的备份.

相关知识:

1,时间操作

(1) 熟悉使用Calendar

1,作为定时任务,我们需要一个具体的定时时间,以前,我是用Date 类取毫秒数,然后进行计数的操作

1.1例如

//以下为以前的某项目算相隔天数的演示代码 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).

以下为定时代码块

//初始化定时类 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分执行

c.set(Calendar.HOUR_OF_DAY, 23); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0);

 

总结:

使用Calendar类操作时间,和进行时间计算,设置,是十分方便的事情,

2,备份操作

1, 建一个接口类用于,监听操作.

public interface CompletionListener { void onBackupComplete(); void onRestoreComplete(); void onError(int errorCode); }

2,创建一个异步备份的类

public 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 
类 FileChannel transferTo

里面有这么一句话

与从此通道读取并将内容写入目标通道的简单循环语句相比,此方法可能高效得多。很多操作系统可将字节直接从文件系统缓存传输到目标通道,而无需实际复制各字节。

看到这句话我就使用了这个方法了,然后,为了搞清楚实现的方式,我查看了一下transferTo 的源码只是一个抽象方法,然后,在的FileInputSteam里面找的了channel 的实现方法,不过可惜的,具体的实现代码,我的源码包没有.

然后我顺便比较了java 和 android java 对于获取,channel的区别

java jdk_1.6_u30 默认的fileChannel是用sun包进行实现,然后,关于实现的部分,应该要下个sun包的源码了吧,因为,没找的,就贴不出来了.

public 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的代码部分

public 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那部分的代码了.至于两者的区别,我就不清楚了.有知道的朋友,望告知

相关文章
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
983 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
Web App开发 安全 程序员
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
多年的互联网寒冬在今年尤为凛冽,坚守安卓开发愈发不易。面对是否转行或学习新技术的迷茫,安卓程序员可从三个方向进阶:1)钻研谷歌新技术,如Kotlin、Flutter、Jetpack等;2)拓展新功能应用,掌握Socket、OpenGL、WebRTC等专业领域技能;3)结合其他行业,如汽车、游戏、安全等,拓宽职业道路。这三个方向各有学习难度和保饭碗指数,助你在安卓开发领域持续成长。
484 1
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
|
编解码 安全 Ubuntu
Android Selinux 问题处理笔记
这篇文章是关于处理Android系统中SELinux权限问题的笔记,介绍了如何通过分析SELinux拒绝的日志、修改SELinux策略文件,并重新编译部署来解决权限问题,同时提供了一些SELinux的背景知识和实用工具。
2137 0
|
JavaScript 前端开发 Java
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
IT寒冬使APP开发门槛提升,安卓程序员需转型。选项包括:深化Android开发,跟进Google新技术如Kotlin、Jetpack、Flutter及Compose;研究Android底层框架,掌握AOSP;转型Java后端开发,学习Spring Boot等框架;拓展大前端技能,掌握JavaScript、Node.js、Vue.js及特定框架如微信小程序、HarmonyOS;或转向C/C++底层开发,通过音视频项目如FFmpeg积累经验。每条路径都有相应的书籍和技术栈推荐,助你顺利过渡。
648 3
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
|
Java API Android开发
技术经验分享:Android源码笔记——Camera系统架构
技术经验分享:Android源码笔记——Camera系统架构
499 0
|
Java 测试技术 开发工具
Android 笔记:AndroidTrain , Lint , build(1),只需一篇文章吃透Android多线程技术
Android 笔记:AndroidTrain , Lint , build(1),只需一篇文章吃透Android多线程技术
|
设计模式 缓存 前端开发
真的强!借助阿里技术博主分享的Android面试笔记,我拿到了字节跳动的offer
真的强!借助阿里技术博主分享的Android面试笔记,我拿到了字节跳动的offer
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
675 3
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
存储 Java API
Android系统 文件访问权限笔记
Android系统 文件访问权限笔记
2529 1
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
1226 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库

热门文章

最新文章