Android - витягнення Android-пристрою бази даних SQlite


100

Я шукав всюди, і я не можу знайти справжню точну відповідь чи підручник щодо того, як це можливо зробити.

чи можна будь-яким чином витягнути базу даних пристрою Android, не виконуючи його? мені просто потрібно витягти ці дані будь-яким чином, щоб зібрати їх на моєму ПК, так як я можу це виконати? чи потрібно мені перепрограмувати додаток чи будь-який інший метод, про який ви знаєте, але пам’ятайте, не вкорінюючи пристрій. Дякую


ось здійсненне рішення: stackoverflow.com/a/29257875/291427
kmalmur


1
stackoverflow.com/questions/13006315 Потягніть db без вкорінення
Naveen Prince P

Відповіді:


78

Поширений спосіб досягти того, що ви хочете, - використовувати команду ADB pull.

Інший спосіб, який я віддаю перевагу в більшості випадків - це скопіювати базу даних за кодом на 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) {

}

Не забудьте встановити дозвіл на запис на SD у своєму маніфесті, як нижче.

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

1
добре, я буду використовувати це на вкладці галактики samsung, на якій немає SD-карти, то як мені це зробити?
DeX03

і, я повинен використовувати подвійний //?
DeX03

Так, це тому, що / є настільки ж спеціальним рядком char. // у вашому "//" призведе до /.
KarlKarlsom

4
Замість того, щоб будувати шлях до бази даних, у SQLiteDatabase є getPathметод.
Чи буде

Блискуча відповідь. дуже розумний, корисний і простий.
Гунду Бандгар

179

Якщо на вашому пристрої працює Android v4 або новішої версії, ви можете витягувати дані додатків, включаючи базу даних, без кореня за допомогою adb backupкоманди, а потім витягувати файл резервної копії та отримувати доступ до бази даних sqlite.

Спочатку резервні копії даних програми на ПК через кабель USB із наступною командою замініть app.package.nameфактичною назвою пакета програми.

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

Це запропонує вам "розблокувати пристрій і підтвердити операцію резервного копіювання". Не надайте пароль для шифрування резервного копіювання , щоб ви могли його витягнути пізніше. Натисніть кнопку "Завантажити мої дані" на своєму пристрої. На екрані відображатиметься назва пакета, який ви створюєте резервну копію, а потім закривайтесь самостійно після успішного завершення.

Отриманий data.abфайл у вашій домашній папці містить дані програми у форматі резервного копіювання Android. Для його вилучення використовуйте таку команду:

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

Якщо вищезазначене закінчилося openssl:Error: 'zlib' is an invalid command.помилкою, спробуйте нижче.

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

Результат - apps/app.package.name/папка, що містить дані програми, включаючи базу даних sqlite.

Для отримання більш детальної інформації ви можете ознайомитися з оригінальною публікацією в блозі .


9
Для тих, у кого zlib не зібраний без zlib, перегляньте відповідь на blog.shvetsov.com/2013/02/…, щоб отримати дані з python.
ingh.am

2
Для користувачів Windows, де команда розпакування недоступна, ви можете скористатись додатком Java "Android Backup Extractor" ( sourceforge.net/projects/adbextractor ). Див. Forum.xda-developers.com/showthread.php?t=2011811 про команди, щоб розпакувати файл .ab.
лалітм

7
на моєму MacBook Pro я отримую повідомлення openssl:Error: 'zlib' is an invalid command., на яке я відповів dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -ЗАРАЗ, після того, як воно покаже, 17+0 records in17+0 records out17 bytes transferred in 0.000064 secsщо в папці немає жодних доказів. Оскільки це всього 17 байт, я вважаю, що команда також не вдалася. Я думаю, це погано, як я не можу adb pullбазу даних з програми налагодження !!
Хтось десь

12
поради: цей резервний матеріал не працюватиме, якщо маніфест програми показуєandroid:allowBackup="false"
Хтось десь

9
Мій opensslна Mac OS X теж не підтримував zlibкоманду, тому я перевстановив один з brew : brew reinstall openssl. Це не замінить вашу систему openssl. Тому я змінив команду PATH лише для поточного сеансу: export PATH=/usr/local/opt/openssl/bin:$PATHпісля цього можна було успішно виконувати команди з цієї відповіді.
Алекс Н.

69

Для налагоджувальних програм 1 на не вкорінених пристроях ви можете використовувати таку команду:

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

Приклад:

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

Встановіть PATH adb для Enviroment Variables або використовуйте команду cd для платформи-інструментів для папок Android sdk.

Приклад:

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

потім скористайтесь командою вище


1 Зауважте, що більшість додатків у магазині Play не підлягають налагодженню, оскільки для цього потрібно встановити прапор для налагодження в маніфесті.


8
Після заміни package.nameпакетом програми помилка повертається:run-as: Package 'com.my.app' is unknown
Хтось десь

3
Здається, це працює не для всіх телефонів. Працює для Nexus 4, наприклад, не працює для SGS4.
Роман Міненок

2
Де збережений файл db?
Vojtěch Pešek

3
Це працювало для мене, але я не можу зробити так, щоб це працювало на моєму Nexus 7, який оновився до Android 5. Чи може хтось підтвердити, що це працює на Android 5?
дереваAreEverywhere

15
Ось хак для оболонки adb для Android 5 (Lollipop) "run-as [package_name] chmod -R 777 / data / data / [package_name] / databases" adb shell "mkdir -p / sdcard / tempDB" adb shell "cp -r / дані / дані / [ім'я пакета] / бази даних / / sdcard / tempDB /. " adb pull sdcard / tempDB /. adb shell "rm -r / sdcard / tempDB / *"
Rubin Yoo

55

Більшість відповідей тут набагато складніші, ніж вони мають бути. Якщо ви просто хочете скопіювати базу даних свого додатка з телефону на комп'ютер, тоді вам знадобиться лише ця команда:

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

Все, що вам потрібно заповнити вищевказану команду, - це назва пакету вашої програми, як називається база даних і, необов'язково, що / куди ви бажаєте скопіювати базу даних.

Зверніть увагу, що ця конкретна команда працюватиме лише у тому випадку, якщо до комп'ютера підключено лише один пристрій. В -dозначає параметр , що тільки підключений пристрій буде адресуватися. Але є й інші параметри, які ви можете використовувати замість цього:

  • -e буде націлений на єдиний запущений емулятор
  • -s <serialnumber> буде націлено на пристрій із певним серійним номером.


Як я можу відкрити цей файл?
Єхад

@Jehad: У мене була така ж проблема. Я знайшов такий спосіб, і це працює для мене. Встановіть SSHDroid на свій телефон, adb -d shell "run-as your.package.name cat databases/database_name.db > /mnt/sdcard/database_name.db" запустіть SSHDroidFileZilla та підключіться до телефону за допомогою протоколу SFTP. Встановити / mnt / sdcard як віддалений каталог за замовчуванням.
Zoltán Süle

Найпростіша відповідь, коли ви хочете отримати базу даних власного додатка. Два доповнення: 1) якщо ви не впевнені у своєму імені бази даних, ви можете скористатися командою ls для переліку файлів у папці бази даних ( adb -d shell "run-as your.package.name ls databases") та 2), можливо, ви захочете отримати будь-які інші пов’язані файли разом із базою даних, у мій випадок файлів -smh і -wal був єдиним способом змусити браузер DB для SQLite відкрити базу даних
Ronan

36

За допомогою Android Studio 3.0 або новішої версії можна витягнути базу даних (також спільні настройки, каталог кешу та інші), якщо програма працює в режимі налагодження на не вкоріненому пристрої.

Щоб витягнути базу даних за допомогою андроїд-студії, виконайте ці кроки.

  1. Клацніть Перегляд > Інструмент Windows > Провідник файлів пристроїв .
  2. Розгорніть / дані / дані / [ім'я пакета] .

Кроки виконуються в Android Studio 3.0


Дякую. Завантажені файли з емулятора, але не вдається отримати їх з укорінених Galaxy S4.
CoolMind

Чи можете ви витягнути базу даних із будь-якого додатка чи просто з власного додатка?
live-love

Будь-який додаток, окрім передумови - додаток, має бути налагоджуваним.
Шахідул

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

Для Ubuntu (не тільки?):

див. відповідь Сергія, але замість openssl використовуй zlib-flate:

кішка appbackup.ab | (dd bs = 24 count = 0 пропустити = 1; cat) | zlib-flate -uncompress> appbackup.tar

Інакше openssl, ймовірно, кине:

openssl: Помилка: 'zlib' - недійсна команда.

тому що openssl не компілюється з підтримкою zlib в Ubuntu


1

Оскільки для мене нічого насправді не працює. Я створюю невеликий сценарій BATCH для Windows на основі інших відповідей, об'єднаних разом. Сподіваюся, це допоможе комусь. Просто використання: backupDatabase <PackageName> <ApplicationName> [TargetDirectory]. Для цього використовується метод резервного копіювання Сергія та екстрактор резервного копіювання Android .

@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

ви можете легко витягнути файл sqlite зі свого пристрою (root не потрібен)

  1. Перейдіть до папки SDK
  2. CD-платформи-інструменти
  3. почати adb

    Потім введіть наступну команду в терміналі: cd / sdk / platform-tools ./adb shell

    ./adb -d оболонка "run-as com.your_packagename cat /data/data/com.your_packagename/databases/jokhanaNepal> /sdcard/jokhana.sqlite"

    Для напр.

    ./adb -d оболонка "run-as com.yuvii.app cat /data/data/com.yuvii.app/databases/jokhanaNepal> /sdcard/jokhana.sqlite"


1

Якщо ви намагаєтеся це зробити на android 6, запитайте дозвіл і використовуйте код відповіді на це питання

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

Як тільки це буде надано

@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

Крім того, ви можете використовувати мою бібліотеку Ultra Debugger . Це дозволяє завантажувати базу даних у вигляді файлу або редагувати значення безпосередньо в браузері. Корінь не потрібен, дуже простий у використанні.


1

На Mac (НЕ потрібен корінь)

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

Він скопіює файл sqlite у папку інструментів платформи.


Здається, це працює лише в тому випадку, якщо додаток складено для налагодження.
Девід Беррі

@DavidBerry Так, це потягне db, якщо його буде складено для налагодження, інакше ви могли б витягнути будь-який db програми. І це буде серйозна проблема безпеки програми. :)
Йогеш Сутар

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

так, якщо ваш додаток для Android створює файлову копію бази даних, доступну для всіх.

android захищає приватні дані додатків, щоб вони не були видимими / доступними для інших додатків. база даних - це приватні дані. Ваш додаток, звичайно, може читати файл бази даних, щоб він міг зробити копію файлу у якийсь загальнодоступний файл.


0

На вкоріненому пристрої ви можете:

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

Я не впевнений на 100%, але думаю, що перед тим, як потягнути потрібен> су і дати дозвіл
pavol.franek

0

Виходячи з відповіді Лам Він, ось простий пакетний файл, який працює для мене на моєму Nexus 7. 1-го покоління. Він пропонує користувачеві ввести ім'я пакета, а потім ім'я бази даних (без розширення .sqlite) і поставить його в c: \ temp. Це передбачає, що у вас є встановлений sdk Android для змінних оточення.

@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

Якщо ви перебуваєте на Android 4.0 або новішої версії, а ви перебуваєте на комп'ютері mac , то ось сценарій рубіну, який збереже вміст програми на робочому столі. Я думаю, що це також спрацює в Ubuntu, хоча я цього не перевіряв.

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

запустити -> ruby ​​your_ruby_file_name.rb

Цей сценарій призначений лише для "щасливого шляху", тому переконайтеся, що ваш пристрій підключено та додано adb до вашого профілю.


0

Я даю повне рішення "зберегти" та "відновити" базу даних додатків у / з внутрішнього сховища (не на ПК із adb).

Я зробив два способи: один для збереження та інший для відновлення бази даних. Використовуйте ці методи в кінці onCreate () в MainActivity (той чи інший, якщо ви хочете зберегти або відновити базу даних).

зберегти базу даних до внутрішнього сховища:

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

відновити базу даних із внутрішнього сховища:

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

Завжди краще, якщо все буде автоматизовано. Ось чому я написав простий скрипт python для копіювання db-файлу з пристрою за допомогою ADB. Це економить багато часу на розробку, якщо ви робите це часто.

Працює лише з налагоджуваними програмами, якщо пристрій не вкорінений.

Ось посилання на суть.

Виконайте це як: 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

Якщо ви хочете, щоб ваш файл бази даних

Див. Розділ DDMS> Файл

знайдіть свій db-файл із імені пакета

потім натисніть на витягнути файл із пристрою (лише з укоріненим пристроєм)


3
це можна зробити, але на вкоріненому пристрої, в чому полягає питання мого питання, як це зробити на не вкоріненому пристрої
DeX03,

1
це не працює на не вкоріненому пристрої. У вашій відповіді має бути зазначено, що.
tony9099
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.