Android: dispositivo Android de extracción de base de datos SQlite

99

He buscado en todas partes y no puedo encontrar una respuesta real precisa o un tutorial sobre cómo, si es posible, hacer esto.

¿Es posible extraer de alguna manera una base de datos de un dispositivo Android sin tener que rootearlo? Solo necesito extraer esos datos de cualquier manera para recopilarlos en mi PC, entonces, ¿cómo puedo realizar esto? ¿Tengo que reprogramar la aplicación o cualquier método que conozcan, pero recuerde sin rootear el dispositivo? Gracias

DeX03
fuente
aquí está la solución viable: stackoverflow.com/a/29257875/291427
kmalmur
1
stackoverflow.com/questions/13006315 Extraer db sin rootear
Naveen Prince P

Respuestas:

78

Una forma común de lograr lo que desea es utilizar el comando de extracción de ADB.

Otra forma que prefiero en la mayoría de los casos es copiar la base de datos por código a la tarjeta 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) {

}

No olvide establecer el permiso para escribir en SD en su manifiesto, como se muestra a continuación.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
KarlKarlsom
fuente
1
Bueno, voy a usar esto en una pestaña de Samsung Galaxy que no tiene una tarjeta SD, entonces, ¿cómo lo hago allí?
DeX03
y tengo que usar double //?
DeX03
Sí, esto se debe a que / es un carácter de cadena especial. // en su "//" resultará en /.
KarlKarlsom
4
En lugar de crear la ruta de la base de datos, SQLiteDatabase tiene un getPathmétodo.
Será el
Brillante respuesta. muy inteligente, útil y simple.
Gundu Bandgar
179

Si su dispositivo ejecuta Android v4 o superior, puede extraer datos de la aplicación, incluida su base de datos, sin root mediante el adb backupcomando, luego extraer el archivo de respaldo y acceder a la base de datos sqlite.

Primero haga una copia de seguridad de los datos de la aplicación en su PC mediante un cable USB con el siguiente comando, reemplácelo app.package.namecon el nombre real del paquete de la aplicación.

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

Esto le pedirá que "desbloquee su dispositivo y confirme la operación de copia de seguridad". No proporcione una contraseña para el cifrado de respaldo , para que pueda extraerla más tarde. Haga clic en el botón "Hacer una copia de seguridad de mis datos" en su dispositivo. La pantalla mostrará el nombre del paquete que está respaldando y luego se cerrará por sí solo cuando se complete con éxito.

El data.abarchivo resultante en su carpeta de inicio contiene datos de la aplicación en formato de copia de seguridad de Android. Para extraerlo use el siguiente comando:

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

Si lo anterior terminó con un openssl:Error: 'zlib' is an invalid command.error, intente lo siguiente.

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

El resultado es la apps/app.package.name/carpeta que contiene los datos de la aplicación, incluida la base de datos sqlite.

Para obtener más detalles, puede consultar la publicación del blog original .

Sergei
fuente
9
Para aquellos que no tienen zlib compilado sin zlib, consulte la respuesta en blog.shvetsov.com/2013/02/… para extraer los datos con python.
ingh.am
2
Para los usuarios de Windows donde el comando de descomprimir no está disponible, puede usar la aplicación Java "Android Backup Extractor" ( sourceforge.net/projects/adbextractor ). Consulte forum.xda-developers.com/showthread.php?t=2011811 para conocer los comandos para descomprimir el archivo .ab.
lalitm
7
en mi MacBook Pro, recibo el mensaje openssl:Error: 'zlib' is an invalid command., al que respondí dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -SIN EMBARGO, después de que muestra que 17+0 records in17+0 records out17 bytes transferred in 0.000064 secsno hay evidencia de que se haya hecho nada en la carpeta. Como solo tiene 17 bytes, supongo que el comando también falló. ¡Creo que es malo que no pueda acceder a adb pullla base de datos desde una aplicación de depuración!
Someone Somewhere
12
consejo profesional: esta copia de seguridad no funcionará si se muestra el manifiesto de la aplicaciónandroid:allowBackup="false"
alguien en algún lugar
9
Mi opensslen Mac OS X no apoyaron zlibcomando tampoco, así que vuelve a instalar el uno con cerveza: brew reinstall openssl. Esto no reemplazará su sistema openssl. Por lo tanto, modifiqué el comando PATH solo para la sesión actual: export PATH=/usr/local/opt/openssl/bin:$PATHdespués de lo cual pude ejecutar con éxito los comandos de esta respuesta.
Aleks N.
69

Para aplicaciones depurables 1 en dispositivos no rooteados , puede usar el siguiente comando:

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

Ejemplo:

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

Establezca PATH adb para las variables de entorno o use el comando cd para las herramientas de plataforma de la carpeta sdk de Android.

Ejemplo:

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

luego use el comando anterior


1 Tenga en cuenta que la mayoría de las aplicaciones en Play Store no se pueden depurar, ya que requiere configurar el indicador de depuración en el manifiesto.

Lam Vinh
fuente
8
Después de reemplazar package.namecon el paquete de la aplicación, se devuelve el error:run-as: Package 'com.my.app' is unknown
Alguien en algún lugar
3
Parece que no funciona para todos los teléfonos. Funciona para Nexus 4, no funciona para SGS4, por ejemplo.
Roman Minenok
2
¿Dónde se guarda el archivo db?
Vojtěch Pešek
3
Esto solía funcionar para mí, pero parece que no puedo hacerlo funcionar en mi Nexus 7 que se ha actualizado a Android 5. ¿Alguien puede confirmar que esto funciona en Android 5?
treesAreEverywhere
15
Aquí hay un truco para Android 5 (Lollipop) adb shell "ejecutar-como [nombre_paquete] chmod -R 777 / data / data / [nombre_paquete] / bases de datos" adb shell "mkdir -p / sdcard / tempDB" adb shell "cp -r / data / data / [nombre_paquete] / bases de datos / / sdcard / tempDB /. " adb pull sdcard / tempDB /. adb shell "rm -r / sdcard / tempDB / *"
Rubin Yoo
55

La mayoría de las respuestas aquí son mucho más complicadas de lo que deberían ser. Si solo desea copiar la base de datos de su aplicación desde su teléfono a su computadora, solo necesita este comando:

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

Todo lo que necesita completar en el comando anterior es el nombre del paquete de su aplicación, cómo se llama la base de datos y, opcionalmente, qué / dónde desea que se copie la base de datos.

Tenga en cuenta que este comando específico solo funcionará si solo tiene un dispositivo conectado a su computadora. El -dparámetro significa que se apuntará al único dispositivo conectado. Pero hay otros parámetros que puede usar en su lugar:

  • -e apuntará al único emulador en ejecución
  • -s <serialnumber> apuntará a un dispositivo con un número de serie específico.

Xaver Kapeller
fuente
¿Cómo puedo abrir este archivo?
Jehad
@Jehad: Tuve el mismo problema. Encontré de esta manera y funciona para mí. Instale SSHDroid en su teléfono, adb -d shell "run-as your.package.name cat databases/database_name.db > /mnt/sdcard/database_name.db" inicie SSHDroidFileZilla y conéctese a su teléfono a través del protocolo SFTP. Establezca / mnt / sdcard como directorio remoto predeterminado.
Zoltán Süle
La respuesta más sencilla cuando desea obtener la base de datos de su propia aplicación. Dos adiciones: 1) si no está seguro del nombre de su base de datos, puede usar un comando ls para listar los archivos en la carpeta de la base de datos ( adb -d shell "run-as your.package.name ls databases") y 2) es posible que desee obtener cualquier otro archivo asociado junto con la base de datos, en mi caso, la extracción de los archivos -smh y -wal era la única forma de que DB Browser para SQLite abriera la base de datos
Ronan
36

Con Android Studio 3.0 o una versión posterior, es posible extraer la base de datos (también preferencia compartida, directorio de caché y otros) si la aplicación se ejecuta en modo de depuración en un dispositivo no rooteado.

Para extraer la base de datos usando Android Studio, siga estos pasos.

  1. Haga clic en Ver > Ventanas de herramientas > Explorador de archivos de dispositivo .
  2. Expanda los nodos / data / data / [nombre-paquete] .

Pasos seguidos en Android Studio 3.0

Shahidul
fuente
Gracias. Archivos descargados de un emulador, mientras que no se pueden obtener de Galaxy S4 sin root.
CoolMind
¿Puedes extraer la base de datos de cualquier aplicación o solo de tu propia aplicación?
live-love
Cualquier aplicación, excepto la condición previa, debe ser depurable.
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
fuente
5

Para Ubuntu (¿no solo?):

vea la respuesta de Sergeis pero en lugar de openssl use zlib-flate:

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

De lo contrario, openssl probablemente arrojará:

openssl: Error: 'zlib' es un comando no válido.

porque openssl no está compilado con soporte zlib en Ubuntu

Murmel
fuente
1

Desde entonces, nada funciona realmente para mí. Creo un pequeño script de Windows BATCH basado en otras respuestas combinadas. Espero que ayude a alguien. Simplemente use: backupDatabase <PackageName> <ApplicationName> [TargetDirectory]. Utiliza el método de copia de seguridad de Sergei y 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
fuente
1

puede extraer fácilmente el archivo sqlite de su dispositivo (root no es necesario)

  1. Ir a la carpeta SDK
  2. herramientas de plataforma de cd
  3. empezar adb

    cd / sdk / platform-tools ./adb shell

    Luego escriba el siguiente comando en la terminal

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

    Por ejemplo

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

Yubaraj poudel
fuente
1

Si está intentando hacerlo en Android 6 solicite el permiso y use el código de la respuesta de esta pregunta

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 vez que se concede

@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
fuente
1

Alternativamente, puede usar mi biblioteca Ultra Debugger . Permite descargar la base de datos como archivo o editar valores directamente en el navegador. No se necesita root, muy fácil de usar.

BArtWell
fuente
1

En Mac (NO se requiere root)

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

Copiará el archivo sqlite en la carpeta de herramientas de la plataforma.

Yogesh Suthar
fuente
Esto parece funcionar solo si la aplicación está compilada para depuración.
David Berry
@DavidBerry Sí, extraerá la base de datos si se compila para la depuración, de lo contrario, podría haber extraído la base de datos de cualquier aplicación. Y será un problema de seguridad grave de la aplicación. :)
Yogesh Suthar
0
 > is it possible to pull in any way a database of an Android device without having to root it? 

sí, si su aplicación de Android crea una copia de archivo de la base de datos a la que todos pueden acceder.

Android protege los datos privados de las aplicaciones para que no sean visibles / accesibles por otras aplicaciones. una base de datos son datos privados. su aplicación puede, por supuesto, leer el archivo de base de datos para que pueda hacer una copia de archivo en algún archivo público visible.

k3b
fuente
0

En un dispositivo rooteado puede:

// 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
fuente
No estoy 100% seguro, pero creo que antes de tirar es necesario> su y dar permiso
pavol.franek
0

Según la respuesta dada por Lam Vinh, aquí hay un archivo por lotes simple que funciona para mí en mi Nexus 7 de primera generación. Le pide al usuario que ingrese el nombre del paquete y luego el nombre de la base de datos (sin la extensión .sqlite) y lo coloca en c: \ temp. Esto supone que tiene el sdk de Android configurado en las variables de entorno.

@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
fuente
0

Si está en Android 4.0 o superior, y está en una Mac , entonces aquí hay un script ruby ​​que guardará el contenido de su aplicación en el escritorio. Me imagino que esto también funcionaría en Ubuntu, aunque no lo probé.

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

para ejecutar -> ruby ​​your_ruby_file_name.rb

Esta secuencia de comandos es solo "ruta feliz", así que asegúrese de que su dispositivo esté conectado y de que adb se haya agregado a su perfil.

Swifty McSwifterton
fuente
0

Doy la solución completa para "guardar" y "restaurar" la base de datos de la aplicación hacia / desde el almacenamiento interno (no a la PC con adb).

He hecho dos métodos, uno para guardar y otro para restaurar la base de datos. Utilice estos métodos al final de onCreate () en MainActivity (uno u otro si desea guardar o restaurar la base de datos).

guardar la base de datos en el almacenamiento interno:

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

restaurar la base de datos desde el almacenamiento interno:

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");
        }
    }
Cubos digitales
fuente
0

Siempre es mejor si las cosas están automatizadas Es por eso que escribí un script de Python simple para copiar el archivo db desde el dispositivo usando ADB. Ahorra mucho tiempo de desarrollo si lo hace con frecuencia.

Solo funciona con aplicaciones depurables si el dispositivo no está rooteado.

Aquí hay un enlace a la esencia.

Ejecútelo como: 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
fuente
-1

Si quieres tu archivo de base de datos

Ver DDMS> Explorar archivos

encuentre su archivo db a partir del nombre de su paquete

luego haga clic en extraer un archivo del dispositivo (solo dispositivo rooteado)

MAC
fuente
3
esto se puede hacer pero en un dispositivo rooteado, que es el punto de mi pregunta, cómo hacerlo en un dispositivo no rooteado
DeX03
1
esto no funciona en un dispositivo no rooteado. Tu respuesta debería indicar eso.
tony9099