1. 程式人生 > >Android中db和apk分離

Android中db和apk分離

我們在做Android應用尤其是商業應用的時候,很多時候都需要後期版本升級,如果我們的資料庫檔案非常大,比如遊戲之類的,這時候就不應該每次版本更新都去重新複製資料庫。將資料庫和安裝包分離,下面來詳細介紹:

(1)判斷是否是第一次安裝

try {
			//獲取程式的當前版本
			PackageInfo info = getPackageManager().getPackageInfo(PACKAGE_NAME, 0);
			currentVersion = info.versionCode;
			//獲取上一個版本
			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
			lastVersion = prefs.getInt(VERSION_KEY, 0);
			System.out.println("當前版本是版本"+currentVersion);
			//判斷是否是第一次安裝
			if(currentVersion > lastVersion){
				//如果當前版本大於上次版本,說明該版本安裝檔案屬於第一次啟動
				initDatabase();
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}

(2)如果是第一次安裝,則需要判斷是否有資料庫檔案,如果沒有則需要複製
	private void initDatabase(){
		Toast.makeText(this, "不同版本", 2000);
		//獲取資料庫檔案要存放的路徑
		databaseFilename = DATABASE_PATH + "/" + DATABASE_FILENAME;
		File dir = new File(DATABASE_PATH);
		//如果目錄不存在,建立這個目錄
		if(!dir.exists()){
			dir.mkdir();
		}
		//資料庫檔案是否已存在,不存在則匯入
		if(!(new File(databaseFilename)).exists()){
			StartFrameTask startFrameTask = new StartFrameTask();
			startFrameTask.execute();
		}else{
			System.out.println("資料庫已經存在");
		}
	}

(3)如果還沒有資料庫檔案,則啟動非同步任務來複制
	private void copyDataBase(){
		try{
			// 獲得InputStream物件
			InputStream is = getResources().openRawResource(R.raw.cpdata);
			pd.setMax(is.available());
			FileOutputStream fos = new FileOutputStream(databaseFilename);
			byte[] buffer = new byte[1024];
			int count = 0;
			// 開始複製db檔案
			int process = 0;
			while ((count = is.read(buffer)) > 0) {
				fos.write(buffer, 0, count);
				process += count;
				pd.setProgress(process);
			}
			fos.close();
			is.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}

例項程式碼如下:
package com.example.testsqlite;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.widget.Toast;

public class MainActivity extends Activity {
	private static final String PACKAGE_NAME = "com.example.testsqlite";
	private static final String VERSION_KEY = "versionCode";  
	private static final String DATABASE_PATH = "data/data/com.example.testsqlite";
	private static final String DATABASE_FILENAME = "cpdata.db";
	private int currentVersion;
	private int lastVersion;
	private ProgressDialog pd;
	private String databaseFilename;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		try {
			//獲取程式的當前版本
			PackageInfo info = getPackageManager().getPackageInfo(PACKAGE_NAME, 0);
			currentVersion = info.versionCode;
			//獲取上一個版本
			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
			lastVersion = prefs.getInt(VERSION_KEY, 0);
			System.out.println("當前版本是版本"+currentVersion);
			//判斷是否是第一次安裝
			if(currentVersion > lastVersion){
				//如果當前版本大於上次版本,說明該版本安裝檔案屬於第一次啟動
				initDatabase();
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	private void initDatabase(){
		Toast.makeText(this, "不同版本", 2000);
		//獲取資料庫檔案要存放的路徑
		databaseFilename = DATABASE_PATH + "/" + DATABASE_FILENAME;
		File dir = new File(DATABASE_PATH);
		//如果目錄不存在,建立這個目錄
		if(!dir.exists()){
			dir.mkdir();
		}
		//資料庫檔案是否已存在,不存在則匯入
		if(!(new File(databaseFilename)).exists()){
			StartFrameTask startFrameTask = new StartFrameTask();
			startFrameTask.execute();
		}else{
			System.out.println("資料庫已經存在");
		}
	}
	
	private void copyDataBase(){
		try{
			// 獲得InputStream物件
			InputStream is = getResources().openRawResource(R.raw.cpdata);
			pd.setMax(is.available());
			FileOutputStream fos = new FileOutputStream(databaseFilename);
			byte[] buffer = new byte[1024];
			int count = 0;
			// 開始複製db檔案
			int process = 0;
			while ((count = is.read(buffer)) > 0) {
				fos.write(buffer, 0, count);
				process += count;
				pd.setProgress(process);
			}
			fos.close();
			is.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	
	/**
	 * 開啟進度對話方塊
	 */
	private void startProgressDialog() {
		if (pd == null) {
			pd = new ProgressDialog(this);
			pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			pd.setMessage("正在初始化資料庫檔案");
			pd.setCancelable(false);
		}
		pd.show();
	}

	/**
	 * 停止進度對話方塊
	 */
	private void stopProgressDialog() {
		if (pd != null) {
			pd.dismiss();
			pd = null;
		}

	}

	/**
	 * 建立非同步任務
	 * 
	 * @author 李小強
	 * 
	 */
	public class StartFrameTask extends AsyncTask {
		/**
		 * 建構函式
		 */
		public StartFrameTask() {

		}

		/**
		 * 呼叫取消時
		 */
		@Override
		protected void onCancelled() {
			stopProgressDialog();
			super.onCancelled();
		}

		/**
		 * 後臺執行緒查詢資料
		 */
		@Override
		protected Integer doInBackground(Integer... params) {
			copyDataBase();
			return null;
		}

		/**
		 * 該方法將在執行後臺耗時操作前被呼叫
		 */
		@Override
		protected void onPreExecute() {
			startProgressDialog();
		}

		/**
		 * 將doInBackground()的返回值傳給該方法
		 */
		@Override
		protected void onPostExecute(Integer result) {
			stopProgressDialog();
		}

	}

}