在设备上调试sqlite数据库

99

我目前正在为Android开发一个WiFi应用程序。我在尝试访问设备上的数据库时遇到了麻烦。在模拟器中进行调试对我来说行不通,因为模拟器中没有WiFi支持。我尝试使用拉取数据库文件从设备中提取出数据库文件。

adb pull data/data/package-name/databases/database-name

但是我遇到了“权限被拒绝”的错误。 在这个答案Android: Where are database files stored?中,Commonsware建议通过在调试模式下运行来拉取数据库文件。但这也不起作用。如何在不root设备的情况下调试数据库,任何帮助都将不胜感激。
17个回答

2
如果一个apk是可调试的,那么可以使用非root的adb shell中的run-as程序来复制应用程序的私有文件。

1

我的设备没有SD卡

因此第一个解决方案对我无效。
如果您遇到类似的问题,请尝试以下方法:
  adb shell "run-as package chmod 777 /data/data/package/databases/yourdb.sqlite";
  adb pull /data/data/package/databases/yourdb.sqlite

“/sdcard” 不一定是指SD卡。在我的手机上,当没有插入物理SD卡时,它指向内部存储。 - DearVolt

1

我曾经尝试过这个。但它会给我一个“在正式版本中adb不能以root身份运行”的错误提示。 - Primal Pappachan
你需要在调试模式下运行它。 - Malfist
请查看此链接:http://www.mydroidworld.com/forums/android-hacks/5508-adb-help-needed-adbd-cannot-run-root-production-builds.html 如果您在手机上运行而不是模拟器上运行,您将需要对其进行root。 - Malfist
我以调试模式运行了该应用程序,并尝试了上述步骤。但它并没有起作用。 - Primal Pappachan
这仅适用于模拟器或已获取 root 权限的设备。 - slott
如果你遇到了“run-as: unknown package”的错误,请仔细检查你在build.gradle文件中设置的applicationId。那个值决定了“package” ID,而不是代码中实际包名。 - Carl Rossman

1
没有一个run-as-and-cat-to-sdcard 的解决方案适用于我的Android 4.4.2。我不确定,但我怀疑可能是由于run-as工具没有正确处理新的sdcard_rsdcard_rw权限所致。
我首先必须将数据库文件复制到应用程序私有内部存储中的/files
shell@hammerhead:/ $ run-as com.example.myapp   
shell@hammerhead:/data/data/com.example.myapp $ cp databases/mydb files/mydb

然后我将其复制到Javaland中的/sdcard/Android/data/com.example.myapp/files(这需要WRITE_EXTERNAL_STORAGE权限):

public class MainActivity extends BaseActivity {

    @Override
     protected void onCreate(Bundle savedInstanceState) {
         ...

         if (isExternalStorageWritable()) {
             final FileInputStream input;
             try {
                 input = openFileInput("mydb");

                 File output = new File(getExternalFilesDir(null), "mydb");

                 copy(input, output);
             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }

     public void copy(FileInputStream in, File dst) throws IOException {
         OutputStream out = new FileOutputStream(dst);

         // Transfer bytes from in to out
         byte[] buf = new byte[1024];
         int len;
         while ((len = in.read(buf)) > 0) {
             out.write(buf, 0, len);
         }
         in.close();
         out.close();
     }

     public boolean isExternalStorageWritable() {
         String state = Environment.getExternalStorageState();
         return Environment.MEDIA_MOUNTED.equals(state);
     }
 }

最后,我将文件复制到了我的笔记本电脑上:

$ adb pull /sdcard/Android/data/com.example.myapp/files/mydb

1
有一个更简单的解决方案。如果你将你的sqlite文件chmod 777,然后退出run-as,它会让你将它作为常规用户复制到/sdcard上。 - zedix

0

在OSX上,使用@Tadas的答案和automator以及sqllitebrowser(https://github.com/sqlitebrowser/sqlitebrowser):

  1. 打开Automator并创建新的工作流程。

  2. 添加“运行Shell脚本”操作。

  3. 粘贴以下内容:

    source ~/.bash_profile adb shell 'run-as cat /data/data/your_app_uid/databases/db.name > /tmp/db.name' adb pull /tmp/db.name ~/ open -a sqlitebrowser ~/db.name

  4. 点击运行以刷新sqlitebrowser上的数据库。


0
  1. 打开终端
  2. cd <ANDROID_SDK_PATH>(对于我在Windows上的路径是cd C:\Users\Willi\AppData\Local\Android\sdk
  3. cd platform-tools
  4. adb shell(仅当只有一个模拟器正在运行时才有效)
  5. cd data/data
  6. su(获取超级用户权限)
  7. cd <PACKAGE_NAME>/databases
  8. sqlite3 <DB_NAME>
  9. 发出SQL语句(重要:;结尾,否则语句不会被执行并且会换到新行。)

注意:如果需要列出目录内容,请使用ls(Linux)或dir(Windows)。


0

试试这个应用程序:SQLiteWeb(https://play.google.com/store/apps/details?id=br.com.cm.sqliteweb)。它可以远程访问您的数据库,而无需将其提取出来。

在付费版本中,它具有私有数据库(/data/data/package-name...)的根访问权限,或者实现内容提供程序以使用SQLiteWeb进行连接(应用程序内有说明)

但是,如果想要使用免费版本,您可以在外部存储器中创建您的数据库:

database = SQLiteDatabase.openDatabase(Environment.getExternalStorageDirectory()
        + "/" + DATABASE_NAME, null, DATABASE_VERSION);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接