1.背景

所谓外部数据库文件此处指的就是一个在外部单独创建的db文件,假设有这么一个场景,我们项目中有一些本地数据,不需要接口去获取的(不需要进行网络操作),写死的数据,比如全国各个省各个市的一些基本信息,每个市的信息可以作为表里的一条记录存放,在项目中使用,此时如何我们已经有了包含这些信息的db文件,我们就可以通过greendao来操作这个db文件,更具方便进行开发工作,当然这只是个模拟情况,至于合不合理,有没有更好的方式,此处不过多讨论,重点讲这么一种方式,这种方式可以用于一些不经常变化的数据。

2.项目配置

  • 首先看一下项目结构:

res/raw目录存放的就是外部的db文件的压缩文件,我们可以打开看一下数据库结构,db文件包含两张表,student和teacher里面简单的插入了几条测试数据:

 

  • 引入greendao库文件或者引用库工程:

2.代码实现

实现之前先说一下具体的思路,程序运行,首先把raw目录下的db文件拷贝到数据库存储的默认目录,然后通过greendao的api对这个文件进行操作即可;

    • 我们需要获取应用db存储的路径,通过如下方式:
private void getAppInfo()
{
// 获取packageManager的实例
PackageManager packageManager = getPackageManager();
// getPackageName()是你当前类的包名,0代表是获取版本信息
try
{
packInfo = packageManager.getPackageInfo(getPackageName(), );
}
catch (NameNotFoundException e)
{
e.printStackTrace();
}
}
    • 通过以上方式即可获取到数据库的路径: 

    • 拷贝操作:

public static boolean copyRawDBToApkDb(Context context, int copyRawDbResId, String apkDbPath, String dbName,boolean refresh)
throws IOException
{
boolean b = false; File f = new File(apkDbPath);
if (!f.exists())
{
f.mkdirs();
} File dbFile = new File(apkDbPath + dbName);
b = isDbFileExists(dbFile,refresh);
if (!b)
{
InputStream is = context.getResources().openRawResource(copyRawDbResId); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry entry; while ((entry = zis.getNextEntry()) != null)
{
int size;
byte[] buffer = new byte[ * ]; OutputStream fos = new FileOutputStream(apkDbPath + entry.getName());
BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.length); while ((size = zis.read(buffer, , buffer.length)) != -)
{
bos.write(buffer, , size);
}
bos.flush();
bos.close();
}
zis.close();
is.close();
}
return !b;
}

此处是拷贝操作的关键代码,需要我们传入raw资源ID,数据库的拷贝路径,数据库文件名,是否覆盖已经存在的db文件,@return 拷贝是否成功,关于refresh参数,我们一般希望只拷贝一次,当我们在某些情况下更新了这个db文件的话就可以设置为true进行覆盖操作;

  • 使用greenDao java工程,生成外部db文件所对应表的实体类Dao类等代码:

上图中的DBController类是我封装的数据库操作类,更方便我们去进行操作,DBController的关键代码如下:

/**
* 外部数据库控制类
*/
public class DBController
{
private static DaoMaster daoMasterEcmc; private static DaoMaster daoMasterSchool; // 默认DB
private static DaoSession daoSessionDefault; // 拷贝的db
private static DaoSession daoSchoolSession; /**
* 默认数据库名称:localdata
*/
public static final String DATABASE_NAME = "localdata.db"; /**
* 拷贝数据库名称:school
*/
public static final String DATABASE_SCHOOL_NAME = "school.db"; private static DaoMaster obtainMaster(Context context, String dbName)
{
return new DaoMaster(new DaoMaster.DevOpenHelper(context, dbName, null).getWritableDatabase());
} private static DaoMaster getDaoMaster(Context context, String dbName)
{
if (dbName == null)
return null;
if (daoMasterEcmc == null)
{
daoMasterEcmc = obtainMaster(context, dbName);
}
return daoMasterEcmc;
} private static DaoMaster getSchoolDaoMaster(Context context, String dbName)
{
if (dbName == null)
return null;
if (daoMasterSchool == null)
{
daoMasterSchool = obtainMaster(context, dbName);
}
return daoMasterSchool;
} /**
* 取得DaoSession
*
* @return
*/
public static DaoSession getDaoSession(String dbName)
{ if (daoSchoolSession == null)
{
daoSchoolSession = getSchoolDaoMaster(MainApplication.getIns(), dbName).newSession();
}
return daoSchoolSession;
} /**
* 默认操作localdata数据库
*/
public static DaoSession getDaoSession()
{ if (daoSessionDefault == null)
{
daoSessionDefault = getDaoMaster(MainApplication.getIns(), DATABASE_NAME).newSession();
}
return daoSessionDefault;
}
}
  • 可能我们还需要默认的greendao数据库进行其他的操作,至于默认的操作此处不再详细介绍,不了解的可以看greendao基本使用,此处我们演示的外部DB文件命名为school.db,默认的greenDao数据库命名为history.db,下面我们在MainActivity进行测试操作:
public class MainActivity extends Activity
{
private StringBuilder builder; @Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建默认的数据,并插入一条数据
HistoryDao historyDao = DBLocalController.getDaoSession().getHistoryDao();
History entity = new History();
entity.setName("科罗拉多");
entity.setImageUrl("http://www.baidu.com");
historyDao.insert(entity);
//拷贝外部DB文件到指定目录
copyRawDB();
//通过greendao查询外部db文件数据
selDBData();
} private void selDBData()
{
StudentDao student = DBController.getDaoSession(DBController.DATABASE_SCHOOL_NAME).getStudentDao();
List<Student> students = student.queryBuilder().list();
builder = new StringBuilder();
for (int i = ; i < students.size(); i++)
{
builder.append(students.get(i).getName() + "---");
}
Toast.makeText(MainActivity.this, builder.toString(), Toast.LENGTH_SHORT).show();
} private void copyRawDB()
{
try
{
// 拷贝res/raw/xxxxdb.zip 到
// /data/data/com.xinhang.mobileclient/databases/ 目录下面
boolean isSuccess = DBUtils.copyRawDBToApkDb(MainActivity.this, R.raw.schooldb, DBUtils.APK_DB_PATH, DBUtils.ECMC_DB_NAME, false);
}
catch (IOException e)
{
e.printStackTrace();
}
} }

运行结果:

可以看到我们的外部db文件已经拷贝到数据库默认路径下,还有我们的默认数据库也创建成功;区分两个数据库的方式是通过DBLocalController.getDaoSession(name)方法,想操作哪个数据库传入对应的数据库名称即可,gif操作图如下;


源码下载:源码下载,有问题欢迎交流讨论!

Android GreenDao操作外部DB数据库文件的更多相关文章

  1. Android虚拟机中的sqlite数据库文件

    Android虚拟机中的sqlite数据库文件 ①

  2. 查看Android下生成的.db数据库

    1.在cmd中找到sdk中的platform-tools文件夹. 2.输入adb shell命令. 3.再输入sqlite3 /data/data/com.svs.db/databases/svs.d ...

  3. android greendao的外部封装不太友好。

    https://github.com/greenrobot/greenDAO 下载下官网的示例,有完整的封装版本,但自已封装是碰到很多问题. 因greenDao的Master和Session中很多方法 ...

  4. Android 使用greenDAO 3.2.2 操作外部数据库

    项目开发中有时需要用到一些写死的数据,如公司的产品信息之类的.这就需要我们先把数据库文件保存在资源文件夹下,然后当应用创建时将数据库文件拷到应用安装目录的/databases/文件夹下,然后再对数据进 ...

  5. 通过adb shell操作android真机的SQLite数据库

    要通过命令行直接操作android真机上的SQLite数据库,可以直接通过adb shell来完成,不过,前提是必须获得root权限. 另外,android系统其实就是linux的shell,这个应该 ...

  6. Android下创建一个SQLite数据库

    数据库:SQLite(轻量级,嵌入式的数据库) 大量的相似结构的数据的储存,快速的查询.特殊的文件(按照一定的格式生成) 数据库的创建 创建文件 1.声明文件对象,文件是不会被创建出来的. File ...

  7. 【转】Phonegap离线调用SQLite数据库文件

    按:不可多得的好文章,转过来以免源丢失 文章来源:http://liuwei.co/index.php/default/The-quickest-way-to-execute-many-sql-for ...

  8. Android -- com.android.providers.media,external.db

    external.db android是管理多媒体文件(音频.视频.图片)的信息是在/data/data/com.android.providers.media下的数据库文件external.db. ...

  9. Android 查看和管理sqlite数据库

    在Android中可以使用Eclipse插件DDMS来查看,也可以使用Android工具包中的adb工具来查看.android项目中的sqlite数据库位于/data/data/项目包/databas ...

随机推荐

  1. python 抓取美丽说店铺的宝贝图片及详细信息的实现(爬虫)

    对于页面的抓取,我们使用的是requests,现在大部分的网站都支持动态加载,我们在firefox f12后查找动态的url :http://www.meilishuo.com/aj/shop_lis ...

  2. 九 Vue学习 manager页面布局

    1:  登录后系统页面如下: 对应代码: <template> <div class="manage_page fillcontain"> <el-r ...

  3. MVC4 @helper辅助方法

    Razor提供了一种很方便的语法,可以将view页面中部分内容或部分代码抽取出来,变成一个独立的辅助方法.   eg1: @foreach(var item in Model){ <标签tr&g ...

  4. keycode和which

    firefox 中不支持keyCode ie9-- 不支持which firefox:上下左右键会触发kepress. chrome: 上下左右键不会触发kepress. oprea:上下左右键不会触 ...

  5. Unity3D 自动添加Fbx Animation Event

    http://blog.csdn.net/aa20274270/article/details/52528449 using UnityEngine; using System.Collections ...

  6. 洛谷P3757 [CQOI2017]老C的键盘

    传送门 首先可以直接把整个序列建成一个完全二叉树的结构,这个应该都看得出来 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小 ...

  7. 洛谷P3750 [六省联考2017]分手是祝愿(期望dp)

    传送门 嗯……概率期望这东西太神了…… 先考虑一下最佳方案,肯定是从大到小亮的就灭(这个仔细想一想应该就能发现) 那么直接一遍枚举就能$O(nlogn)$把这个东西给搞出来 然后考虑期望dp,设$f[ ...

  8. c#根据身份证获取身份证信息

    /// <summary> /// 根据身份证获取身份证信息 /// 18位身份证 /// 0地区代码(1~6位,其中1.2位数为各省级政府的代码,3.4位数为地.市级政府的代码,5.6位 ...

  9. PJzhang:子域名发掘工具Sublist3r

    猫宁!!! 参考链接:https://www.freebuf.com/sectool/90584.html 作者上一次更新是2018年10月16日了,sublist3r中融合有另外一个子域名爆破工具S ...

  10. axios 跨域配置

    axios跨域设置 找到项目config文件夹下的index.js文件,将dev中的proxyTable项中添加配置 proxyTable: { '/api': { target: 'https:// ...