122

On a non-rooted android device, I can navigate to the data folder containing the database using the run-as command with my package name. Most files types I am content with just viewing, but with the database I would like to pull if from the android device.

Is there a download copy or move command from this part of adb shell? I would like to download the database file and view its content using a database browser.

One answer here involves turning entire application package into a compressed archive, but there is no further answer on how to extract that archive once this is done and moved to the machine, leaving me very sidetracked when there might be a more direct solution to begin with

Alex P.
  • 30,437
  • 17
  • 118
  • 169
CQM
  • 42,592
  • 75
  • 224
  • 366

12 Answers12

251

By design user build of Android (that's what you have on your phone until you unlock the bootloader and flash the phone with userdebug or eng software) restricts access to the Internal Storage - every app can only access its own files. Fortunately for software developers not willing to root their phones Google provides a way to access the Internal Storage of debuggable versions of their packages using run-as command.

To download the /data/data/debuggable.app.package.name/databases/file from an Android 5.1+ device run the following command:

adb exec-out run-as debuggable.app.package.name cat databases/file > file

To download multiple files in a folder under the /data/data/debuggable.app.package.name/ at once - use tar:

adb exec-out run-as debuggable.app.package.name tar c databases/ > databases.tar
adb exec-out run-as debuggable.app.package.name tar c shared_prefs/ > shared_prefs.tar
Alex P.
  • 30,437
  • 17
  • 118
  • 169
  • 9
    Or, just use `run-as` to copy the file to a spot on external storage, and pull the database file from there, rather than messing around with file permissions. – CommonsWare Jul 04 '14 at 11:02
  • 5
    The run-as has no permission to write to the sdcard - there is something new added with the latest update... :( – slott Jan 13 '15 at 11:09
  • 4
    When I run adb shell "run-as package.name chmod 666 /data/data/package.name/databases/file" adb ends me error -->run-as: exec failed for chmod666 Error:Permission denied . I'm in Nexus 7 without root – Shudy Jan 13 '15 at 12:02
  • 2
    Write access to external sd card is no longer possible with adb. – slott Jan 13 '15 at 13:40
  • 1
    Did you check if this depends on the permissions of the app you run as? – Arthur Dent Jan 13 '15 at 15:23
  • 2
    When transferring my database using "adb exec-out run-as package.name cat databases/file > file", I'm getting extra line-breaks (CR LF), making the file unreadable by sqliteman. Looks like the file is being copied as text rather than binary. Is there any way to fix it? – Gyum Fox Sep 23 '15 at 13:36
  • 1
    @GyumFox, double check Android version of your device. The whole purpose of `adb exec-out` is to run a `shell` command without `tty` so it would not mangle the output. – Alex P. Sep 23 '15 at 17:00
  • in case anyone else is confused about the "exec out" command: exec out makes the adb command running on your computer return whatever it is that the shell on Android "returns". That means that the pipe ( "> file" ) happens on your computer, not the Android device. "file" will then be a file in the current dir from where you ran the adb command on your computer. – treesAreEverywhere Sep 23 '15 at 22:00
  • So this *seems* to work for me, but the file that I get, is a few hundred bytes different in size. This is if I cat the output to my local shell. If I redirect the output of cat to a file on the device (e.g. "/sdcard/out.db", I get just a 0-byte-sized file. – treesAreEverywhere Sep 23 '15 at 22:39
  • @AlexP., I think the issue is with the cat command, which copies the content of the file as text, rather than binary – Gyum Fox Sep 24 '15 at 07:53
  • 1
    The only solution that worked for me. I mean the one for Android 5.0+ – Erik K. Mar 13 '16 at 21:59
  • This doesn't work for me because the cmd output is: File is in use by a different process. Is there a way around this? I'm running a service that constantly writes to the DB. But even if I deactivate the app, it does not work. Any help? – Spurious Nov 30 '16 at 15:37
  • @Spurious You might want to try going to Developer Options (on the phone) then Running Services, find your app/service and kill it from there. –  Dec 05 '16 at 01:48
  • @AlexP. The 5.0+ worked like a charm for me, but what if we have reverse situation and want to put db from our pc to application? I tried: adb exec-in run-as my.application cat mydbname.db > databases/intouchDatabase with no luck it just says 'The system cannot find the path specified.' I coulnd't find much about exec-in tbh, also i suspect it cannot find the mydbname.db location. – Tafari Feb 18 '17 at 09:57
  • @AlexP. I've already seen that post, it's not exactly reverse as you just move files from sdcard not the pc, when I'm trying following: _adb shell run-as my.application cp mydbname.db databases/mydb_ I am getting following response: _cp mydbname.db: No such file or directory_ – Tafari Feb 18 '17 at 17:07
  • @AlexP. I tried moving the db to sdcard with adb push mydbname.db /sdcard/mydbname.db and then using cp and now I am getting /sdcard/mydbname.db: Permission denied. I checked the permissions on sdcard and its -rwxrwx--- root (my phone is not rooted). I remember when I had older phone android 4.2.2 there were absolutely no problems with accessing stuff on sdcard. But when _adb pull /sdcard/mydbname mydbname_ it works without any problems. – Tafari Feb 18 '17 at 18:07
  • I am having trouble with the execution of the exec-out command on an Samsung device running 6.0. I get a plain text document file which a can't view with sqlitebrowser for example. Can anyone help? – Sandra Mar 01 '17 at 10:58
  • 4
    If you are finding that you are getting back a blank or nearly blank file, you may find that the file is simply an error from the console that has been redirected to this file that you have created. A frequent issue here is that you are trying to copy a DB from the Release variant of your app. **You can only copy DBs from the Debug variant of your app**. If this happens, just install the debug variant and try the command again. Hope this helps someone. – Aonghus Shortt Apr 14 '17 at 18:02
  • In my case `Marshamallow` it does not show any error, but file not found anywhere in internal sd card. where does it pull the file. Please help me out !!! – Rajeev Kumar Apr 17 '17 at 06:57
  • Not work for Windows 10 (64 bit), Android 6.0. File db pull from device but it's empty. – Alexei Jun 08 '17 at 14:43
  • Note run-as is broken on recent Samsung phones. Works great on pixel, LG, HTC, Sony, etc – Stan Kurdziel Mar 26 '18 at 21:50
  • 2
    Note that `adb exec-out` seems to capture stderr on the device and prints it to *stdout* locally. That means that if `tar` prints error messages (e.g. if you give it an absolute path), they'll end up in the generated `.tar` file and make it malformed. – jamesdlin Apr 16 '19 at 23:19
75

The accepted answer doesn't work anymore for me (blocked by Android?)

So instead I did this:

> adb shell
shell $ run-as com.example.package
shell $ chmod 666 databases/file
shell $ exit                                               ## exit out of 'run-as'
shell $ cp /data/data/package.name/databases/file /sdcard/
shell $ run-as com.example.package
shell $ chmod 600 databases/file
> adb pull /sdcard/file .
marmor
  • 27,641
  • 11
  • 107
  • 150
  • 3
    This should be the new correct answer OR @Alex P. you should add this answer for newer Android versions. Also in my case I had to use 777 and apply it to the database-directory first/as-well before I could access the db file. – muetzenflo Mar 31 '15 at 09:10
  • 1
    My device is rooted, but I found I still need to run `su` to get the `run-as` command working. – ThomasW Apr 09 '15 at 08:26
  • What if you don't have SD card? – Gyum Fox Sep 23 '15 at 12:19
  • 1
    if you don't have an SD card, there's still a "sdcard" directory anyways. – treesAreEverywhere Sep 23 '15 at 22:50
  • This is the new answer for 5.0+ Android Devices. If I could I would upvote this answer 5 times. – macio.Jun Nov 08 '15 at 01:03
  • Another solution that helps even for non-debuggable applications is described there: http://android.stackexchange.com/a/50411/96640. – Leos Literak Sep 10 '16 at 04:48
  • Can I create a db file outside a device, manually create 'databases' directory inside the device, and copy the db file into the directory? – ghchoi Jun 16 '17 at 01:53
  • you can, just use `run-as ` when you need to act in behalf of the app – marmor Jun 16 '17 at 09:54
  • 1
    Great!. it worked for me too. Can we make a batch/shell file? just passing db file name as param and we have the db file. – Qadir Hussain Aug 18 '17 at 11:09
  • By following these step i got the db file. But after that my app is getting crashed after some time in same device only. App is working perfectly in other devices. – Armaan Aug 23 '19 at 11:18
31

If anyone looking for pulling database from debug application may use the procedure below:

  1. search and open device file explorer

search and open device file explorer

  1. Select your handset and then browse to data/data directory

go to data/data directory

  1. Now find your application package and go to databases folder. You can see the databases there and upon right click, you will get option to save this in your drive.

enter image description here

Ifta
  • 1,536
  • 18
  • 25
9

I've published a simple shell script for dumping databases:

https://github.com/Pixplicity/humpty-dumpty-android

It performs two distinct methods described here:

  1. First, it tries to make the file accessible for other users, and attempting to pull it from the device.
  2. If that fails, it streams the contents of the file over the terminal to the local machine. It performs an additional trick to remove \r characters that some devices output to the shell.

From here you can use a variety of CLI or GUI SQLite applications, such as sqlite3 or sqlitebrowser, to browse the contents of the database.

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
  • This script is for debuggable applications, how about if app is not debuggable? – blueware Feb 21 '19 at 09:41
  • Your only options are likely to use backup tools, if the app in question exposes that data as part of a backup. Beyond that, I'm afraid it would require elevated permissions. – Paul Lammertsma Feb 27 '19 at 00:35
7

I couldn't get anything else to work for me but this:

adb shell
run-as package.name
cat /databases/databaseFileName.db > /sdcard/copiedDatabaseFileName.db
exit
exit
adb pull /sdcard/copiedDatabaseFileName.db /file/location/on/computer/

The first exit is to exit out of the run-as, the second exit is to exit out of adb shell to do the pull.

Triplee121
  • 81
  • 1
  • 4
5

For app's debug version, it's very convenient to use command adb exec-out run-as xxx.yyy.zzz cat somefile > somefile to extract a single file. But you have to do multiple times for multiple files. Here is a simple script I use to extract the directory.

#!/bin/bash
P=
F=
D=

function usage()
{
    echo "$(basename $0) [-f file] [-d directory] -p package"
    exit 1
}

while getopts ":p:f:d:" opt
do
    case $opt in
        p)
            P=$OPTARG
            echo package is $OPTARG
            ;;
        f)
            F=$OPTARG
            echo file is $OPTARG
            ;;
        d)
            D=$OPTARG
            echo directory is $OPTARG
            ;;
        \?)
            echo Unknown option -$OPTARG
            usage
            ;;
        \:)
            echo Required argument not found -$OPTARG
            usage
            ;;
    esac
done

[ x$P == x ] && {
    echo "package can not be empty"
    usage
    exit 1
}

[[ x$F == x  &&  x$D == x ]] && {
    echo "file or directory can not be empty"
    usage
    exit 1
}

function file_type()
{
    # use printf to avoid carriage return
    __t=$(adb shell run-as $P "sh -c \"[ -f $1 ] && printf f || printf d\"")
    echo $__t
}

function list_and_pull()
{
    t=$(file_type $1)
    if [ $t == d ]; then
        for f in $(adb shell run-as $P ls $1)
        do
            # the carriage return output from adb shell should
            # be removed
            mkdir -p $(echo -e $1 |sed $'s/\r//')
            list_and_pull $(echo -e $1/$f |sed $'s/\r//')
        done
    else
        echo pull file $1
        [ ! -e $(dirname $1) ] && mkdir -p $(dirname $1)
        $(adb exec-out run-as $P cat $1 > $1)
    fi
}

[ ! -z $D ] && list_and_pull $D
[ ! -z $F ] && list_and_pull $F

Hope it would be helpful. This script is also available at gist.

Typical usage is

$ ./exec_out.sh -p com.example.myapplication -d databases

then it will extract all files under your apps databases directory, which is /data/data/com.example.myapplication/databases, into current directory.

alijandro
  • 11,627
  • 2
  • 58
  • 74
  • 2
    even for multiple files it is still just a single command. check the update https://stackoverflow.com/a/18472135/1778421 if you would prefer you could also add another pipe on the host side to unpack the files – Alex P. Jul 10 '17 at 08:35
3

Much much simpler approach to download the file onto your local computer:

In your PC shell run:

adb -d shell 'run-as <package_name> cat /data/data/<package_name>/databases/<db_name>' > <local_file_name>
Emre
  • 125
  • 1
  • 2
  • 3
1
#!/bin/bash
#export for adb
export PATH=$PATH:/Users/userMe/Library/Android/sdk/platform-tools
export PATH=$PATH:/Users/userMe/Library/Android/sdk/tools

adb -d shell 'run-as com.android.app  cp /data/data/com.android.app/files/db.realm /sdcard'
adb pull sdcard/db.realm /Users/userMe/Desktop/db

You can use this script for get Realm database.

dralexnumber
  • 238
  • 2
  • 10
1

The database file is emtpy when using adb run-as. This can be resolved by calling close() on the RoomDatabase instance. Call close() to let SQLite write its journal to disk. I've created this button that closes the database connection on request:

via GIPHY

Here is how to call close on the RoomDatabase instance.

Eimert
  • 49
  • 6
  • I was facing the issue : DB copied but not with the latest data. Closing the db connection before db file copy fixed my problem. – Suchith Oct 29 '20 at 11:08
1

Steps to pull app db(installed in debug mode) from device

Close DB connection if opened

Open cmd (command prompt) (Change dir to your adb path)

cd C:\Program Files (x86)\Android\android-sdk\platform-tools

(list the app files)

adb -d shell "run-as com.xyz.name ls /data/data/com.xyz.name/files/"

(copy required file to sdcard)

adb -d shell "run-as com.xyz.name cp /data/data/com.xyz.name/files/abc.db /sdcard/abc.db"

(copy from sdcard to machine adb folder)

adb pull /sdcard/abc.db

Open DB connection

Destination file path in my case C:\Users{userName}\AppData\Local\VirtualStore\Program Files (x86)\Android\android-sdk\platform-tools Or Device storage

Suchith
  • 1,276
  • 17
  • 39
0

Here's a solution that works on a device running Android 5.1. The following example is for Windows.

You need sed (or sed.exe on windows, e.g. from cygwin.) ( On Unix, it'll just be there ;) ). To remove bad '\r' characters, at least on windows.

Now just run the following command:

adb exec-out "run-as com.yourcompany.yourapp /data/data/com.yourcompany.yourapp/databases/YourDatabaseName" | c:\cygwin\bin\sed.exe 's/\x0D\x0A/\x0A/'>YourDatabaseName.db

The sed command strips out trailing /r characters.

Of course you should replace "com.yourcompany.yourapp" with the package name of the app and "YourDatabaseName" with the name of the database in the app.

Nae
  • 14,209
  • 7
  • 52
  • 79
treesAreEverywhere
  • 3,722
  • 4
  • 28
  • 51
0

If someone is looking for another answer that can be used to retrieve Database as well as Shared Preferences then follow this step:

In your build.gradle file of your app add line

debugCompile 'com.amitshekhar.android:debug-db:1.0.0'

now when you run your app in non-release mode then your app will automatically open 8080 port from your device IP address make sure your device is connected via wifi and your laptop is sharing the same network. Now simply visit the url

http://your_mobile_device_ip:8080/

to watch all data of database along with shared preferences.

Pradeep Kumar Kushwaha
  • 2,231
  • 3
  • 23
  • 34