Android - Extraction d'un appareil Android de base de données SQlite

101

J'ai cherché partout et je ne trouve pas de vraie réponse précise ou de tutoriel sur la façon, si c'est possible, de le faire.

est-il possible d'extraire de quelque manière que ce soit une base de données d'un appareil Android sans avoir à le rooter? J'ai juste besoin d'extraire ces données de quelque manière que ce soit pour les rassembler sur mon PC, alors comment puis-je effectuer cela? Dois-je reprogrammer l'application ou toute autre méthode que vous connaissez, mais rappelez-vous sans enraciner l'appareil. Merci

DeX03
la source
voici la solution réalisable: stackoverflow.com/a/29257875/291427
kmalmur
1
stackoverflow.com/questions/13006315 Pull db sans enracinement
Naveen Prince P

Réponses:

78

Une manière courante d'obtenir ce que vous désirez est d'utiliser la commande d'extraction ADB.

Une autre façon que je préfère dans la plupart des cas est de copier la base de données par code sur la carte 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) {

}

N'oubliez pas de définir l'autorisation d'écrire sur SD dans votre manifeste, comme ci-dessous.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
KarlKarlsom
la source
1
Eh bien, je vais l'utiliser sur un onglet Samsung Galaxy qui n'a pas de carte SD, alors comment puis-je faire cela?
DeX03
et, je dois utiliser double //?
DeX03
Oui, c'est parce que le / est un caractère de chaîne spécial. // dans votre "//" donnera /.
KarlKarlsom
4
Plutôt que de créer le chemin de la base de données, SQLiteDatabase a une getPathméthode.
Will
Réponse géniale. très intelligent, utile et simple.
Gundu Bandgar
179

Si votre appareil exécute Android v4 ou supérieur, vous pouvez extraire les données de l'application, y compris sa base de données, sans racine à l'aide de la adb backupcommande, puis extraire le fichier de sauvegarde et accéder à la base de données sqlite.

Sauvegardez d'abord les données de l'application sur votre PC via un câble USB avec la commande suivante, remplacez-les app.package.namepar le nom réel du package de l'application.

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

Cela vous demandera de "déverrouiller votre appareil et de confirmer l'opération de sauvegarde". Ne fournissez pas de mot de passe pour le chiffrement de sauvegarde , vous pourrez donc l'extraire plus tard. Cliquez sur le bouton "Sauvegarder mes données" sur votre appareil. L'écran affichera le nom du package que vous sauvegardez, puis se fermera de lui-même une fois terminé.

Le data.abfichier résultant dans votre dossier d'accueil contient des données d'application au format de sauvegarde Android. Pour l'extraire, utilisez la commande suivante:

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

Si ce qui précède s'est terminé avec une openssl:Error: 'zlib' is an invalid command.erreur, essayez ce qui suit.

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

Le résultat est le apps/app.package.name/dossier contenant les données d'application, y compris la base de données sqlite.

Pour plus de détails, vous pouvez consulter l' article de blog original .

Sergei
la source
9
Pour ceux qui n'ont pas compilé zlib sans zlib, consultez la réponse sur blog.shvetsov.com/2013/02/… pour extraire les données avec python.
ingh.am
2
Pour les utilisateurs Windows pour lesquels la commande de décompression n'est pas disponible, vous pouvez utiliser l'application Java "Android Backup Extractor" ( sourceforge.net/projects/adbextractor ). Voir forum.xda-developers.com/showthread.php?t=2011811 pour les commandes de décompression du fichier .ab.
lalitm
7
sur mon MacBook Pro, je reçois le message openssl:Error: 'zlib' is an invalid command., auquel j'ai répondu avec dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -TOUTEFOIS, après qu'il montre 17+0 records in17+0 records out17 bytes transferred in 0.000064 secsqu'il n'y a aucune preuve que quoi que ce soit ait été fait dans le dossier. Comme il ne s'agit que de 17 octets, je suppose que cette commande a également échoué. Je pense que c'est mal comment je ne peux pas adb pullla base de données d'une application de débogage !!
Someone Somewhere
12
conseil de pro: cette sauvegarde ne fonctionnera pas si le manifeste de l'application s'afficheandroid:allowBackup="false"
Quelqu'un quelque part
9
Mon opensslsous Mac OS X ne prennent pas en charge la zlibcommande non plus , donc je réinstallé celui avec infusion: brew reinstall openssl. Cela ne remplacera pas votre système openssl. Par conséquent, j'ai modifié la commande PATH uniquement pour la session en cours: export PATH=/usr/local/opt/openssl/bin:$PATHaprès quoi j'ai pu exécuter avec succès les commandes de cette réponse.
Aleks N.
69

Pour les applications déboguables 1 sur des appareils non rootés , vous pouvez utiliser la commande suivante:

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

Exemple:

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

Définissez PATH adb pour les variables d'environnement ou utilisez la commande cd pour le dossier android sdk platform-tools.

Exemple:

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

puis utilisez la commande ci-dessus


1 Notez que la plupart des applications du Play Store ne sont pas déboguables car elles nécessitent la définition de l' indicateur déboguable dans le manifeste.

Lam Vinh
la source
8
Après avoir remplacé package.namepar le package de l'application, l'erreur est renvoyée:run-as: Package 'com.my.app' is unknown
Someone Somewhere
3
Il semble que cela ne fonctionne pas pour tous les téléphones. Fonctionne pour Nexus 4, ne fonctionne pas pour SGS4 par exemple.
Roman Minenok
2
Où le fichier db est-il enregistré?
Vojtěch Pešek
3
Cela fonctionnait pour moi, mais je n'arrive pas à faire fonctionner cela sur mon Nexus 7 qui a été mis à jour vers Android 5. Quelqu'un peut-il confirmer que cela fonctionne sur Android 5?
arbresAreEverywhere
15
Voici un hack pour 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 / [nom_package] / databases / / sdcard / tempDB /. " adb pull sdcard / tempDB /. shell adb "rm -r / sdcard / tempDB / *"
Rubin Yoo
55

La plupart des réponses ici sont bien plus compliquées qu'elles ne devraient l'être. Si vous souhaitez simplement copier la base de données de votre application de votre téléphone sur votre ordinateur, vous avez juste besoin de cette commande:

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

Tout ce que vous devez remplir dans la commande ci-dessus est le nom du package de votre application, le nom de la base de données et éventuellement vers quoi / où vous voulez que la base de données soit copiée.

Veuillez noter que cette commande spécifique ne fonctionnera que si vous n'avez qu'un seul appareil connecté à votre ordinateur. Le -dparamètre signifie que le seul appareil connecté sera ciblé. Mais il existe d'autres paramètres que vous pouvez utiliser à la place:

  • -e ciblera le seul émulateur en cours d'exécution
  • -s <serialnumber> ciblera un appareil avec un numéro de série spécifique.

Xaver Kapeller
la source
Comment puis-je ouvrir ce fichier?
Jehad
@Jehad: J'ai eu le même problème. J'ai trouvé cette voie et cela fonctionne pour moi. Installez SSHDroid sur votre téléphone, adb -d shell "run-as your.package.name cat databases/database_name.db > /mnt/sdcard/database_name.db" démarrez SSHDroidFileZilla et connectez-vous à votre téléphone via le protocole SFTP. Définissez / mnt / sdcard comme répertoire distant par défaut.
Zoltán Süle
La réponse la plus simple lorsque vous souhaitez obtenir la base de données de votre propre application. Deux ajouts: 1) si vous n'êtes pas certain du nom de votre base de données, vous pouvez utiliser une commande ls pour lister les fichiers dans le dossier de la base de données ( adb -d shell "run-as your.package.name ls databases") et 2) vous pouvez vouloir obtenir tous les autres fichiers associés avec la base de données, dans mon cas, l'extraction des fichiers -smh et -wal était le seul moyen d'obtenir DB Browser for SQLite pour ouvrir la base de données
Ronan
36

En utilisant Android Studio 3.0 ou une version ultérieure, il est possible d'extraire la base de données (également les préférences partagées, le répertoire de cache et autres) si l'application s'exécute en mode débogage sur un appareil non rooté.

Pour extraire la base de données à l'aide d'Android Studio, procédez comme suit.

  1. Cliquez sur Affichage > Fenêtres d'outils > Explorateur de fichiers de périphérique .
  2. Développez les nœuds / data / data / [package-name] .

Étapes suivies dans Android Studio 3.0

Shahidul
la source
Merci. Fichiers téléchargés à partir d'un émulateur, mais ne peuvent pas les obtenir à partir d'un Galaxy S4 non enraciné.
CoolMind
Pouvez-vous extraire la base de données de n'importe quelle application ou simplement de votre propre application?
live-love
Toute application dont la condition préalable est l'application doit être déboguable.
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/*"
SaundersB
la source
5

Pour Ubuntu (pas seulement?):

voir Sergeis Answer mais au lieu de openssl, utilisez zlib-flate:

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

Sinon, openssl lancera probablement:

openssl: Erreur: «zlib» est une commande non valide.

car openssl n'est pas compilé avec le support zlib dans Ubuntu

Murmel
la source
1

Depuis, rien ne fonctionne vraiment pour moi. Je crée un petit script Windows BATCH basé sur d'autres réponses combinées. J'espère que cela aidera quelqu'un. Utilisation simple: backupDatabase <PackageName> <ApplicationName> [TargetDirectory]. Il utilise la méthode de sauvegarde de Sergei et 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
la source
1

vous pouvez facilement extraire le fichier sqlite de votre appareil (root pas nécessaire)

  1. Accédez au dossier SDK
  2. outils de plate-forme cd
  3. start adb

    cd / sdk / platform-tools ./adb shell Tapez

    ensuite la commande suivante dans le terminal

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

    Par exemple

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

yubaraj poudel
la source
1

Si vous essayez de le faire sur Android 6, demandez l'autorisation et utilisez le code de la réponse à cette 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; 
} 

Une fois qu'il est accordé

@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();
        } 
    } 
} 
Rodolfo Abarca
la source
1

Vous pouvez également utiliser ma bibliothèque Ultra Debugger . Il permet de télécharger la base de données sous forme de fichier ou de modifier les valeurs directement dans le navigateur. Aucune racine nécessaire, très facile à utiliser.

BArtWell
la source
1

Sur Mac (AUCUNE racine requise)

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

Il copiera le fichier sqlite dans le dossier platform-tools.

Yogesh Suthar
la source
Cela semble ne fonctionner que si l'application est compilée pour le débogage.
David Berry
@DavidBerry Oui, il tirera la base de données si compilée pour le débogage, sinon vous auriez pu extraire la base de données de n'importe quelle application. Et ce sera un grave problème de sécurité de l'application. :)
Yogesh Suthar
0
 > is it possible to pull in any way a database of an Android device without having to root it? 

oui si votre application Android crée une copie de fichier de la base de données accessible à tous.

Android protège les données privées des applications afin qu'elles ne soient pas visibles / accessibles par d'autres applications. une base de données est une donnée privée. votre application peut bien sûr lire le fichier de base de données afin de pouvoir faire une copie de fichier dans un fichier public visible.

k3b
la source
0

Sur un appareil enraciné, vous pouvez:

// 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
la source
Je ne suis pas sûr à 100% mais je pense qu'avant de tirer est nécessaire> su et donnez la permission
pavol.franek
0

Basé sur la réponse donnée par Lam Vinh, voici un simple fichier batch qui fonctionne pour moi sur mon Nexus 7 de 1ère génération.Il invite l'utilisateur à entrer le nom du package puis le nom de la base de données (sans l'extension .sqlite) et le met dans c: \ temp. Cela suppose que vous avez défini le sdk Android dans les variables d'environnement.

@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
la source
0

Si vous êtes sous Android 4.0 ou supérieur et que vous êtes sur un mac , voici un script ruby ​​qui enregistrera le contenu de votre application sur le bureau. J'imagine que cela fonctionnerait également dans Ubuntu, même si je ne l'ai pas testé.

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

pour exécuter -> ruby ​​your_ruby_file_name.rb

Ce script est uniquement "happy path", veuillez donc vous assurer que votre appareil est connecté et que adb a été ajouté à votre profil.

Swifty McSwifterton
la source
0

Je donne la solution complète pour "enregistrer" et "restaurer" la base de données de l'application vers / depuis le stockage interne (pas sur le PC avec adb).

J'ai fait deux méthodes une pour sauvegarder et une autre pour restaurer la base de données. Utilisez ces méthodes à la fin de onCreate () dans MainActivity (l'une ou l'autre si vous souhaitez sauvegarder ou restaurer la base de données).

enregistrer la base de données dans le stockage interne:

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

restaurer la base de données à partir du stockage interne:

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");
        }
    }
Cubes numériques
la source
0

C'est toujours mieux si les choses sont automatisées.C'est pourquoi j'ai écrit un simple script python pour copier un fichier db à partir d'un appareil utilisant ADB. Cela fait gagner beaucoup de temps au développement si vous le faites fréquemment.

Fonctionne uniquement avec les applications déboguables si l'appareil n'est pas enraciné.

Voici le lien vers l'essentiel.

Exécutez-le comme: 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
la source
-1

Si vous voulez que votre fichier de base de données

Voir le DDMS> Exploration de fichiers

trouvez votre fichier db à partir du nom de votre package

puis cliquez sur extraire un fichier de l'appareil (appareil enraciné uniquement)

MAC
la source
3
cela peut être fait mais sur un appareil enraciné, ce qui est le point de ma question, comment le faire sur un appareil non enraciné
DeX03
1
cela ne fonctionne pas sur un périphérique non rooté. Votre réponse devrait l'indiquer.
tony9099