Android - Puxando dispositivo Android do banco de dados SQlite

101

Procurei em todos os lugares e não consigo encontrar uma resposta precisa ou um tutorial sobre como, se possível, fazer isso.

é possível extrair de alguma forma um banco de dados de um dispositivo Android sem ter que fazer o root? Eu só preciso extrair esses dados de alguma forma para coletá-los no meu pc, então como posso fazer isso? Preciso reprogramar o aplicativo ou qualquer método que vocês conheçam, mas lembre-se sem fazer o root no dispositivo. obrigado

DeX03
fonte
aqui está a solução viável: stackoverflow.com/a/29257875/291427
kmalmur
1
stackoverflow.com/questions/13006315 Pull db sem enraizamento
Naveen Prince P

Respostas:

78

Uma maneira comum de conseguir o que deseja é usar o comando pull do ADB.

Outra maneira que prefiro na maioria dos casos é copiar o banco de dados por código para o cartão 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ão se esqueça de definir a permissão para escrever em SD em seu manifesto, como abaixo.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
KarlKarlsom
fonte
1
bem, vou usar isso em uma guia Samsung Galaxy que não tem um cartão SD, então como faço isso lá?
DeX03,
e, eu tenho que usar duplo //?
DeX03
Sim, isso ocorre porque / é um caractere de string especial. // em seu "//" resultará em /.
KarlKarlsom
4
Em vez de construir o caminho do banco de dados, SQLiteDatabase tem um getPathmétodo.
Será de
Resposta brilhante. muito inteligente, útil e simples.
Gundu Bandgar
179

Se o seu dispositivo estiver executando o Android v4 ou superior, você pode extrair dados do aplicativo, incluindo o banco de dados, sem root usando o adb backupcomando, em seguida, extrair o arquivo de backup e acessar o banco de dados sqlite.

Primeiro faça backup dos dados do aplicativo para o seu PC via cabo USB com o seguinte comando, substitua app.package.namepelo nome do pacote real do aplicativo.

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

Isso solicitará que você "desbloqueie o dispositivo e confirme a operação de backup". Não forneça uma senha para criptografia de backup , para que você possa extraí-la mais tarde. Clique no botão "Fazer backup dos meus dados" no seu dispositivo. A tela exibirá o nome do pacote do qual você está fazendo backup e, em seguida, fechará sozinha após a conclusão com êxito.

O data.abarquivo resultante em sua pasta de início contém dados do aplicativo no formato de backup do Android. Para extraí-lo, use o seguinte comando:

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

Se o acima terminar com openssl:Error: 'zlib' is an invalid command.erro, tente o seguinte.

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

O resultado é a apps/app.package.name/pasta que contém os dados do aplicativo, incluindo o banco de dados sqlite.

Para mais detalhes, você pode verificar a postagem original do blog .

Sergei
fonte
9
Para quem não compilou o zlib sem o zlib, verifique a resposta em blog.shvetsov.com/2013/02/… para extrair os dados com python.
ingh.am
2
Para usuários do Windows em que o comando unpack não está disponível, você pode usar o aplicativo Java "Android Backup Extractor" ( sourceforge.net/projects/adbextractor ). Consulte forum.xda-developers.com/showthread.php?t=2011811 para obter os comandos para descompactar o arquivo .ab.
lalitm
7
no meu MacBook Pro, recebo a mensagem openssl:Error: 'zlib' is an invalid command., à qual respondi com dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -NO ENTANTO, depois de mostrar que 17+0 records in17+0 records out17 bytes transferred in 0.000064 secsnão há evidência de que algo tenha sido feito na pasta. Como são apenas 17 bytes, presumo que o comando também falhou. Eu acho que é ruim como eu não consigo acessar adb pullo banco de dados de um aplicativo de depuração !!
Alguém em algum lugar
12
dica profissional: esse backup não funcionará se o manifesto do aplicativo for exibidoandroid:allowBackup="false"
Someone Somewhere
9
Meu opensslon Mac OS X não suportam zlibcomando ou, então, eu reinstalei o único com cerveja: brew reinstall openssl. Isso não substituirá o openssl do seu sistema. Portanto, modifiquei o comando PATH apenas para a sessão atual: export PATH=/usr/local/opt/openssl/bin:$PATHapós o que pude executar com êxito os comandos desta resposta.
Aleks N.
69

Para aplicativos depuráveis 1 em dispositivos não enraizados , você pode usar o seguinte comando:

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

Exemplo:

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

Defina PATH adb para variáveis ​​de ambiente ou use o comando cd para ferramentas de plataforma de pasta android sdk.

Exemplo:

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

então use o comando acima


1 Observe que a maioria dos aplicativos na Play Store não são depuráveis, pois requer a configuração do sinalizador depurável no manifesto.

Lam Vinh
fonte
8
Depois de substituir package.namepelo pacote do aplicativo, o erro é retornado:run-as: Package 'com.my.app' is unknown
Alguém em algum lugar
3
Parece que não funciona para todos os telefones. Funciona para Nexus 4, não funciona para SGS4, por exemplo.
Roman Minenok
2
Onde o arquivo db é salvo?
Vojtěch Pešek
3
Isso costumava funcionar para mim, mas não consigo fazer funcionar no meu Nexus 7, que foi atualizado para o Android 5. Alguém pode confirmar se isso funciona no Android 5?
treesAreEverywhere
15
Aqui está um hack para 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 / [nome_do_pacote] / bancos de dados / / sdcard / tempDB /. " adb pull sdcard / tempDB /. adb shell "rm -r / sdcard / tempDB / *"
Rubin Yoo
55

A maioria das respostas aqui é muito mais complicada do que deveria ser. Se você deseja apenas copiar o banco de dados do seu aplicativo do telefone para o computador, você só precisa deste comando:

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

Tudo o que você precisa preencher no comando acima é o nome do pacote do seu aplicativo, como o banco de dados é chamado e, opcionalmente, para qual / onde você deseja que o banco de dados seja copiado.

Observe que este comando específico só funcionará se você tiver apenas um dispositivo conectado ao computador. O -dparâmetro significa que o único dispositivo conectado será o alvo. Mas existem outros parâmetros que você pode usar em seu lugar:

  • -e terá como alvo o único emulador em execução
  • -s <serialnumber> terá como alvo um dispositivo com um número de série específico.

Xaver Kapeller
fonte
Como posso abrir este arquivo?
Jehad
@Jehad: Eu tive o mesmo problema. Eu encontrei esse caminho e funciona para mim. Instale o SSHDroid em seu telefone, adb -d shell "run-as your.package.name cat databases/database_name.db > /mnt/sdcard/database_name.db" inicie o SSHDroidFileZilla e conecte-se ao telefone via protocolo SFTP. Defina / mnt / sdcard como diretório remoto padrão.
Zoltán Süle
A resposta mais fácil quando você deseja obter o banco de dados de seu próprio aplicativo. Duas adições: 1) se não tiver certeza do nome do banco de dados, você pode usar um comando ls para listar os arquivos na pasta do banco de dados ( adb -d shell "run-as your.package.name ls databases") e 2) você pode querer obter quaisquer outros arquivos associados junto com o banco de dados, em meu caso extraindo os arquivos -smh e -wal era a única maneira de fazer o DB Browser for SQLite abrir o banco de dados
Ronan
36

Usando o Android Studio 3.0 ou versão posterior, é possível extrair o banco de dados (também preferência compartilhada, diretório de cache e outros) se o aplicativo for executado no modo de depuração em um dispositivo sem root.

Para obter o banco de dados usando o Android Studio, siga estas etapas.

  1. Clique em Exibir > Janelas de ferramentas > Gerenciador de arquivos do dispositivo .
  2. Expanda nós / data / data / [nome do pacote] .

Etapas seguidas no Android Studio 3.0

Shahidul
fonte
Obrigado. Arquivos baixados de um emulador, enquanto não consigo obtê-los do Galaxy S4 não rooteado.
CoolMind
Você pode extrair o banco de dados de qualquer aplicativo ou apenas do seu próprio aplicativo?
viver amor
Qualquer aplicativo, exceto a pré-condição, deve ser depurável.
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
fonte
5

Para Ubuntu (não só?):

veja a resposta de Sergeis, mas em vez de openssl use zlib-flate:

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

Caso contrário, o openssl provavelmente irá lançar:

openssl: Erro: 'zlib' é um comando inválido.

porque o openssl não é compilado com suporte zlib no Ubuntu

Murmel
fonte
1

Desde então, nada realmente funciona para mim. Eu crio um pequeno script BATCH do Windows baseado em outras respostas combinadas. Espero que ajude alguém. Simplesmente use: backupDatabase <PackageName> <ApplicationName> [TargetDirectory]. Ele usa o método de backup de Sergei e o 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
fonte
1

você pode facilmente extrair o arquivo sqlite do seu dispositivo (root não é necessário)

  1. Vá para a pasta SDK
  2. ferramentas de plataforma de cd
  3. iniciar adb

    cd / sdk / platform-tools ./adb shell

    Em seguida, digite o seguinte comando no terminal

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

    Por exemplo

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

yubaraj poudel
fonte
1

Se você está tentando fazê-lo no android 6, solicite a permissão e use o código de resposta desta pergunta

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

Assim que for concedido

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

Alternativamente, você pode usar minha biblioteca Ultra Debugger . Permite baixar o banco de dados como arquivo ou editar valores diretamente no navegador. Sem necessidade de root, muito fácil de usar.

BArtWell
fonte
1

No Mac (sem necessidade de 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

Ele copiará o arquivo sqlite na pasta platform-tools.

Yogesh Suthar
fonte
Isso parece funcionar apenas se o aplicativo for compilado para depuração.
David Berry
@DavidBerry Sim, ele irá puxar o banco de dados se compilado para depuração, caso contrário, você poderia puxar o banco de dados de qualquer aplicativo. E será um sério problema de segurança do aplicativo. :)
Yogesh Suthar
0
 > is it possible to pull in any way a database of an Android device without having to root it? 

sim, se seu aplicativo Android criar uma cópia de arquivo do banco de dados que pode ser acessada por todos.

O Android protege os dados privados dos aplicativos para que não sejam visíveis / acessíveis por outros aplicativos. um banco de dados são dados privados. seu aplicativo pode, é claro, ler o arquivo de banco de dados para que possa fazer uma cópia de arquivo para algum arquivo público visível.

k3b
fonte
0

Em um dispositivo com acesso root, você pode:

// 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
fonte
Não estou 100% certo, mas acho que antes de puxar é necessário> su e dar permissão
pavol.franek
0

Com base na resposta dada por Lam Vinh, aqui está um arquivo de lote simples que funciona para mim em minha primeira geração Nexus 7. Ele solicita que o usuário insira o nome do pacote e, em seguida, o nome do banco de dados (sem a extensão .sqlite) e o coloca em c: \ temp. Isso pressupõe que você tenha o SDK do Android definido nas variáveis ​​de 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
chutcher
fonte
0

Se você estiver no Android 4.0 ou superior e em um mac , aqui está um script ruby ​​que salvará o conteúdo do aplicativo na área de trabalho. Eu imagino que isso também funcione no Ubuntu, embora eu não tenha testado.

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 executar -> ruby ​​your_ruby_file_name.rb

Este script é apenas "happy path", portanto, certifique-se de que seu dispositivo esteja conectado e que o adb tenha sido adicionado ao seu perfil.

Swifty McSwifterton
fonte
0

Eu dou a solução completa para "salvar" e "restaurar" o banco de dados do aplicativo de / para o armazenamento interno (não para o PC com adb).

Eu fiz dois métodos, um para salvar e outro para restaurar o banco de dados. Use estes métodos no final de onCreate () em MainActivity (um ou outro se você quiser salvar ou restaurar o banco de dados).

salvar banco de dados no armazenamento 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 banco de dados do armazenamento 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 Digitais
fonte
0

É sempre melhor se as coisas forem automatizadas. É por isso que escrevi um script python simples para copiar o arquivo db do dispositivo usando ADB. Isso economiza muito tempo de desenvolvimento se você fizer isso com frequência.

Funciona apenas com aplicativos depuráveis se o dispositivo não tiver acesso root.

Aqui está o link para a essência.

Execute-o 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
fonte
-1

Se você quiser que seu arquivo de banco de dados

Veja o DDMS> Explorar Arquivos

encontre seu arquivo db a partir do nome do seu pacote

em seguida, clique em extrair um arquivo do dispositivo (apenas dispositivo enraizado)

MAC
fonte
3
isso pode ser feito em um dispositivo com root, que é o ponto da minha dúvida, como fazer em um dispositivo sem
root
1
isso não funciona em um dispositivo sem acesso root. Sua resposta deve indicar isso.
tony9099