某android平板項目開發筆記---計劃任務備份

前言:

好久,都沒更新過這個系列了…由於,除了圖表之外,而後就是數據庫了,調試了一個多星期的Ormlite數據庫,在最新版本中(orm 4.3.3)發現了幾個比較嚴重的bug(例如,查找id的時候沒法使用Long類型),不過,還好,ormlite社區還算活躍,bug,已經在預覽中修復了.關於Ormlite數據庫的話,園子裏面已經有了寫得很不錯的教程了,我就不重複他們的勞動了.而後,數據庫搞定了,就是寫業務了,有這麼一個業務,就是,要求,在某個時間點,對插入的數據進行後臺更新,而後,就涉及到了使用計劃任務這麼一塊知識,以爲有必要作下筆記,這塊,之後應該也能用到html

業務說明:

   在某時某刻進行數據庫的備份.java

相關知識:

1,時間操做

(1) 熟悉使用Calendarandroid

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 執行備份操做ide

居然是定時任務,咱們就要熟悉一個android的一個用於作定時任務的類學習

AlarmManager

各位,先去看一下官方文檔,在接着看下去吧…this

這個類是的初始化是必需要用Context.getSystemService(Context.ALARM_SERVICE). google

如下爲定時代碼塊

//初始化定時類
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那部分的代碼了.至於二者的區別,我就不清楚了.有知道的朋友,望告知

相關文章
相關標籤/搜索