Android中数据库和安装包分离
我们在做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中数据库和安装包分离的更多相关文章
- Android中数据库的操作流程详解
Android中数据库的操作方法: 1.Android平台提供了一个数据库辅助类来创建或打开数据库. 这个辅助类继承自SQLiteOpenHelper类.继承和扩展SQLiteOpenHelper类主 ...
- Android学习记录(2)—Android中数据库的常见操作
android中数据库操作是非常常见了,我们会经常用到,操作的方法也有很多种形式,这里我就把最常见的两种形式记录下来了,以备以后用到方便查看.我就不写注释和解释了,因为android数据库的操作和其它 ...
- Android中数据库Sqlite的性能优化
1.索引简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率.(1). 优点大大加快了数据库检索的速度,包括 ...
- 关于android中数据库的创建以及基础的增删改查的相应操作
这里主要是掌握一些基本的相应的知识,具体的是阿金是等到明天在进行. 相应的知识点如下: 对于数据库中的一些常识.SQLite 没有服务器进程,它通过文件保存数据,该文件是跨平台的,可以放在其他平台中使 ...
- android中的数据库操作
如何在android中调用数据库资源 在android中主要有两种方法来实现对数据库的访问,一种是adb shell方式,另一种是通过相关的android 的java类来间接的对数据库来进行操作.其中 ...
- android中的数据库操作(转)
android中的数据库操作 android中的应用开发很难避免不去使用数据库,这次就和大家聊聊android中的数据库操作. 一.android内的数据库的基础知识介绍 1.用了什么数据库 an ...
- android中的数据库操作(SQLite)
android中的数据库操作 android中的应用开发很难避免不去使用数据库,这次就和大家聊聊android中的数据库操作. 一.android内的数据库的基础知识介绍 1.用了什么数据库 an ...
- Android学习记录(3)—Android中ContentProvider的基本原理学习总结
一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据 ...
- 我的Android六章:Android中SQLite数据库操作
今天学习的内容是Android中的SQLite数据库操作,在讲解这个内容之前小编在前面有一篇博客也是讲解了SQLite数据库的操作,而那篇博客的讲解是讲述了 如何在Window中通过DOM来操作数据库 ...
随机推荐
- python3 分解质因数
python3 分解质因数 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Hiuhung Wan num = int(input(&quo ...
- Loadrunner--运行场景报Socket descriptor not found错误
今天早上在使用LoadRunner时,报了如下的错误,开始并未看错误以为是录制问题引起,就重新录制了一遍,简单施压看看错误是否还有,结果错误仍然有,如下所示: Error: Socket descri ...
- bootstrap课程6 bootstrap的表单注意事项有哪些
bootstrap课程6 bootstrap的表单注意事项有哪些 一.总结 一句话总结: 1.bootstrap中的表单中的每一项是什么样的形式? div.form-group>label +i ...
- Intel X86 CPU 系列的寻址方式
Intel X86 CPU 系列的寻址方式 数据总线和地址总线要尽量相同,这个是一个地址就是一个指针.
- Nginx和Nginx+的比較(下)
Nginx和Nginx+的比較(下) 作者:chszs.未经博主同意不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs 内容紧接上一篇<Nginx和 ...
- 浅浅的分析下es6箭头函数
原文链接:http://damobing.com/?p=589 前言 箭头函数作为es6重点的语法内容之一,很多开发者对其爱不释手,当也要注意其可能存在的问题,其正确的使用场景,否则会引起不必要的bu ...
- IGeometryCollection Interface
Come from ArcGIS Online IGeometryCollection Interface Provides access to members that can be used fo ...
- 向 Windows 高级用户进阶,这 10 款效率工具帮你开路 | 新手问号
原文地址:https://sspai.com/post/41411 编注:「新手问号」是少数派的一个全新栏目.它面向完全「零基础」的新手用户,通过最简单易懂的方式,帮助你快速掌握关于系统和软硬件的入门 ...
- Multi-core compute cache coherency with a release consistency memory ordering model
A method includes storing, with a first programmable processor, shared variable data to cache lines ...
- java之 ------ 枚举类型
枚举 一.枚举类型具体说明 简单的说.Enum一般用来表示一组同样类型的常量. 如性别.日期.月份.颜色等.对这些属性用常量的优点是显而易见的,不仅能够保证单例,且在比較的时候能够用"==& ...