Android - Estrazione del dispositivo Android del database SQlite


101

Ho cercato ovunque e non riesco a trovare una risposta reale precisa o un tutorial su come, se possibile, farlo.

è possibile estrarre in qualche modo un database di un dispositivo Android senza doverlo rootare? ho solo bisogno di estrarre quei dati in qualsiasi modo per raccoglierli sul mio pc, quindi come posso farlo? devo riprogrammare l'app o qualunque metodo voi sappiate, ma ricordate senza eseguire il root del dispositivo. Grazie


ecco la soluzione praticabile: stackoverflow.com/a/29257875/291427
kmalmur



Risposte:


78

Un modo comune per ottenere ciò che desideri è utilizzare il comando pull di ADB.

Un altro modo che preferisco nella maggior parte dei casi è copiare il database tramite codice sulla scheda SD:

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) {

}

Non dimenticare di impostare l'autorizzazione per scrivere su SD nel tuo manifest, come di seguito.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

1
beh, lo userò su una scheda Samsung Galaxy che non ha una scheda SD, quindi come posso farlo lì?
DeX03

e devo usare double //?
DeX03

Sì, questo perché / è una stringa speciale char. // nel tuo "//" risulterà in /.
KarlKarlsom

4
Piuttosto che costruire il percorso del database, SQLiteDatabase ha un getPathmetodo.
Il

Risposta brillante. molto intelligente, utile e semplice.
Gundu Bandgar,

179

Se il tuo dispositivo esegue Android v4 o versioni successive, puoi estrarre i dati dell'app, incluso il database, senza root utilizzando il adb backupcomando, quindi estrarre il file di backup e accedere al database sqlite.

Primo backup dei dati dell'app sul PC tramite cavo USB con il seguente comando, sostituire app.package.namecon il nome effettivo del pacchetto dell'applicazione.

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

Questo ti chiederà di "sbloccare il tuo dispositivo e confermare l'operazione di backup". Non fornire una password per la crittografia del backup , in modo da poterla estrarre in seguito. Fare clic sul pulsante "Backup dei miei dati" sul dispositivo. Lo schermo visualizzerà il nome del pacchetto di cui si sta eseguendo il backup, quindi si chiuderà da solo una volta completato con successo.

Il data.abfile risultante nella cartella home contiene i dati dell'applicazione nel formato di backup di Android. Per estrarlo utilizzare il seguente comando:

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

Se quanto sopra si è concluso con un openssl:Error: 'zlib' is an invalid command.errore, prova quanto segue.

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

Il risultato è la apps/app.package.name/cartella contenente i dati dell'applicazione, incluso il database sqlite.

Per maggiori dettagli puoi controllare il post originale del blog .


9
Per coloro che non hanno zlib compilato senza zlib, controlla la risposta su blog.shvetsov.com/2013/02/… per estrarre i dati con python.
ingh

2
Per gli utenti Windows in cui il comando unpack non è disponibile, è possibile utilizzare l'applicazione Java "Android Backup Extractor" ( sourceforge.net/projects/adbextractor ). Vedi forum.xda-developers.com/showthread.php?t=2011811 per i comandi per decomprimere il file .ab.
lalitm

7
sul mio MacBook Pro, ricevo il messaggio openssl:Error: 'zlib' is an invalid command., al quale ho risposto dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -TUTTAVIA, dopo che non 17+0 records in17+0 records out17 bytes transferred in 0.000064 secsci sono prove che sia stato fatto nulla alla cartella. Dato che sono solo 17 byte, presumo che anche il comando non sia riuscito. Penso che sia brutto come non riesco a creare adb pullil database da un'app di debug !!
Someone Somewhere

12
Suggerimento: questa roba di backup non funzionerà se il manifest dell'app mostraandroid:allowBackup="false"
Someone Somewhere,

9
Il mio opensslsu Mac OS X non supporta zlibil comando o, in modo ho reinstallato quello con birra: brew reinstall openssl. Questo non sostituirà il tuo sistema openssl. Pertanto ho modificato il comando PATH solo per la sessione corrente: export PATH=/usr/local/opt/openssl/bin:$PATHdopo di che ho potuto eseguire con successo i comandi da questa risposta.
Aleks N.

69

Per le app debuggabili 1 su dispositivi non rooted , è possibile utilizzare il seguente comando:

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

Esempio:

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

Imposta PATH adb per le variabili ambientali o usa il comando cd per gli strumenti della piattaforma della cartella SDK di Android.

Esempio:

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

quindi utilizzare il comando sopra


1 Tieni presente che la maggior parte delle app nel Play Store non è eseguibile per il debug poiché richiede l'impostazione del flag di debug nel manifest.


8
Dopo la sostituzione package.namecon il pacchetto dell'app, viene restituito l'errore:run-as: Package 'com.my.app' is unknown
Someone Somewhere,

3
Sembra che non funzioni per tutti i telefoni. Ad esempio, funziona per Nexus 4, non funziona per SGS4.
Roman Minenok

2
Dove viene salvato il file db?
Vojtěch Pešek

3
Questo funzionava per me, ma non riesco a farlo funzionare sul mio Nexus 7 che è stato aggiornato ad Android 5. Qualcuno può confermare che funziona su Android 5?
treesAreEverywhere

15
Ecco un trucco per Android 5 (Lollipop) adb shell "run-as [nome_pacchetto] chmod -R 777 / data / data / [nome_pacchetto] / database" shell adb "mkdir -p / sdcard / tempDB" shell adb "cp -r / data / data / [nome_pacchetto] / databases / / sdcard / tempDB /. " adb pull sdcard / tempDB /. shell adb "rm -r / sdcard / tempDB / *"
Rubin Yoo

55

La maggior parte delle risposte qui sono molto più complicate di quanto devono essere. Se vuoi solo copiare il database della tua app dal tuo telefono al tuo computer, allora hai solo bisogno di questo comando:

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

Tutto ciò di cui hai bisogno per compilare il comando precedente è il nome del pacchetto della tua app, come viene chiamato il database e, facoltativamente, cosa / dove vuoi che venga copiato il database.

Tieni presente che questo comando specifico funzionerà solo se hai un solo dispositivo collegato al tuo computer. Il -dparametro indica che verrà scelto come target l'unico dispositivo connesso. Ma ci sono altri parametri che puoi usare invece:

  • -e prenderà di mira l'unico emulatore in esecuzione
  • -s <serialnumber> mirerà a un dispositivo con un numero di serie specifico.


Come posso aprire questo file?
Jehad

@ Jehad: ho avuto lo stesso problema. Ho trovato questo modo e per me funziona. Installa SSHDroid sul tuo telefono, adb -d shell "run-as your.package.name cat databases/database_name.db > /mnt/sdcard/database_name.db" avvia SSHDroidFileZilla e connettiti al tuo telefono tramite protocollo SFTP. Imposta / mnt / sdcard come directory remota predefinita.
Zoltán Süle

La risposta più semplice quando vuoi ottenere il database della tua app. Due aggiunte: 1) se non sei sicuro del nome del tuo database, puoi usare un comando ls per elencare i file nella cartella del database ( adb -d shell "run-as your.package.name ls databases") e 2) potresti voler ottenere altri file associati insieme al database, in il mio caso l'estrazione dei file -smh e -wal era l'unico modo per ottenere DB Browser per SQLite per aprire il database
Ronan

36

Utilizzando Android Studio 3.0 o versione successiva è possibile eseguire il pull del database (anche preferenze condivise, directory della cache e altri) se l'applicazione viene eseguita in modalità di debug su un dispositivo non rooted.

Per estrarre il database utilizzando Android Studio, segui questi passaggi.

  1. Fare clic su Visualizza > Strumenti di Windows > Esplora file del dispositivo .
  2. Espandere i nodi / data / data / [nome-pacchetto] .

Passaggi seguiti in Android Studio 3.0


Grazie. File scaricati da un emulatore, mentre non è possibile ottenerli da Galaxy S4 senza root.
CoolMind

Puoi estrarre il database da qualsiasi app o solo dalla tua app?
live-love

Qualsiasi app ma la condizione preliminare è l'app deve essere debug.
Shahidul

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/*"

5

Per Ubuntu (non solo?):

vedi Sergeis Answer ma invece di openssl usa zlib-flate:

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

Altrimenti openssl probabilmente lancerà:

openssl: Errore: "zlib" è un comando non valido.

perché openssl non è compilato con il supporto zlib in Ubuntu


1

Da allora, niente funziona davvero per me. Creo un piccolo script BATCH di Windows basato su altre risposte combinate insieme. Spero che aiuti qualcuno. Utilizzo semplice: backupDatabase <PackageName> <ApplicationName> [TargetDirectory]. Utilizza il metodo di backup di Sergei e 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

1

puoi facilmente estrarre il file sqlite dal tuo dispositivo (root non necessario)

  1. Vai alla cartella SDK
  2. cd platform-tools
  3. avvia adb

    cd / sdk / platform-tools ./adb shell

    Quindi digita il seguente comando nel terminale

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

    Per es.

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


1

Se stai provando a farlo su Android 6 richiedi il permesso e usa il codice della risposta a questa domanda

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

Una volta concesso

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

1

In alternativa puoi usare la mia libreria Ultra Debugger . Permette di scaricare il database come file o modificare i valori direttamente nel browser. Nessuna radice necessaria, molto facile da usare.


1

Su Mac (NESSUN root richiesto)

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

Copierà il file sqlite nella cartella degli strumenti della piattaforma.


Sembra funzionare solo se l'app è compilata per il debug.
David Berry

@DavidBerry Sì, tirerà db se compilato per il debug, altrimenti avresti potuto estrarre il db di qualsiasi app. E sarà un serio problema di sicurezza dell'app. :)
Yogesh Suthar

0
 > is it possible to pull in any way a database of an Android device without having to root it? 

Sì, se la tua app Android crea una copia del file del database accessibile a tutti.

Android protegge i dati privati ​​delle app in modo che non siano visibili / accessibili da altre app. un database è un dato privato. la tua app può ovviamente leggere il file di database in modo da poter eseguire una copia del file in un file pubblico visibile.


0

Su un dispositivo rooted puoi:

// 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

Non sono sicuro al 100% ma penso che prima di tirare sia necessario> su e dare il permesso
pavol.franek

0

Sulla base della risposta data da Lam Vinh, ecco un semplice file batch che funziona per me sul mio Nexus di prima generazione 7. Chiede all'utente di inserire il nome del pacchetto e quindi il nome del database (senza l'estensione .sqlite) e lo inserisce in c: \ temp. Ciò presuppone che l'SDK di Android sia impostato nelle variabili di ambiente.

@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

0

Se sei su Android 4.0 o versioni successive e sei su un Mac , ecco uno script ruby ​​che salverà i contenuti della tua app sul desktop. Immagino che funzioni anche in Ubuntu, anche se non l'ho testato.

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 -`

per eseguire -> ruby ​​your_ruby_file_name.rb

Questo script è solo "percorso felice", quindi assicurati che il tuo dispositivo sia connesso e che adb sia stato aggiunto al tuo profilo.


0

Fornisco la soluzione completa per "salvare" e "ripristinare" il database dell'app nella / dalla memoria interna (non sul PC con adb).

Ho eseguito due metodi uno per il salvataggio e l'altro per il ripristino del database. Utilizzare questi metodi alla fine di onCreate () in MainActivity (uno o l'altro se si desidera salvare o ripristinare il database).

salva il database nella memoria interna:

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

ripristinare il database dalla memoria interna:

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

È sempre meglio se le cose sono automatizzate, ecco perché ho scritto un semplice script python per copiare il file db dal dispositivo usando ADB. Risparmia molto tempo di sviluppo se lo fai spesso.

Funziona solo con app debuggabili se il dispositivo non è rootato .

Ecco il collegamento all'essenza.

Eseguilo come: 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")

-1

Se vuoi il tuo file database

Vedi DDMS> Esplora file

trova il tuo file db dal nome del pacchetto

quindi fare clic su Estrai un file dal dispositivo (solo dispositivo con root)


3
questo può essere fatto ma su un dispositivo rooted, che è il punto della mia domanda, come farlo su un dispositivo non
rootato

1
questo non funziona su un dispositivo non rootato. La tua risposta dovrebbe affermarlo.
tony9099
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.