Android把数据库保存到sdcard

作者: 花开堪折枝 | 来源:发表于2016-06-07 23:23 被阅读772次

前言

有时候我们想把用户的一些数据存储在sdcard里面,因为sdcard里不会因为用户卸载数据被删除或用户用系统自带的清除,但是同样我们自己需要注意添加以下数据清除,这个不是属于现在要讨论的东西。文件什么保存都是很容易的了,但是数据库系统没有提供,默认是保存在当前应用下面的,但是我们还是可以通过一些手段把它保存到sdcard里面的。

查看源码,一切秘密都展现到你的面前

第一种 修改数据库保存根路径

通过查看 SQLiteOpenHelper 创建数据库的代码如下,发现两个关键的地方

  • mContext.getDatabasePath(mName).getPath()
  • db = mContext.openOrCreateDatabase(mName, ...
    跟踪进去看看,一看是什么鬼,怎么都是空的实现。这里就不具体说了,有兴趣的可以看看Android Context的设计。
    同时我们发现 ContextWrapper 继承 Context , 而 Application又继承 ContextWrapper , 而 Context 真正的实现在 ContextImpl 中,源码路径: /frameworks/base/core/java/android/app/ContextImpl.java
                try {
                    if (DEBUG_STRICT_READONLY && !writable) {
                        final String path = mContext.getDatabasePath(mName).getPath();
                        db = SQLiteDatabase.openDatabase(path, mFactory,
                                SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                    } else {
                        db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
                                Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
                                mFactory, mErrorHandler);
                    }
                } catch (SQLiteException ex) {
                    if (writable) {
                        throw ex;
                    }
                    Log.e(TAG, "Couldn't open " + mName
                            + " for writing (will try read-only):", ex);
                    final String path = mContext.getDatabasePath(mName).getPath();
                    db = SQLiteDatabase.openDatabase(path, mFactory,
                            SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                }

创建数据库文件,在我再重新看一遍源码的时候,我竟然发现系统是提供了自定义存储的方法的,注代码里面注释。为啥以前查出来那么多变种的答案呢。

    private File validateFilePath(String name, boolean createDirectory) {
        File dir;
        File f;
        //数据库名字如果以 / 开头,会自动截取到最后一个 /当作文件存储的文件夹
        if (name.charAt(0) == File.separatorChar) {
            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
            dir = new File(dirPath);
            name = name.substring(name.lastIndexOf(File.separatorChar));
            f = new File(dir, name);
        } else {
            dir = getDatabasesDir();
            f = makeFilename(dir, name);
        }

        if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
            FileUtils.setPermissions(dir.getPath(),
                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
                -1, -1);
        }

        return f;
    }

第二种 重写了SQLiteOpenHelper

项目地址: android-sdcard-helper

据就是重新 getWritableDatabasegetReadableDatabase ,创建数据库使用 SQLiteDatabase.openOrCreateDatabase, 默认打开数据库是打开读写的,但是有一点需要注意的。在sdcard存储满的时候,读写的数据库是打不开的,但是可以打开只读的数据库,所以我们默认打开的数据库都是读写,有两个原因:

  • 如果打开一个只读的,文件可能会被锁住,再打开读写的会失败
  • 只读的数据库转读写的是一个 hide 方法,这里无法调用

最后了,感觉自己需要一点反思。如果好好的看一下相关的代码可能就不需要再重新造一个轮子了,但是还是有一些应用场景的。

谢谢阅读到这里,觉得好的点个赞吧 _

相关文章

网友评论

    本文标题:Android把数据库保存到sdcard

    本文链接:https://www.haomeiwen.com/subject/xgoddttx.html