Android 如何在非根安卓设备上检查数据库

Android 如何在非根安卓设备上检查数据库,android,sqlite,adb,android-contentprovider,android-sqlite,Android,Sqlite,Adb,Android Contentprovider,Android Sqlite,我正在开发一个应用程序,使用sqllite3数据库存储值。我有Nexus S和Nexus 7都是无根设备。如何获取应用程序的数据库以进行调试 我试过了 (1) 我已经尝试了所有提到的方法 这说明找不到cp (二) 您可以使用以下方法将数据库写入外部内存: private void writeToSD() throws IOException { File sd = Environment.getExternalStorageDirectory(); if (sd.canWrit

我正在开发一个应用程序,使用sqllite3数据库存储值。我有Nexus S和Nexus 7都是无根设备。如何获取应用程序的数据库以进行调试

我试过了 (1) 我已经尝试了所有提到的方法

这说明找不到cp

(二)


您可以使用以下方法将数据库写入外部内存:

private void writeToSD() throws IOException {
    File sd = Environment.getExternalStorageDirectory();

    if (sd.canWrite()) {
        String currentDBPath = DB_NAME;
        String backupDBPath = "backupname.db";
        File currentDB = new File(DB_PATH, currentDBPath);
        File backupDB = new File(sd, backupDBPath);

        if (currentDB.exists()) {
            FileChannel src = new FileInputStream(currentDB).getChannel();
            FileChannel dst = new FileOutputStream(backupDB).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
        }
    }
}
其中,
DB_NAME
是我的数据库的名称,
DB_PATH
定义如下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        DB_PATH = context.getFilesDir().getAbsolutePath().replace("files", "databases") + File.separator;
    }
    else {
        DB_PATH = context.getFilesDir().getPath() + context.getPackageName() + "/databases/";
    }
并添加以下权限(感谢@Sathesh指出这一点):


每当我写数据库时,我就会调用这个方法,这样我的最新数据库文件就在外部内存中,我可以从那里查看和调试它


然后,您可以使用从Android设备上的外部内存查看数据库

您无法访问非根设备上的/data文件夹


没有办法做到这一点。安卓有很好的安全机制。只有你的应用才能访问自己的文件

这不可能从非根目录电话进行。您无法访问/data目录,因此无法复制数据库或使用(2)中的sqlite应用程序。如果需要调试,请使用模拟器,或通过应用程序运行查询检查数据库。

如果不知道应用程序路径,则可以使用以下方法:

public void copyAppDbToExternalStorage() throws IOException {
    File sd = Environment.getExternalStorageDirectory();
    File currentDB = getApplicationContext().getDatabasePath("databaseName"); //databaseName=your current application database name, for example "my_data.db"
    if (sd.canWrite()) {
        File backupDB = new File(sd, "toDatabaseName"); // for example "my_data_backup.db"
        if (currentDB.exists()) {
            FileChannel src = new FileInputStream(currentDB).getChannel();
            FileChannel dst = new FileOutputStream(backupDB).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
        }
    }
}
public void copyAppDbToDownloadFolder() throws IOException {
    File backupDB = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "toDatabaseName"); // for example "my_data_backup.db"
    File currentDB = getApplicationContext().getDatabasePath("databaseName"); //databaseName=your current application database name, for example "my_data.db"
    if (currentDB.exists()) {
        FileChannel src = new FileInputStream(currentDB).getChannel();
        FileChannel dst = new FileOutputStream(backupDB).getChannel();
        dst.transferFrom(src, 0, src.size());
        src.close();
        dst.close();
    }
}
或者,如果您需要将数据库复制到公共“下载”文件夹,则可以使用以下方法:

public void copyAppDbToExternalStorage() throws IOException {
    File sd = Environment.getExternalStorageDirectory();
    File currentDB = getApplicationContext().getDatabasePath("databaseName"); //databaseName=your current application database name, for example "my_data.db"
    if (sd.canWrite()) {
        File backupDB = new File(sd, "toDatabaseName"); // for example "my_data_backup.db"
        if (currentDB.exists()) {
            FileChannel src = new FileInputStream(currentDB).getChannel();
            FileChannel dst = new FileOutputStream(backupDB).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
        }
    }
}
public void copyAppDbToDownloadFolder() throws IOException {
    File backupDB = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "toDatabaseName"); // for example "my_data_backup.db"
    File currentDB = getApplicationContext().getDatabasePath("databaseName"); //databaseName=your current application database name, for example "my_data.db"
    if (currentDB.exists()) {
        FileChannel src = new FileInputStream(currentDB).getChannel();
        FileChannel dst = new FileOutputStream(backupDB).getChannel();
        dst.transferFrom(src, 0, src.size());
        src.close();
        dst.close();
    }
}

这在我的Nexus 4设备上运行得非常好。

我只是需要做一些类似的事情,而且有一种方法可以做到,尽管这很痛苦。您需要将文件cat作为应用程序的用户帐户,然后通过管道将其传输到可写位置。这在运行4.3.3的Nexus 4上对我起了作用:

adb shell "run-as org.your.application cat /data/data/org.your.application/your-file > /mnt/sdcard/your-file"
adb pull /mnt/sdcard/your-file

以下解决方案仅适用于可调试的应用程序。它可能无法在所有设备上正常工作,因为​​run-as命令在某些设备上不起作用,尤其是在Jelly Bean上

  • ​创建一个*.bat文件并复制以下脚本​​

    adb shell以[package]chmod 777/data/data/[package]/databases/

    adb shell以[package]chmod 777/data/data/[package]/databases/[db\u file\u name]的形式运行。

    adb shell以[package]cp/data/data/[package]/databases/[db\u file\u name]/sdcard/

    adb pull/sdcard/[db\u文件名]

  • ​将[package]更改为所需的应用程序包

  • 将[db_file_name]更改为所需的db名称并运行bat文件 您应该可以在与bat相同的文件夹中看到复制的数据库 文件

  • 上述解决方案假设:

    • 您正在Windows上工作
    • 设备已连接,并且在下可见 “亚洲开发银行设备”

    尝试使用facebook开发的stetho库,它使您能够通过web浏览器查看数据库


    在Xamrin.forms中,我必须将数据库替换为文件

    这里有一个非常简单明了的答案:(在Android one上测试:无根

    现在将数据库拉到默认的adb路径

    adb -d pull /sdcard/mydatabase.db
    
    或者,到您的桌面,例如

    adb -d pull /sdcard/mydatabase.db C:\Users\user\Desktop
    
    您可能希望使用以下命令删除副本:

    adb -d shell "rm /sdcard/mydatabase.db"
    
    -d
    选项选择具有多个仿真器的默认设备

    如果在运行之后

    adb shell "run-as your.package.name"
    
    您收到“runas:Package'your.Package.name'未知”,然后尝试从emulator获取数据库。请看这里:

    在Android Studio 3.0中,单击视图>工具窗口>设备文件资源管理器。
    展开/data/data/[package name]节点。

    我认为这是最简单的方法。将此依赖项添加到gradle文件:debugImplementation'com.amitshekhar.android:debug db:1.0.0'

    在此之后,当您将在控制台中启动应用程序时,您可以看到以下消息: D/DebugDB:在浏览器中打开



    这就是你的数据库。

    你仍然可以将数据库复制到/data之外的某个地方并在那里查看它…+1当设备未根目录且应用程序处于非调试模式时,很难获取应用程序数据。。。即使使用
    run as
    its也会失败…您仍然可以将数据库复制到/data之外的某个地方并在那里查看它…@TronicZomB True您可以从应用程序中执行此操作,但有时您无法修改源代码。因为OP可以修改源代码,所以您的答案是最好的。对,如果是其他人的应用程序,则无法查看数据库。您需要添加外部存储权限。您可以使用“context.getDatabasePath(dbName).toString()”以编程方式获取dbpath。我正在获取原始DB文件的未找到文件异常。我有一个无根的Nexus4。我已经交叉检查了路径。@geekoraul您确定您的调用中的数据库名称和路径正确吗?非常确定。我甚至在ADB shell上通过run-as命令浏览应用程序目录来检查它。我还更改了原始数据库的权限file@geekoraul这很奇怪。。。听起来该文件不在您认为的位置,或者似乎不太可能创建该文件……数据库文件存储在/data/data//databases/中,也使用
    cat
    ,编写了一个空白文件。我使用了
    cp
    来让它工作。这也只适用于调试版本。尝试以发布版本的形式运行会导致
    运行方式:包“”不可调试
    这是一个有效的解决方案,如果您遵循所有3条注释,我现在可以在Nexus 5X上使用!太糟糕了OP不更新答案,否则我会+1它。。。感谢前三位评论员@Ted Mielczarek,如果你更新答案,你会得到当之无愧的回答。我不确定是否有增加的安全更改,但这会导致SD卡文件为零字节,因为某种原因,当我在android上尝试时,请检查我的答案,这将解决你的问题。我如何找到db_文件名。它说没有这样的文件或文件directory@SergeyDirin您需要将名称更改为您在应用程序中设置的实际文件名。在我的情况下,数据库是loca
    adb -d pull /sdcard/mydatabase.db C:\Users\user\Desktop
    
    adb -d shell "rm /sdcard/mydatabase.db"
    
    adb shell "run-as your.package.name"