99

I am presently working on an WiFi application for Android. I am having trouble trying to access the database on the device. Debugging in the emulator doesn't work for me, because there is no WiFi support in the emulator. I tried pulling the database file out of the device by using

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

But I get the error "Permission denied.". In this answer Android: Where are database files stored?, Commonsware has suggested to pull database file by running in debug mode. But it doesn't work too. Any help on how to debug the database without rooting the device would be much appreciated.

Community
  • 1
  • 1
Primal Pappachan
  • 25,857
  • 22
  • 67
  • 84

17 Answers17

143

I'll repeat myself from another answer:

Starting from API level 8 (Android 2.2), if you build the application as debuggable, you can use the shell run-as command to run a command or executable as a specific user/application or just switch to the UID of your application so you can access its data directory.

Copy files to external storage on the device

So if you wish to pull your application database from the device you can launch a debug build of the application from Android Studio, connect with adb shell and run the following command:

run-as com.your.package sh -c "cat ~/databases/db-file.db" > /sdcard/db-file.db

or you can use a shorter version which uses relative paths and by skipping the reference to the home directory ~ can omit the sh -c part too:

run-as com.your.package cat databases/db-file.db > /sdcard/db-file.db

This will copy your db-file.db to the root of your SD card / external storage. Now you can easily get it from there by using file manager, adb pull or whatever else you like. Note that with this approach, there is NO need for your app to have WRITE_EXTERNAL_STORAGE permission, as the copying is done by the shell user who can always write to the external storage.

Copy files directly to the computer

You can also copy a database directly to your computer with the following command:

adb shell 'run-as com.your.package cat databases/db-file.db' > db-file.db

The adb shell command above will not work correctly on Windows host because of the CR/LF symbols conversion, unless you run it from a bash shell or use the undocumented adb exec-out command instead (some comments mention they still cannot get it to work correctly on a Windows machine, so your mileage may vary):

adb exec-out 'run-as com.your.package cat databases/db-file.db' > db-file.db

Write files back to the device

If you modified the file on your computer and wish to write the modifications back to the device use the following command:

adb exec-in 'run-as com.your.package tee databases/db-file.db' < db-file.db

or if you prefer an adb shell version over undocumented exec-in, use the following (but read the concern about the Windows CR/LF conversion above):

adb shell 'run-as com.your.package tee databases/db-file.db' < db-file.db >/dev/null
Status update

All the commands above are still working as of July, 2023

Volo
  • 28,673
  • 12
  • 97
  • 125
  • @Idolon, I tried this answer and was able to download the database but now when I try and open it with sqlite it give me the error "Error: file is encrypted or is not a database". Any ideas how I can fix it and access through sqlite? – MikeIsrael Apr 09 '12 at 11:08
  • 1
    @MikeIsrael Just in case, you don't use SQLCipher in your app do you? If not, then to roughly check whether the database was downloaded correctly open the DB file in a viewer (preferably a hex-viewer) and check whether it starts with `SQLite format 3` string. Also make sure you have a correct `sqlite` version (i.e. you're not trying to open sqlite3 database with sqlite2 executable). And you may also try other SQLite clients (for example [SQLiteStudio](http://sqlitestudio.one.pl/)). Hope it helps. – Volo Apr 12 '12 at 09:53
  • You made my day @Idolon! A little improvement to your answer: android:debuggable="true" is not needed, it's the default AFAIK in the manifest. I've just typed run-as and cat in my adb shell and worked perfectly, without android:debuggable in the manifest – Jose_GD Jul 02 '12 at 19:02
  • @Jose_GD Yes, you're right - [android:debuggable is set automatically](http://stackoverflow.com/a/5701672/648313) by the Eclipse ADT plugin. – Volo Jul 10 '12 at 13:50
  • 1
    I'm having trouble with the one liner. It works fine if I run the command in a shell but if I put in the one liner I get: The system cannot find the path specified. – Rev Tyler Oct 07 '12 at 20:48
  • 2
    package is unknown... anyone know why. I installed via studio by pressing the debug button. – Nathan Schwermann Oct 22 '14 at 19:12
  • @schwiz There is a known bug in Android 4.3: https://code.google.com/p/android/issues/detail?id=58373. And few workarounds, for example making [run-as set-uid root](https://code.google.com/p/android/issues/detail?id=58373#c41), `/data/…` folders permission changes may also be required: [post #60](https://code.google.com/p/android/issues/detail?id=58373#c60) – Volo Oct 22 '14 at 20:31
  • 4
    On Android Lollipop i'm getting `permission denied` – Muhammad Babar Feb 05 '15 at 17:33
  • @MuhammadBabar I get that on Lollipop too. Managed to get a semi-accessible database by catting it through the adb link and writing to a file on the local computer. Like `adb shell 'run-as myapp cat /data/data/myapp/databases/dbname.db' > ~/dbname.db` Something's kind of wrong with that, but I'm not sure what yet. – Mason Feb 09 '15 at 05:11
  • @Mason thanks but you said you managed to get it and then you are saying something's wrong. I'm confused :? – Muhammad Babar Feb 09 '15 at 09:50
  • 1
    I pulled a database with two tables and a dozen or so rows in each, and did full select queries on each table. One worked fine, the other reported a data error in the file. My best guess right now is an encoding mismatch between the Android and local shell. – Mason Feb 09 '15 at 18:44
  • @Mason Is your phone rooted? I'm still getting `permission-denied` & `read-only-filesystem` error :( – Muhammad Babar Feb 11 '15 at 14:41
  • @MuhammadBabar Nope, if it was rooted, I could just do a pull of the file I wanted. Try running the commands from a adb shell, and make sure the run-as command works, and that your app is built in debug mode. – Mason Feb 12 '15 at 01:24
  • @Mason i already did run in adb shell and the command is working. The apk is debugged with eclipse using debug.keystore. Is your device 5.0.1? – Muhammad Babar Feb 12 '15 at 10:09
  • I am also having the same problem but not on lollipop but on Android 4.0.4. Any ideas on what I am doing wrong? – Neon Warge Mar 12 '15 at 15:22
  • Not sure if this is it, but keep in mind you are doing your 'cat' in context of your app. Make sure your has WRITE_EXTERNAL_STORAGE permission. – Tom May 14 '15 at 16:32
  • If for some reason you are like me getting an error stating `Device not found`: Simply replace the `-d` with `-s `. `` needs to be replaced by the device id given in the left column in the output of `adb devices`. This happened to me while using a virtual genymotion device. – olik79 Jul 06 '15 at 13:47
  • mine needed to have quotes: `adb -d shell "run-as com.yourpackage cat /data/data/com.yourpackage/databases/dbname.sqlite > /sdcard/dbname.sqlite"` – danfolkes Feb 27 '17 at 19:57
  • `adb shell 'run-as com.yourpackage sh -c "cat ~/databases/db-file"' > db-file.sqlite` is not going to work regardless of the host OS. see my explanation here https://stackoverflow.com/a/13587203/1778421 – Alex P. Jul 09 '17 at 21:17
  • also why do you keep insisting on using the unnecessary `sh -c "cat file"` construct? https://stackoverflow.com/a/18472135/1778421 is much cleaner. – Alex P. Jul 09 '17 at 21:21
  • By running bash on windows cmd, the linux and mac command at the bottom of this answer can also be used. – T.Woody Aug 02 '18 at 18:50
23

I use this shell script on my MAC, that copies database directly to my home folder. Easy one click solution, just change package name (com.example.app) and database name (database.sqlite)

Simple Script

#!/bin/bash
adb -d shell 'run-as com.example.app cat /data/data/com.example.app/databases/database.sqlite > /sdcard/database.sqlite'
adb pull /sdcard/database.sqlite ~/

Script which accepts arguments [package_name] [database]

#!/bin/bash

REQUIRED_ARGS=2
ADB_PATH=/Users/Tadas/Library/sdk/platform-tools/adb
PULL_DIR="~/"

if [ $# -ne $REQUIRED_ARGS ]
    then
        echo ""
        echo "Usage:"
        echo "android_db_move.sh [package_name] [db_name]"
        echo "eg. android_db_move.sh lt.appcamp.impuls impuls.db"
        echo ""
    exit 1
fi;


echo""

cmd1="$ADB_PATH -d shell 'run-as $1 cat /data/data/$1/databases/$2 > /sdcard/$2' "
cmd2="$ADB_PATH pull /sdcard/$2 $PULL_DIR"

echo $cmd1
eval $cmd1
if [ $? -eq 0 ]
    then
    echo ".........OK"
fi;

echo $cmd2
eval $cmd2

if [ $? -eq 0 ]
    then
    echo ".........OK"
fi;

exit 0
Tadas Valaitis
  • 870
  • 10
  • 11
  • The first command was creating a zero-byte copy of the database, so I made some adjustments in your script: https://gist.github.com/romulof/6af8a8919660f395f975 – romulof May 16 '15 at 05:49
15

The best way to view and manage you android app database is to use this library https://github.com/sanathp/DatabaseManager_For_Android

With this library you can manage your app SQLite database from you app itself. you can view the tables in your app database , update ,delete, insert rows to your tables .Everything from your app.

Its a single java activity file ,just add the java file to your source folder.When the development is done remove the java file from your src folder thats it .

It helped me a lot .Hope it helps you too .

You can view the 1 minute demo here : http://youtu.be/P5vpaGoBlBY

sanath_p
  • 2,198
  • 2
  • 26
  • 22
13

Although, it's an old question I think it's still relevant and deserves a current state answer. There are tools available, which allow you to inspect databases directly (without the need to pull them from the device or emulator).

The tool, I most recently discovered (and favor most) is Android Debug Database.

You only need to add this dependency:

debugImplementation 'com.amitshekhar.android:debug-db:1.0.3'

No further code is required. After you started your app, open logcat and filter for "DebugDB" and you will find a message saying

D/DebugDB: Open http://192.168.178.XXX:8080 in your browser

It works with every browser and you can inspect your database tables and shared preferences.

enter image description here

It also works with the default and the Genymotion emulators.


The tool I used before is stetho.

Downside: You need to add a bit of code and you are bound to the Chrome browser.

Advantage: You have the option to also inspect network traffic.

Peter F
  • 3,633
  • 3
  • 33
  • 45
6

In the new Android Studio 4.1 there is the new Database Inspector.

https://i.ibb.co/9tNM1xg/database-Inspector.gif

You can select the following options from the menu bar View > Tool Windows > Database Inspector to open it (App Inspector in Android Studio 4.2). More detailed instructions can be found in this blog and in Exploring the Database Inspector in Android Studio medium article.

Another way is to use stetho for this. You add the dependency and then can use the Chrome DevTools ( chrome://inspect ) to check the database when the device is plugged in.

jeprubio
  • 17,312
  • 5
  • 45
  • 56
5

If you get

The system cannot find the path specified.

try

adb -d shell "run-as com.yourpackage cat /data/data/com.yourpackage/databases/dbname.sqlite > /sdcard/dbname.sqlite"

Note the double quote!

Gerold Meisinger
  • 4,500
  • 5
  • 26
  • 33
5

In my application I export the database to the SD card. Once the database is on the SD card it can be accessed by plugging the device into your computer.

Look at this post: Making a database backup to SDCard on Android

Community
  • 1
  • 1
3

I simply did:

$ adb shell
shell@android:/ $ run-as myapp.package.name sh
shell@android:/data/data/myapp.package.name $

Then I can debug an sqlite database or whatever I wanna do from shell with the right permissions.

smichak
  • 4,716
  • 3
  • 35
  • 47
3

Android Studio 4.1 Added a new feature to view/ edit Android SQLite databases.

enter image description here

How to open Database Inspector

To open the Database Inspector in Android Studio, you need to select View > Tool Windows > Database Inspector from the menu bar.

Also you need to run the app to a device running API level 26 or higher.

Using this tool you can

  • Query your databases

  • Modify and debug your database

enter image description here

Darish
  • 11,032
  • 5
  • 50
  • 70
2

Here is step by step instructions - mostly taken from a combination of the other answers. This works with devices that are not unlocked.

  1. Connect your device and launch the application in debug mode.

  2. Copy the database file from your application folder to your sd card: execute:

    ./adb -d shell 'run-as com.yourpackge.name cat /data/data/com.yourpackge.name/databases/filename.sqlite > /sdcard/filename.sqlite'

  3. Pull the database files to your machine: execute:

    ./adb pull /sdcard/ execute: ./adb

  4. Install Firefox SQLLite Manager: https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/

  5. Open Firefox SQLLite Manager and open your database file from step 3 above.

  6. Enjoy!

Andy Cochrane
  • 2,409
  • 1
  • 18
  • 16
2

There is a way if an apk is debuggable to use a program called run-as from the (non-root) adb shell to copy an application's private file.

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117
1

None of the run-as-and-cat-to-sdcard solutions worked for me on Android 4.4.2. I'm not sure, but I suspect it may be due to the run-as tool not correctly handling the new sdcard_r and sdcard_rw permissions.

I first had to copy the database file to /files in my application's private internal storage:

shell@hammerhead:/ $ run-as com.example.myapp   
shell@hammerhead:/data/data/com.example.myapp $ cp databases/mydb files/mydb

Then I copied to /sdcard/Android/data/com.example.myapp/files in Javaland (this requires the WRITE_EXTERNAL_STORAGE permission):

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);
     }
 }

Finally, I copied the file to my laptop:

$ adb pull /sdcard/Android/data/com.example.myapp/files/mydb
user167019
  • 567
  • 1
  • 5
  • 10
  • 1
    There's a simpler solution. If you chmod 777 your sqlite file, then exit run-as, it'll let you copy it over to /sdcard as the regular usre. – zedix Aug 18 '14 at 01:19
1

My Device was not having sdcard

so the first solution did not work for me.

If you are having similar issue try like this:

  adb shell "run-as package chmod 777 /data/data/package/databases/yourdb.sqlite";
  adb pull /data/data/package/databases/yourdb.sqlite
dsharew
  • 10,377
  • 6
  • 49
  • 75
  • `/sdcard` isn't necessarily an SD card. On my phone it points to internal storage when no physical SD card is present. – DearVolt Jul 07 '17 at 12:11
1

You need to be running adb as root, or be using it on a rooted phone.

To run adb as root, use adb root

See also: Why do I get access denied to data folder when using adb?

Community
  • 1
  • 1
Malfist
  • 31,179
  • 61
  • 182
  • 269
0

Try this app: SQLiteWeb (https://play.google.com/store/apps/details?id=br.com.cm.sqliteweb). It provides remote access to your database without pulling it out.

In paid version, it has root access for private database (/data/data/package-name...) or implement a Content Provider to connect using SQLiteWeb (Instructions inside app)

But if want to stay with the free version, you may create your database in external storage:

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

On OSX,using @Tadas answer with automator and sqllitebrowser(https://github.com/sqlitebrowser/sqlitebrowser):

  1. open Automator and create new workflow.

  2. add "Run Shell Script" action.

  3. Paste this :

    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. click run to refresh the database on sqlitebrowser.

Zaster
  • 860
  • 7
  • 6
0
  1. Open up a terminal
  2. cd <ANDROID_SDK_PATH> (for me on Windows cd C:\Users\Willi\AppData\Local\Android\sdk)
  3. cd platform-tools
  4. adb shell (this works only if only one emulator is running)
  5. cd data/data
  6. su (gain super user privileges)
  7. cd <PACKAGE_NAME>/databases
  8. sqlite3 <DB_NAME>
  9. issue SQL statements (important: terminate them with ;, otherwise the statement is not issued and it breaks to a new line instead.)

Note: Use ls (Linux) or dir (Windows) if you need to list directory contents.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121