我们在做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<Integer, String, Integer> {
/**
* 构造函数
*/
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();
} } }

目录结构如下:

Android中数据库和安装包分离的更多相关文章

  1. Android中数据库的操作流程详解

    Android中数据库的操作方法: 1.Android平台提供了一个数据库辅助类来创建或打开数据库. 这个辅助类继承自SQLiteOpenHelper类.继承和扩展SQLiteOpenHelper类主 ...

  2. Android学习记录(2)—Android中数据库的常见操作

    android中数据库操作是非常常见了,我们会经常用到,操作的方法也有很多种形式,这里我就把最常见的两种形式记录下来了,以备以后用到方便查看.我就不写注释和解释了,因为android数据库的操作和其它 ...

  3. Android中数据库Sqlite的性能优化

    1.索引简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率.(1). 优点大大加快了数据库检索的速度,包括 ...

  4. 关于android中数据库的创建以及基础的增删改查的相应操作

    这里主要是掌握一些基本的相应的知识,具体的是阿金是等到明天在进行. 相应的知识点如下: 对于数据库中的一些常识.SQLite 没有服务器进程,它通过文件保存数据,该文件是跨平台的,可以放在其他平台中使 ...

  5. android中的数据库操作

    如何在android中调用数据库资源 在android中主要有两种方法来实现对数据库的访问,一种是adb shell方式,另一种是通过相关的android 的java类来间接的对数据库来进行操作.其中 ...

  6. android中的数据库操作(转)

    android中的数据库操作 android中的应用开发很难避免不去使用数据库,这次就和大家聊聊android中的数据库操作. 一.android内的数据库的基础知识介绍 1.用了什么数据库   an ...

  7. android中的数据库操作(SQLite)

    android中的数据库操作 android中的应用开发很难避免不去使用数据库,这次就和大家聊聊android中的数据库操作. 一.android内的数据库的基础知识介绍 1.用了什么数据库   an ...

  8. Android学习记录(3)—Android中ContentProvider的基本原理学习总结

    一.ContentProvider简介        当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据 ...

  9. 我的Android六章:Android中SQLite数据库操作

    今天学习的内容是Android中的SQLite数据库操作,在讲解这个内容之前小编在前面有一篇博客也是讲解了SQLite数据库的操作,而那篇博客的讲解是讲述了 如何在Window中通过DOM来操作数据库 ...

随机推荐

  1. Jmeter--性能测试工具的搭建

    第一步:Jmeter软件下载第二步:解压下载的Jmeter包到某一盘符下,最好解压到无中文字符目录下,防止乱码问题,以我电脑为例,比如:D:tools第三步:找到解压的文件jmeter.bat,一般在 ...

  2. Dynamics CRM 2015/2016 Web API:Unbound Function 和 Bound Function

    今天我们来看看Dynamics CRM Web API Function 吧, 这是一个新概念,刚接触的时候我也是比較的迷糊.这种命名确实是和之前的那套基于SOAP协议的API全然联系不上.好了,不说 ...

  3. Oracle游标进行循环效率比较

    对300万一张表数据,用游标进行循环,不同写法的效率比较 对300万一张表数据,用游标进行循环,不同写法的效率比较   1.显示游标   declare     cursor cur_2 is sel ...

  4. Linux下的lds链接脚本简介(四)

    十一. 表达式 lds中表达式的文法与C语言的表达式文法一致,表达式的值都是整型,如果ld的运行主机和生成文件的目标机都是32位,则表达式是32位数据,否则是64位数据. 以下是一些常用的表达式: _ ...

  5. swift项目第九天:正则表达式的学习

    import UIKit /* 练习1:匹配abc 练习2:包含一个a~z,后面必须是0~9 -->[a-z][0-9]或者[a-z]\d * [a-z] : a~z * [0-9]/\d : ...

  6. 在scala中调用java代码

      详细代码请见https://github.com/lujinhong/scalademo 在scala中调用java代替非常非常简单,直接调用即可 (一)一个简单示例 1.创建一个java类 pa ...

  7. LibCurl HTTP部分详细介绍

    目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.curl_easy_setopt函数部分选项介绍 四.curl_easy_perform 函数说明(error 状态码) 五.lib ...

  8. 8、hzk16的介绍以及简单的使用方法

    HZK16 字库是符合GB2312标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个.其中一级汉字有3755个,按 声序排列,二级汉字有3008个,按偏旁部首 ...

  9. 《SPA设计与架构》之JavaScript模块化

    原文 简书原文:https://www.jianshu.com/p/d5fc38506bc4 大纲 1.什么是模块? 2.基本的模块模式 3.模块模式概念 4.模块结构 5.揭示模式 6.模块编程的意 ...

  10. 详解HTML的a标签(超链接标签)

    原文 简书原文:https://www.jianshu.com/p/d6a2499db73b 大纲 1.什么是<a>标签 2.<a>标签的几个重要属性 3.a标签的运行机制 4 ...