最近遇到的需要加载已有路径下(sd card下)db的问题,找了一下资料,以下是解决的方法,仅供参考(转载自eoe):

SQLiteOpenHelper 是Android框架为我们提供的一个非常好的数据库打开、升级与关闭的工具类。但是这个工具类会自动把db文件创建到“ /data/data/com.*.*(package name)/” 目录下,这么做可能是与Android文件系统的设计思路有关。

但 是在实战过程中,我们可能有各种原因需要自定义db文件路径(例如db文件较大放到sd卡更安全等等),相信很多人都遇到了这个需求,网上也有很多解决方 法,这些方法大多是抛弃Android框架为我们提供的SQLiteOpenHelper类,自己重头写一个DbHelper类完成自定义路径的数据库打 开关闭等。这么做虽然可以解决问题,但并不是一个最好的方法,因为自己写的DbHelper可靠性和功能自然难和google巨匠相。

本文提出一种方法,通过继承和添加代码,并复用SQLiteOpenHelper的代码,来解决自定义db路径的问题。


先我们来分析一下SQLiteOpenHelper的源代码。getReadableDatabase()和getWritableDatabase()
在内部都是调用getDatabaseLocked()。getDatabaseLocked()的源代码很容易理解,分析得知:

  • 如果以只读方式打开,是通过mContext.getDatabasePath(mName)来获取db文件的路径并使用SQLiteDatabase.openDatabase()直接打开数据库;

  • 果以读写方式打开,是通过mContext.openOrCreateDatabase(mName,
    mEnableWriteAheadLogging ? Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
    mFactory, mErrorHandler)打开或创建数据库。

所以我们需要改变mContext的行为。Android框架提供了一个ContextWrapper类,是Context的一个代理,可以通过继承的方式拉改变Context的行为,所以我们继承ContextWrapper,代码如下:

class CustomPathDatabaseContext extends ContextWrapper{
    private String mDirPath;

  public CustomPathDatabaseContext(Context base, String dirPath) {

    super(base);

    this.mDirPath = dirPath;

  }

  @Override

  public File getDatabasePath(String name) {

    File result = new File(mDirPath + File.separator + name);

    if (!result.getParentFile().exists()){

      result.getParentFile().mkdirs();

    }

    return result;

    }

    

  @Override

  public SQLiteDatabase openOrCreateDatabase(String name, int mode ,CursorFactory factory){

    return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);

  }

  

  @Override

  public SQLiteDatabase openOrCreateDatabase(String name,
int mode, CursorFactory factory, DatabaseErrorHandler errorHandler){

    return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(),
factory, errorHandler);

  }
  }

上述代码很简单了,就不用多说明了吧,然后我们在继承SQLiteOpenHelper时这么写就可以了:

class YourDbHelper extends SQLiteOpenHelper{

public YourDbHelper(Context context, String name, CursorFactory factory,
                        int version) {
                super(new CustomPathDatabaseContext(context, getDirPath()), name, factory, version);
        }

/**
         * 获取db文件在sd卡的路径
         * @return
         */
        private static String getDirPath(){
                //TODO 这里返回存放db的文件夹的绝对路径
                return "";
        }
        
        @Override
        public void onCreate(SQLiteDatabase db) {
        }

@Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
        
  }

如此一来,我们既可以自定义db文件路径,又可以复用SQLiteOpenHelper十分好用的功能了~

另外需要注意的是,有些应
用可能是有一个已建好表的db文件放在assets中,应用运行时先判断db文件是否存在,如果不存在则从assets中复制到自定义路径。这种情况通常
都是在PC端使用SQLiteSpy诸如此类的工具写sql建表,使用这种方法的小伙伴们别忘了在建表时执行  PRAGMA
schema_version = 1   这句sql(当然了版本号取决于您的需求) ,
否则SQLiteOpenHelper还是会触发onCreate的~看了SQLiteOpenHelper什么时候触发onCreate的源码就明白怎么回事了~

解决SQLite打开已有路径下的db问题的更多相关文章

  1. 痞子衡嵌入式:MCUXpresso IDE下添加新路径下源文件进工程编译的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下添加新路径下源文件进工程编译的方法. 接着上篇文章 <MCUXpresso IDE下SDK工程导入与 ...

  2. Excel Access 新建空白文档/打开已有文档 提示内存或磁盘空间不足的解决方法--验证

    服务器上发现,打开mdb数据库,点知道只有个空白的截面,打开已有的excel文件,一样,但多了个提示:内存磁盘空间不足或者关闭不再使用的工作表或者程序.检查过,内存和磁盘很充裕啊.那里不足啊,任务管理 ...

  3. 算法积累:解决如何获取指定文件夹路径或者文件路径下所有子文件后缀为.h .m .c的文本的行数

    1.先解决如何获取一个文件的代码行数 一开始对于这个问题,我的思路就回荡在:1字符串子字符串的判断 2循环直到结束的想法 3将原来是"\n"替换掉之类的想法 一个问题总会有多种解决 ...

  4. 解决eclipse部署maven时,src/main/resources里面配置文件加载不到webapp下classes路径下的问题

    解决eclipse部署maven时,src/main/resources里面配置文件加载不到webapp下classes路径下的问题. 有时候是src/main/resources下面的,有时候是sr ...

  5. unity Android在streamingAssets路径下文件无法读取的的解决方法

    unity Android在streamingAssets路径下文件,有时候plugin下的.jar或者.so无法直接读取: 解决方法之一,拷贝至其他路径: #if UNITY_ANDROID str ...

  6. 如何使用eclipse打开已有工程

    在开始使用Eclipse的时候,会发现一个问题,那就是如何打开一个现有的Eclipse工程,开始在菜单中找了好久也没找到. 其实,Eclipse生成的结果不像VC,Jcreator那样可以直接打开,若 ...

  7. 打开已存在 Android项目及常见的问题

    Eclipse 打开已存在 Android项目及常见的问题   1.  点击菜单“File”-- "Import",会弹出 Import 对话框:   2,  选择“General ...

  8. 指定路径下建立Access数据库并插入数据

    今天刚刚开通博客,想要把我这几天完成小任务的过程,记录下来.我从事软件开发的时间不到1年,写的不足之处,还请前辈们多多指教. 上周四也就是2016-04-14号上午,部门领导交给我一个小任务,概括来讲 ...

  9. 解决*.props打开失败问题

    由于不同机器的绝对地址不一样,可能会出现解决*.props打开失败问题,解决方向如下: 1.找到这里缺失的.props文件,复制到固定路径下: 2.强行打开代码,这个时候是报错的 3.选择编辑 4.将 ...

随机推荐

  1. [转] Kubernetes集群安装文档-v1.6版本

    [From] https://www.kubernetes.org.cn/1870.html http://jimmysong.io/kubernetes-handbook

  2. 关于jstl taglib的错误 Can not find the tag library descriptor for “http://java.sun.com/jstl/core”

    在查了N个帖子之后,决定记录一下关于jstl taglib的配置方法. 首先我遇到的错误是: Can not find the tag library descriptor for "htt ...

  3. 将Eclipse的Java Project转换为Dynamic Web Project

    在用Eclipse做JavaEE开发时经常遇到Web工程被识别为Java工程的问题,导致很多功能无法使用. 只需做以下操作便可解决该问题. 1.右击Java工程选择Properties 2.选择左边目 ...

  4. js请求数据的例子

    //es6实现方式 const getData = async ()=> { //同步请求数据 const res1=await this.$http.get("https://www ...

  5. mysql 数据库导入数据报错MySQL server has gone away解决办法

    mysql 数据库导入数据报错MySQL server has gone away解决办法: 进入数据库执行以下命令即可: set global wait_timeout = 2880000; set ...

  6. PIE SDK辐射定标

    1. 算法功能简介 辐射定标是使用大气纠正技术将影像数据的灰度值转化为表观辐亮度.表观反射率等物理量的过程. PIE支持算法功能的执行,下面对辐射定标算法功能进行介绍. 2. 算法功能实现说明 2.1 ...

  7. Yii2 执行Save()方法失败,却没有错误信息

    一般用$model->errors 就能查看到更新失败的原因,但是这次却什么错误信息都没有,最后发现是因为在模型类中定义了一个方法 public function beforeSave($ins ...

  8. eclipse中注释快捷键

    手动注释: ①类注释:Shift+Alt+J ②方法注释:在方法上方输入/** 后点击回车 自动注释:点击菜单栏上的Window -->Preferences-->Java-->Co ...

  9. (转) Linux Shell经典实例解析

    原文:http://blog.csdn.net/yonggeit/article/details/72779955 该篇博客作为对之前Linux Shell常用技巧和高级技巧系列博客的总结,将以Ora ...

  10. 关于kernel的疑问,不解

    (1)最近看的关于linux的部分主要是底层部分,linux对设备是如何访问,结果还是通过地址.机制差不错知道,下一步是阅读相关代码进一步理清内核,同时了解驱动的开发. 主要的疑问是对于高端内存映射, ...