106

I've looked everywhere and i can't find a real precise answer or a tutorial on how, if it is possible, to do this.

is it possible to pull in any way a database of an Android device without having to root it? i just need to extract that data in any way in order to gather it on my pc, so how can i perform this? do i have to reprogram the app or whatever method you guys know about, but remember without rooting the device. thanks

DeX03
  • 1,609
  • 3
  • 14
  • 15

19 Answers19

180

If your device is running Android v4 or above, you can pull app data, including it's database, without root by using adb backup command, then extract the backup file and access the sqlite database.

First backup app data to your PC via USB cable with the following command, replace app.package.name with the actual package name of the application.

adb backup -f ~/data.ab -noapk app.package.name

This will prompt you to "unlock your device and confirm the backup operation". Do not provide a password for backup encryption, so you can extract it later. Click on the "Back up my data" button on your device. The screen will display the name of the package you're backing up, then close by itself upon successful completion.

The resulting data.ab file in your home folder contains application data in android backup format. To extract it use the following command:

dd if=data.ab bs=1 skip=24 | openssl zlib -d | tar -xvf -

If the above ended with openssl:Error: 'zlib' is an invalid command. error, try the below.

dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -

The result is the apps/app.package.name/ folder containing application data, including sqlite database.

For more details you can check the original blog post.

Elye
  • 53,639
  • 54
  • 212
  • 474
Sergei
  • 2,090
  • 2
  • 13
  • 7
  • 9
    For those who don't have zlib compiled without zlib, checkout the answer on http://blog.shvetsov.com/2013/02/access-android-app-data-without-root.html to extract the data with python. – ingh.am Apr 17 '13 at 13:56
  • In case you were not able to extract the file (for whatever reason), you can use this small software on windows that does the extaction easily using a GUI rather than command prompt. http://android.stackexchange.com/questions/28481/how-do-you-extract-an-apps-data-from-a-full-backup-made-through-adb-backup – tony9099 Sep 02 '13 at 11:46
  • 2
    For Windows users where the unpack command is unavailable, you can use "Android Backup Extractor" Java Application (http://sourceforge.net/projects/adbextractor/). See http://forum.xda-developers.com/showthread.php?t=2011811 for the commands to unpack the .ab file. – lalitm Apr 02 '14 at 09:55
  • 7
    on my MacBook Pro, I get the message `openssl:Error: 'zlib' is an invalid command.`, to which I responded with `dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -` HOWEVER, after it shows `17+0 records in17+0 records out17 bytes transferred in 0.000064 secs` there is no evidence of anything having been done to the folder. Since it's just 17 bytes I assume that command also failed. I think it's bad how I can't `adb pull` the database from a debug app !! – Someone Somewhere May 25 '14 at 04:51
  • 12
    pro tip: this backup stuff won't work if the app's manifest shows `android:allowBackup="false"` – Someone Somewhere May 27 '14 at 01:23
  • 9
    My `openssl` on Mac OS X didn't support `zlib` command either, so I reinstalled the one with brew: `brew reinstall openssl`. This won't replace your system openssl. Therefore I modified PATH command only for the current session: `export PATH=/usr/local/opt/openssl/bin:$PATH` after which could successfully perform the commands from this answer. – Aleks N. Oct 12 '14 at 14:10
  • 1
    Here is another oneliner for you: (echo -ne "\x1f\x8b\x08\x00\x00\x00\x00\x00" ; dd if=data.ab bs=1 skip=24) | gzip -dc - | tar -xvf - – Gal Bracha Dec 22 '14 at 02:48
  • lots of "not found" on windows, I think it works well on linux – Shirish Herwade Mar 30 '15 at 15:40
  • This works. Other answers require the device to be rooted or do some other jackup. Thanks @Sergei – ARK Jul 22 '15 at 20:58
  • "unlock your device and confirm the backup operation" - Yeah, so I unlocked the device using fastboot oem unlock. That deleted everything on my device. Thanks for the warning. – Johann Jan 14 '16 at 15:50
  • @AndroidDev: Unlock as in press the power button to turn on your device's screen and enter the password, not unlocking your boot loader. – Jade Jul 05 '16 at 14:28
  • the way how it works on ubuntu 16.04 `cat data.ab | (dd bs=24 count=0 skip=1; cat) | zlib-flate -uncompress > backup.tar` [How to backup / restore a paid Android app’s SQLite database without root](http://blog.jeshurun.ca/technology/backup-restore-paid-android-app-sqlite-database-no-root) – Zoltán Süle Jan 07 '17 at 20:13
  • Hi @sergi, can please tell me where is apps folder you are referring to? – anupam_kamble May 23 '18 at 18:37
  • Is this possible with any app installed on your phone, or just your own app? – live-love Jul 06 '18 at 17:19
  • this method doesn't work if application developer has explicitly disabled ability to backup his app by setting android:allowBackup="false" in the application manifest. – surya Jun 04 '19 at 06:08
79

A common way to achieve what you desire is to use the ADB pull command.

Another way I prefer in most cases is to copy the database by code to SD card:

try {
    File sd = Environment.getExternalStorageDirectory();

    if (sd.canWrite()) {
        String currentDBPath = "/data/data/" + getPackageName() + "/databases/yourdatabasename";
        String backupDBPath = "backupname.db";
        File currentDB = new File(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();
        }
    }
} catch (Exception e) {

}

Don't forget to set the permission to write on SD in your manifest, like below.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
dakshbhatt21
  • 3,558
  • 3
  • 31
  • 40
KarlKarlsom
  • 5,868
  • 4
  • 29
  • 36
  • 1
    well i'm gonna use this on a samsung galaxy tab which does not have a SD card so how do i do that there? – DeX03 Apr 03 '12 at 20:51
  • and, i have to use double //? – DeX03 Apr 04 '12 at 14:27
  • Yes, this is because the / is as special string char. // in your "//" will result in /. – KarlKarlsom Apr 04 '12 at 14:36
  • 4
    Rather than building the database path, SQLiteDatabase has a [`getPath`](http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#getPath()) method. – dysbulic Jan 15 '14 at 05:30
  • Brilliant answer. very smart,useful and simple. – Gundu Bandgar Oct 11 '17 at 11:28
  • I just wanted you to know this is awesome! I have a device that I cannot ADB into and this work-around (saving to SD card) is exactly what I needed. THANKS! – Brian Oct 31 '17 at 15:57
  • Worked very nice. Is this also 'reversable', so I can restore a backupped database? – Ramon Mar 09 '18 at 15:44
70

For debuggable apps1 on non-rooted devices, you could use following command:

adb shell run-as package.name chmod 666 /data/data/package.name/databases/file
adb pull /data/data/package.name/databases/file

Example:

adb shell run-as com.app chmod 666 /data/data/com.app/databases/data.db
adb pull /data/data/com.app/databases/data.db

Set PATH adb for Enviroment Variables or use cd command to android sdk folder platform-tools.

Example:

cd /folder/android-sdk/platform-tools/

then use above command


1 Note that most apps in Play store are not debuggable since it requires setting the debuggable flag in the manifest.

rustyx
  • 80,671
  • 25
  • 200
  • 267
Lam Vinh
  • 724
  • 5
  • 5
  • 8
    After I replace `package.name` with the app's package, the error is returned: `run-as: Package 'com.my.app' is unknown` – Someone Somewhere May 25 '14 at 05:02
  • 3
    It seems it doesn't work for all phones. Works for Nexus 4, doesn't work for SGS4 for instance. – Roman Minenok Jul 01 '14 at 12:53
  • 2
    Where is the db file saved? – Vojtěch Pešek Nov 06 '14 at 19:13
  • 3
    This used to work for me, but i can't seem to get this to work on my Nexus 7 that has updated to Android 5. Can anyone confirm that this works on Android 5? – treesAreEverywhere Dec 17 '14 at 20:27
  • 1
    @treesAreEverywhere this used to work for me also and now doesnt, and i think the culprit is android 5 as well – joshkendrick Feb 26 '15 at 20:50
  • on micromax devices it work, but doesn't work on samsung tab SM-T111, gives "permission denied" error – Shirish Herwade Mar 30 '15 at 15:39
  • 15
    Here’s a hack for Android 5(Lollipop) adb shell "run-as [package_name] chmod -R 777 /data/data/[package_name]/databases" adb shell "mkdir -p /sdcard/tempDB" adb shell "cp -r /data/data/[package_name]/databases/ /sdcard/tempDB/." adb pull sdcard/tempDB/ . adb shell "rm -r /sdcard/tempDB/*" – Rubin Yoo Apr 28 '15 at 21:52
  • the last part of your solution is not working. I am not able to pull data using "adb pull sdcard/tempDB" though I can see data has copied on /sdcard. What could be wrong? – Nitesh Verma Apr 29 '16 at 07:05
57

Most of the answers here are way more complicated than they have to be. If you just want to copy the database of your app from your phone to your computer then you just need this command:

adb -d shell "run-as your.package.name cat databases/database.name" > target.sqlite

All you need to fill in in the above command is the package name of your app, what the database is called and optionally what/where you want the database to be copied to.

Please note that this specific command will only work if you have only one device connected to your computer. The -d parameter means that the only connected device will be targeted. But there are other parameters which you can use instead:

  • -e will target the only running emulator
  • -s <serialnumber> will target a device with a specific serial number.

Xaver Kapeller
  • 49,491
  • 11
  • 98
  • 86
  • How can i open this file ? – Jehad Dec 31 '15 at 07:36
  • @Jehad: I had same problem. I found this way and it works for me. [Install SSHDroid on your phone](https://www.maketecheasier.com/access-android-device-with-linux-file-managers/) `adb -d shell "run-as your.package.name cat databases/database_name.db > /mnt/sdcard/database_name.db"` start the `SSHDroid` start FileZilla and connect to your phone via SFTP protocol. Set /mnt/sdcard as default remote directory. – Zoltán Süle Jan 07 '17 at 22:05
  • The easiest answer when you want to get the database of your own app. Two additions : 1) if you aren't certain of your database name, you can use a ls command to list the files in the database folder (`adb -d shell "run-as your.package.name ls databases"`) and 2) you may want to get any other associated files along with the database, in my case extracting the -smh and -wal files was the only way to get _DB Browser for SQLite_ to open the database – Ronan Aug 08 '19 at 09:59
  • This, too, only works if the app **is debuggable**. – dgw Oct 15 '20 at 01:33
37

Using Android Studio 3.0 or later version it is possible to pull database (also shared preference, cache directory and others) if application runs in debug mode on non-rooted device.

To pull database using android studio follow these steps.

  1. Click View > Tool Windows > Device File Explorer.
  2. Expand /data/data/[package-name] nodes.

Steps followed in Android Studio 3.0

Shahidul
  • 2,997
  • 1
  • 21
  • 20
6
 adb shell "run-as [package.name] chmod -R 777 /data/data/[package.name]/databases" 
 adb shell "mkdir -p /sdcard/tempDB" 
 adb shell "cp -r /data/data/[package.name]/databases/ /sdcard/tempDB/." 
 adb pull sdcard/tempDB/ . 
 adb shell "rm -r /sdcard/tempDB/*"
SaundersB
  • 607
  • 2
  • 12
  • 25
5

For Ubuntu (not only?):

see Sergeis Answer but instead of openssl use zlib-flate:

cat appbackup.ab | (dd bs=24 count=0 skip=1; cat) | zlib-flate -uncompress > appbackup.tar

Otherwise openssl will probably throw:

openssl:Error: 'zlib' is an invalid command.

because openssl is not compiled with zlib support in Ubuntu

Community
  • 1
  • 1
Murmel
  • 5,402
  • 47
  • 53
1

Since, nothing really work for me. I create a little windows BATCH script based on other answers combined together. Hope it help somebody. Simply usage: backupDatabase < PackageName > < ApplicationName > [TargetDirectory]. It use Sergei's backup method and Android Backup Extractor.

@echo off

if [%1]==[] goto usage
if [%2]==[] goto usage
if NOT [%4]==[] goto usage

@echo Processing: preparations
set PACKAGE=%1
set APPLICATION_NAME=%2
set TARGET_DIR=%cd%
IF NOT "%~3"=="" set TARGET_DIR=%3

set PATH_ADB="c:\Program Files (x86)\Android\android-studio\sdk\platform-tools"
set PATH_ABE="c:\Programs\android-backup-extractor-20140630-bin"
set PATH_7Z="c:\Program Files\7-Zip"

@echo Processing: backup
%PATH_ADB%\adb.exe backup -f %TARGET_DIR%\%APPLICATION_NAME%\%APPLICATION_NAME%.ab -noapk %PACKAGE%

@echo Processing: unpack
java -jar %PATH_ABE%\abe.jar unpack %TARGET_DIR%\%APPLICATION_NAME%\%APPLICATION_NAME%.ab %TARGET_DIR%\%APPLICATION_NAME%\%APPLICATION_NAME%.ab.tar

@echo Processing: extract
cd %TARGET_DIR%\%APPLICATION_NAME%
%PATH_7Z%\7z.exe e %APPLICATION_NAME%.ab.tar "apps\%PACKAGE%\db\%APPLICATION_NAME%"

@echo Processing: cleaning
del %APPLICATION_NAME%.ab
del %APPLICATION_NAME%.ab.tar
goto :eof

:usage
@echo.Pull out SQLite database file from your android device.
@echo.Needs: - connected device
@echo.       - device enable backup.
@echo.       - application enable backup
@echo.       - application in debug mode
@echo.       - installed Android Backup Extractor 
@echo.       - installed command line TAR extractor (7z, ...)
@echo.Does NOT need: root device
@echo.
@echo.Uses: - ADB backup (set PATH_ADB)
@echo.      - Android Backup Extractor (http://sourceforge.net/projects/adbextractor/) (set PATH_ABE)
@echo.      - Extract TAR container, uses 7z (set PATH_7Z)
@echo.
@echo.Usage: backupDatabase ^<PackageName^> ^<ApplicationName^> [TargetDirectory]
@echo.Example: backupDatabase com.foo.example ExampleApp 
@echo Example: backupDatabase com.foo.example ExampleApp workspace\AndroidProjects\Example
exit /B 1
Wooff
  • 1,091
  • 12
  • 23
1

If you are trying to do it on android 6 request the permission and use the code of the answer of this question

if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_RC); 
    return; 
} 

Once it is granted

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == STORAGE_PERMISSION_RC) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //permission granted  start reading or writing database
        } else { 
            Toast.makeText(this, "No permission to read external storage.", Toast.LENGTH_SHORT).show();
        } 
    } 
} 
Quintin Balsdon
  • 5,484
  • 10
  • 54
  • 95
Rodolfo Abarca
  • 565
  • 7
  • 15
1

Alternatively you can use my library Ultra Debugger. It's allow to download database as file or edit values directly in browser. No root needed, very easy to use.

BArtWell
  • 4,176
  • 10
  • 63
  • 106
1

On Mac (NO root required)

1. Go to platform-tools folder.
2) Run following command in terminal.

./adb -d shell "run-as your.package.name cat databases/database.sqlite" > database.sqlite

It will copy the sqlite file in platform-tools folder.

Yogesh Suthar
  • 30,424
  • 18
  • 72
  • 100
0

On a rooted device you can:

// check that db is there
>adb shell
# ls /data/data/app.package.name/databases
db_name.sqlite // a custom named db
# exit
// pull it
>adb pull /data/app.package.name/databases/db_name.sqlite
yanchenko
  • 56,576
  • 33
  • 147
  • 165
0

Based on the answer given by Lam Vinh, here is a simple batch file that works for me on my 1st gen Nexus 7. It prompts the user to enter the package name and then the database name (without the .sqlite extension) and puts it in c:\temp. This assumes you have the Android sdk set in the environment variables.

@echo off
cd c:\temp\

set /p UserInputPackage= Enter the package name: 
set /p UserInputDB= Enter the database name: 

@echo on
adb shell "run-as %UserInputPackage% chmod 666 /data/data/%UserInputPackage%/databases/%UserInputDB%.sqlite"
adb pull /data/data/%UserInputPackage%/databases/%UserInputDB%.sqlite
@echo off
pause
chutcher
  • 586
  • 6
  • 11
0

If you are on Android 4.0 or above, and you are on a mac, then here is a ruby script that will save your app contents to the desktop. I would imagine this would also work in Ubuntu, though I didn't test it.

puts "enter your package name"
package_name = gets.chomp
puts "press the 'Back up my data' button on your device"
`adb backup -f ~/Desktop/data.ab -noapk #{package_name}`
puts "press enter once once the 'Backup finished' toast has appeared"
gets.chomp
puts "extracting..."
`dd if=data.ab bs=1 skip=24 | openssl zlib -d | tar -xvf -`

to run -> ruby your_ruby_file_name.rb

This script is "happy path" only, so please make sure your device is connected and that adb has been added to your profile.

Swifty McSwifterton
  • 2,637
  • 1
  • 30
  • 37
0

you can easily extract the sqlite file from your device(root no necessary)

  1. Go to SDK Folder
  2. cd platform-tools
  3. start adb

    cd /sdk/platform-tools ./adb shell

    Then type in the following command in terminal

    ./adb -d shell "run-as com.your_packagename cat /data/data/com.your_packagename/databases/jokhanaNepal > /sdcard/jokhana.sqlite"

    For eg

    ./adb -d shell "run-as com.yuvii.app cat /data/data/com.yuvii.app/databases/jokhanaNepal > /sdcard/jokhana.sqlite"

yubaraj poudel
  • 3,821
  • 1
  • 31
  • 28
0

I give the complete solution to "save" and "restore" the app database to/from the internal storage (not to the PC with adb).

I have done two methods one for save and other for restore the database. Use these methods at the end of the onCreate() in MainActivity (one or the other if you want to saver or restore the database).

save database to internal storage:

void copyDatabase (){
        try {
            final String inFileName = "/data/data/<pakage.name>/databases/database.db";
            final String outFileName = Environment.getExternalStorageDirectory() + "database_backup.db";
            File dbFile = new File(inFileName);
            FileInputStream fis = new FileInputStream(dbFile);


            Log.d(TAG, "copyDatabase: outFile = " + outFileName);

            // Open the empty db as the output stream
            OutputStream output = new FileOutputStream(outFileName);

            // Transfer bytes from the inputfile to the outputfile
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }

            // Close the streams
            output.flush();
            output.close();
            fis.close();
        }catch (Exception e){
            Log.d(TAG, "copyDatabase: backup error");
        }
    }

restore database from internal storage:

void restoreDatabase (){
        try {
            final String inFileName = Environment.getExternalStorageDirectory() + "database_backup.db";
            final String outFileName = "/data/data/<package.name>/databases/database.db";
            File dbFile = new File(inFileName);
            FileInputStream fis = new FileInputStream(dbFile);

            Log.d(TAG, "copyDatabase: outFile = " + outFileName);

            // Open the empty db as the output stream
            OutputStream output = new FileOutputStream(outFileName);

            // Transfer bytes from the inputfile to the outputfile
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }

            // Close the streams
            output.flush();
            output.close();
            fis.close();
        }catch (Exception e){
            Log.d(TAG, "copyDatabase: backup error");
        }
    }
0

It is always better if things are automated.That's why I wrote simple python script for copying db file from device using ADB. It saves a lot of development time if you're doing it frequently.

Works only with debuggable apps if device is Not rooted.

Here is link to the gist.

Run it as : python copyandroiddbfile.py

import sys
import subprocess
import re

#/
# Created by @nieldeokar on 25/05/2018.
#/

# 1. Python script which will copy database file of debuggable apps from the android device to your computer using ADB.
# 2. This script ask for PackageName and DatabaseName at runtime.
# 3. You can make it static by passing -d at as command line argument while running script and setting defaults in following way.
# 4. Edit script and change the values of varialbe packageName and dbName to debuggable app package name and database name then
# run script as : python Copydbfileandroid.py -d 

useDefaults = False


def checkIfPackageInstalled(strSelectedDevice) :

    packageName = 'com.nileshdeokar.healthapp.debug'
    dbName = 'healthapp.db'


    if not useDefaults : 
        print('Please enter package name : ')
        packageName = raw_input()

    packageString = 'package:'+packageName

    try:
        adbCheckIfPackageInstalledOutput = subprocess.check_output('adb -s ' + strSelectedDevice + ' shell pm list packages | grep -x '+ packageString, shell=True)
    except subprocess.CalledProcessError as e:
                print "Package not found"
                return


    if packageString.strip() == adbCheckIfPackageInstalledOutput.strip() : 
        if not useDefaults : 
            print('Please enter db name : ')
            dbName = raw_input()

        adbCopyDbString = 'adb -s '+strSelectedDevice + ' -d shell \"run-as '+packageName+' cat /data/data/'+packageName+'/databases/'+ dbName +'\" > '+dbName

        try:
            copyDbOp = subprocess.check_output(adbCopyDbString,shell=True)
        except subprocess.CalledProcessError as e:
                return

        if "is not debuggable" in copyDbOp :
            print packageString + 'is nto debuggable'

        if copyDbOp.strip() == "":
            print 'Successfully copied '+dbName + ' in current directory'

    else :
        print 'Package is not installed on the device'



defaultString = "-d"
if len(sys.argv[1:]) > 0 and sys.argv[1] == defaultString :
        useDefaults = True

listDevicesOutput = subprocess.check_output("adb devices", shell=True)
listDevicesOutput = listDevicesOutput.replace("List of devices attached"," ").replace("\n","").replace("\t","").replace("\n\n","")

numberofDevices = len(re.findall(r'device+', listDevicesOutput))

connectedDevicesArray = listDevicesOutput.split("device")   
del connectedDevicesArray[-1] 


strSelectedDevice = ''
if(numberofDevices > 1) :
    print('Please select the device : \n'),

    for idx, device in enumerate(connectedDevicesArray):
        print idx+1,device

    selectedDevice = raw_input()

    if selectedDevice.isdigit() :
        intSelected = int(selectedDevice)
        if 1 <= intSelected <= len(connectedDevicesArray) :
            print 'Selected device is : ',connectedDevicesArray[intSelected-1]
            checkIfPackageInstalled(connectedDevicesArray[intSelected-1])
        else :
            print 'Please select in range'
    else : 
        print 'Not valid input'

elif numberofDevices == 1 :
    checkIfPackageInstalled(connectedDevicesArray[0])
elif numberofDevices == 0 :
    print("No device is attached")
Nilesh Deokar
  • 2,975
  • 30
  • 53
0
 > is it possible to pull in any way a database of an Android device without having to root it? 

yes if your android app creates a file copy of the database that is accessable by everyone.

android protects apps private data so it is not visible/accessable by other apps. a database is private data. your app can of course read the database-file so it can do a file-copy to some public visible file.

k3b
  • 14,517
  • 7
  • 53
  • 85
-1

If you want your database file

See the DDMS > File explore

find your db file from your package name

then Click on pull a file from device (Rooted device only)

MAC
  • 15,799
  • 8
  • 54
  • 95
  • 3
    this can be done but on a rooted device, which is the point of my question, how to do it on a not rooted device – DeX03 Apr 03 '12 at 20:17
  • 1
    this does not work on a non rooted device. Your answer should state that. – tony9099 Aug 30 '13 at 12:13