You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从Android设备提取Room数据库?物理文件创建与位置问询

Room数据库文件创建时机与位置详解

嘿,我来帮你理清这两个关键问题!

一、物理数据库文件何时创建?

Room采用懒加载机制,你调用myDatabase.getDatabase(getApplication())只是初始化了数据库的实例,并不会立刻创建物理文件。真正触发数据库文件创建的时机是:

  • 第一次执行任何数据库操作的时候,比如调用DAO的查询、插入、更新、删除方法,或者通过实例获取DAO对象后执行相关操作。
  • 简单说:只要你没真正和数据库交互(只是拿到实例),文件就不会生成。

二、数据库文件的位置

这个分两种情况,取决于你的应用是debug版本还是release版本,以及设备是否root:

1. Debug版本(模拟器/root真机/非root真机的debug包)

物理文件存放在应用的私有目录下,路径格式为:

/data/data/[你的应用包名]/databases/

里面会有3个相关文件(SQLite的特性):

  • [你的数据库名].db:主数据库文件
  • [你的数据库名].db-shm:SQLite共享内存文件
  • [你的数据库名].db-wal:SQLite写前日志文件

提示:导出的时候最好把这三个文件一起复制,否则可能出现数据不完整或者数据库无法打开的情况。

获取文件的方式:

  • 模拟器/Android Studio Device File Explorer:直接打开Android Studio右下角的Device File Explorer,找到对应路径,右键选择Save As导出到电脑。
  • 非root真机的debug包:用adb命令导出(电脑要装ADB工具):
    # 导出主数据库文件
    adb exec-out run-as com.your.package.name cat databases/your_db.db > ~/Desktop/your_db.db
    # 导出shm文件
    adb exec-out run-as com.your.package.name cat databases/your_db.db-shm > ~/Desktop/your_db.db-shm
    # 导出wal文件
    adb exec-out run-as com.your.package.name cat databases/your_db.db-wal > ~/Desktop/your_db.db-wal
    
  • root真机:直接用文件管理器(比如ES文件浏览器)访问上述路径复制即可。

2. Release版本(非root真机)

这个路径属于应用的私有目录,没有root权限的话无法直接访问。如果要导出,你需要在应用里添加代码,把数据库文件复制到外部存储(比如下载目录),然后再从手机的外部存储复制到电脑。

示例代码思路(简化版):

private void copyDatabaseToExternal() {
    try {
        File dbFile = getDatabasePath("your_db.db");
        File destFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "your_db.db");
        
        FileInputStream fis = new FileInputStream(dbFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        
        byte[] buffer = new byte[1024];
        int length;
        while ((length = fis.read(buffer)) > 0) {
            fos.write(buffer, 0, length);
        }
        
        fos.flush();
        fos.close();
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意:Android 10及以上需要适配Scoped Storage,或者在Manifest里添加android:requestLegacyExternalStorage="true"(仅临时兼容),同时要申请外部存储的读写权限。

额外小技巧:提前预填充数据库

如果你想在电脑上先填充好数据再用到应用里,其实不用手动复制文件,更方便的方法是:

  1. 在电脑上用SQLite管理器创建并填充好数据库文件。
  2. 将这个文件放到应用的assets/databases/目录下(没有就创建)。
  3. 在Room的数据库类里,修改@Database注解的构建器,添加createFromAsset方法:
@Database(entities = {YourEntity.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
    public abstract YourDao yourDao();
    
    private static volatile MyDatabase INSTANCE;
    
    public static MyDatabase getDatabase(final Context context) {
        if (INSTANCE == null) {
            synchronized (MyDatabase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                                    MyDatabase.class, "your_db.db")
                            .createFromAsset("databases/your_db.db") // 预加载assets里的数据库
                            .build();
                }
            }
        }
        return INSTANCE;
    }
}

这样应用第一次启动时,就会自动将assets里的预填充数据库复制到私有目录,不用手动操作啦!

内容的提问来源于stack exchange,提问作者Kev

火山引擎 最新活动