zoukankan      html  css  js  c++  java
  • 某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那部分的代码了.至于两者的区别,我就不清楚了.有知道的朋友,望告知

  • 相关阅读:
    EXCEL某列长度超过255个字符导入SQL SERVER2005的处理方法
    正则同时获取a标签里的href,text 2项
    火柴棍
    特殊数
    骨牌铺方格
    拼图
    挑战题之排列生成
    模拟 找规律
    sort
    贪心 简单背包问题
  • 原文地址:https://www.cnblogs.com/youxilua/p/2365346.html
Copyright © 2011-2022 走看看