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