Android-拉SQlite数据库android设备


99

我到处都看过了,找不到真正的准确答案,也找不到关于如何执行此操作的教程。

是否有可能以任何方式提取Android设备的数据库而无需将其root?我只需要以任何方式提取该数据以便将其收集到我的PC上,那么我该如何执行呢?我是否需要对应用程序或您知道的任何方法进行重新编程,但是请记住不要生根设备。谢谢


这是可行的解决方案:stackoverflow.com/a/29257875/291427
kmalmur 2015年



Answers:


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
好吧,我要在没有SD卡的三星银河标签上使用它,那我该怎么办?
DeX03'4

而且,我必须使用double //?
DeX03 2012年

是的,这是因为/是特殊字符串char。//您的“ //”中的结果为/。
KarlKarlsom 2012年

4
SQLiteDatabase具有构建getPath方法,而不是构建数据库路径。
2014年

辉煌的答案。非常聪明,有用和简单。
Gundu Bandgar '17

179

如果您的设备运行的是Android v4或更高版本,则可以使用命令在没有 root用户的情况下提取应用数据(包括数据库)adb backup,然后提取备份文件并访问sqlite数据库。

首先使用以下命令通过USB电缆将应用程序数据备份到您的PC,然后替换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 2013年

2
对于unpack命令不可用的Windows用户,可以使用“ Android Backup Extractor” Java应用程序(sourceforge.net/projects/adbextractor)。有关解压缩.ab文件的命令,请参见forum.xda-developers.com/showthread.php?t=2011811
lalitm 2014年

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从调试应用程序中删除数据库!
某处某人2014年

12
专家提示:如果应用的清单显示此备份内容将不起作用android:allowBackup="false"
某处某人2014年

9
openssl在Mac OS X上也不支持该zlib命令,因此我用brew:重新安装了该命令brew reinstall openssl。这不会取代您的系统openssl。因此,我仅针对当前会话修改了PATH命令:export PATH=/usr/local/opt/openssl/bin:$PATH此后可以成功执行此答案中的命令。
Aleks N.

69

对于非root用户设备上的可调试应用程序 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或使用cd命令对android sdk文件夹platform-tools进行设置。

例:

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

然后使用上面的命令


1请注意,Play商店中的大多数应用程序不可调试,因为它需要在清单中设置可调试标志


8
在我替换package.name为应用程序的软件包后,将返回错误:run-as: Package 'com.my.app' is unknown
某处某人

3
似乎不适用于所有手机。例如,适用于Nexus 4的产品不适用于SGS4。
Roman Minenok

2
数据库文件保存在哪里?
VojtěchPešek

3
这曾经对我有用,但是我似乎无法在更新到Android 5的Nexus 7上使用它。有人能确认这在Android 5上可以工作吗?
treeAreEverywhere

15
这是针对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 / [package_name] / databases / / sdcard / tempDB /。” 亚行拉sdcard / tempDB /。亚行外壳程序“ 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"启动SSHDroid启动FileZilla并通过SFTP协议连接到手机。将/ mnt / sdcard设置为默认远程目录。
佐尔坦SULE

想获得自己应用程序的数据库时最简单的答案。还有两个补充:1)如果不确定数据库名称,可以使用ls命令列出数据库文件夹(adb -d shell "run-as your.package.name ls databases")中的文件,以及2)您可能希望将任何其他关联文件与数据库一起获取,在我的案例中提取-smh和-wal文件是获取SQLite数据库浏览器打开数据库的唯一方法
Ronan

36

如果应用程序在非root用户的设备上以调试模式运行,则使用Android Studio 3.0或更高版本可以提取数据库(共享首选项,缓存目录等)。

要使用android studio拉数据库,请按照以下步骤操作。

  1. 单击视图 > 工具窗口 > 设备文件资源管理器
  2. 展开/ data / data / [package-name]节点。

Android Studio 3.0中遵循的步骤


谢谢。从仿真器下载文件,但无法从无根的Galaxy S4获取文件。
CoolMind

您可以从任何应用程序中提取数据库,还是仅从自己的应用程序中提取数据库?
live-love

除前提条件外,任何应用程序都必须是可调试的。
Shahidul

6
 adb shell "run-as [package.name] chmod -R 777 /data/data/[package.name]/databases" 
 adb shell "mkdir -p /sdcard/tempDB" 
 adb shell "cp -r /data/data/[package.name]/databases/ /sdcard/tempDB/." 
 adb pull sdcard/tempDB/ . 
 adb shell "rm -r /sdcard/tempDB/*"

5

对于Ubuntu(不仅如此):

请参阅Sergeis答案,但请使用zlib-flate而不是openssl:

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

否则,openssl可能会抛出:

openssl:Error:'zlib'是无效的命令。

因为在Ubuntu中没有使用zlib支持编译openssl


1

既然如此,对我来说什么都没有。我根据结合在一起的其他答案创建了一个Windows BATCH脚本。希望对别人有帮助。简单用法:backupDatabase <包名称> <应用程序名称> [TargetDirectory]。它使用Sergei的备份方法和Android Backup Extractor

@echo off

if [%1]==[] goto usage
if [%2]==[] goto usage
if NOT [%4]==[] goto usage

@echo Processing: preparations
set PACKAGE=%1
set APPLICATION_NAME=%2
set TARGET_DIR=%cd%
IF NOT "%~3"=="" set TARGET_DIR=%3

set PATH_ADB="c:\Program Files (x86)\Android\android-studio\sdk\platform-tools"
set PATH_ABE="c:\Programs\android-backup-extractor-20140630-bin"
set PATH_7Z="c:\Program Files\7-Zip"

@echo Processing: backup
%PATH_ADB%\adb.exe backup -f %TARGET_DIR%\%APPLICATION_NAME%\%APPLICATION_NAME%.ab -noapk %PACKAGE%

@echo Processing: unpack
java -jar %PATH_ABE%\abe.jar unpack %TARGET_DIR%\%APPLICATION_NAME%\%APPLICATION_NAME%.ab %TARGET_DIR%\%APPLICATION_NAME%\%APPLICATION_NAME%.ab.tar

@echo Processing: extract
cd %TARGET_DIR%\%APPLICATION_NAME%
%PATH_7Z%\7z.exe e %APPLICATION_NAME%.ab.tar "apps\%PACKAGE%\db\%APPLICATION_NAME%"

@echo Processing: cleaning
del %APPLICATION_NAME%.ab
del %APPLICATION_NAME%.ab.tar
goto :eof

:usage
@echo.Pull out SQLite database file from your android device.
@echo.Needs: - connected device
@echo.       - device enable backup.
@echo.       - application enable backup
@echo.       - application in debug mode
@echo.       - installed Android Backup Extractor 
@echo.       - installed command line TAR extractor (7z, ...)
@echo.Does NOT need: root device
@echo.
@echo.Uses: - ADB backup (set PATH_ADB)
@echo.      - Android Backup Extractor (http://sourceforge.net/projects/adbextractor/) (set PATH_ABE)
@echo.      - Extract TAR container, uses 7z (set PATH_7Z)
@echo.
@echo.Usage: backupDatabase ^<PackageName^> ^<ApplicationName^> [TargetDirectory]
@echo.Example: backupDatabase com.foo.example ExampleApp 
@echo Example: backupDatabase com.foo.example ExampleApp workspace\AndroidProjects\Example
exit /B 1

1

您可以轻松地从设备中提取sqlite文件(无需root)

  1. 转到SDK文件夹
  2. cd平台工具
  3. 启动adb

    cd / sdk / platform-tools ./adb shell

    然后在终端中键入以下命令

    ./adb -d shell“以com.your_packagename cat /data/data/com.your_packagename/databases/jokhanaNepal> /sdcard/jokhana.sqlite运行”

    ,例如

    ./adb -d shell“以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。允许将数据库下载为文件或直接在浏览器中编辑值。无需root,非常易于使用。


1

在Mac上(无需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

它将在平台工具文件夹中复制sqlite文件。


这似乎只有在编译应用程序进行调试时才起作用。
David Berry

@DavidBerry是的,如果为调试而编译,它将拉动db,否则您可能拉过任何应用程序的db。这将是应用程序的严重安全问题。:)
Yogesh Suthar '18

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%肯定,但是我认为在需要拉之前> su并给予许可
pavol.franek 2015年

0

根据Lam Vinh给出的答案,这是一个简单的批处理文件,可在我的第一代Nexus 7上使用。它提示用户输入程序包名称,然后输入数据库名称(不带.sqlite扩展名),并将其放入在c:\ temp。假设您在环境变量中设置了Android sdk。

@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,则这是一个ruby脚本,它将您的应用程序内容保存到桌面。我想这也可以在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还原到PC)。

我已经完成了两种方法,一种用于保存,另一种用于还原数据库。在MainActivity的onCreate()末尾使用这些方法(如果要保存或还原数据库,则使用一个或另一个)。

将数据库保存到内部存储中:

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脚本,使用ADB从设备复制db文件的原因。如果您经常这样做,可以节省很多开发时间。

如果设备未植根,则仅适用于可调试的应用程序

这是要点的链接。

运行为: 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>文件浏览

从包名称中找到您的数据库文件

然后单击“从设备中拉出文件”(仅根设备)


3
可以做到这一点,但是要在有根设备上进行操作,这是我的问题的重点,如何在没有根的设备上进行操作
DeX03 2012年

1
这不适用于无根设备。您的答案应说明这一点。
tony9099
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.