Android - 拉取 SQlite 数据库 android 设备

Posted

技术标签:

【中文标题】Android - 拉取 SQlite 数据库 android 设备【英文标题】:Android - Pulling SQlite database android device 【发布时间】:2012-04-17 09:14:45 【问题描述】:

我到处寻找,但找不到真正准确的答案或有关如何(如果可能)执行此操作的教程。

是否可以以任何方式提取 android 设备的数据库而无需 root ?我只需要以任何方式提取该数据以便在我的电脑上收集它,那么我该如何执行呢?我是否必须重新编程应用程序或你们知道的任何方法,但请记住不要生根设备。谢谢

【问题讨论】:

这里是可行的解决方案:***.com/a/29257875/291427 ***.com/a/28558521/1939564 ***.com/questions/13006315 拉取数据库不root ***.com/a/18472135/1778421 【参考方案1】:

如果您的设备运行Android v4或更高版本,您可以使用adb backup命令提取应用程序数据,包括它的数据库,无需 root,然后提取备份文件并访问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 数据库。

更多详情可以查看original blog post。

【讨论】:

对于没有zlib编译没有zlib的人,请查看blog.shvetsov.com/2013/02/…上的答案以使用python提取数据。 对于无法使用 unpack 命令的 Windows 用户,您可以使用“Android Backup Extractor”Java 应用程序 (sourceforge.net/projects/adbextractor)。有关解压 .ab 文件的命令,请参阅 forum.xda-developers.com/showthread.php?t=2011811。 在我的 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 数据库很糟糕! 专业提示:如果应用的清单显示 android:allowBackup="false",此备份内容将不起作用 我在 Mac OS X 上的openssl 也不支持zlib 命令,所以我用brew 重新安装了一个:brew reinstall openssl。这不会取代您的系统 openssl。因此,我仅针对当前会话修改了 PATH 命令:export PATH=/usr/local/opt/openssl/bin:$PATH 之后可以成功执行此答案中的命令。【参考方案2】:

实现所需的常用方法是使用 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" />

【讨论】:

好吧,我将在没有 SD 卡的三星 Galaxy Tab 上使用它,我该怎么做呢? 而且,我必须使用双 //? 是的,这是因为 / 是特殊的字符串字符。 // 在你的“//”中将导致 /. SQLiteDatabase 没有建立数据库路径,而是有一个getPath 方法。 出色的答案。非常聪明,有用且简单。【参考方案3】:

对于非root设备上的debuggable apps1,您可以使用以下命令:

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 文件夹平台工具。

例子:

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

然后使用上面的命令


1请注意,Play 商店中的大多数应用都不可调试,因为它需要在清单中设置 debuggable flag。

【讨论】:

我把package.name换成应用的包后,返回错误:run-as: Package 'com.my.app' is unknown 似乎不适用于所有手机。适用于 Nexus 4,不适用于 SGS4。 db文件保存在哪里? 这曾经对我有用,但我似乎无法让它在我更新到 Android 5 的 Nexus 7 上工作。谁能确认这适用于 Android 5? 这是一个针对 Android 5(Lollipop) 的 hack 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 拉 sdcard/tempDB/ 。 adb shell "rm -r /sdcard/tempDB/*"【参考方案4】:

这里的大多数答案都比他们必须的要复杂得多。如果您只想将应用程序的数据库从手机复制到计算机,那么您只需要以下命令:

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

您需要在上面的命令中填写您的应用程序的包名称、数据库的名称以及您希望将数据库复制到的位置/位置。

请注意,此特定命令仅在您只有一个设备连接到您的计算机时才有效。 -d 参数意味着唯一连接的设备将成为目标。但是您可以使用其他参数:

-e 将针对唯一正在运行的模拟器 -s &lt;serialnumber&gt; 将针对具有特定序列号的设备。

【讨论】:

如何打开这个文件? @Jehad:我遇到了同样的问题。我找到了这种方式,它对我有用。 Install SSHDroid on your phone adb -d shell "run-as your.package.name cat databases/database_name.db &gt; /mnt/sdcard/database_name.db" 启动 SSHDroid 启动 FileZilla 并通过 SFTP 协议连接到您的手机。将 /mnt/sdcard 设置为默认远程目录。 当您想要获取您自己的应用程序的数据库时最简单的答案。两个补充:1)如果您不确定您的数据库名称,您可以使用 ls 命令列出数据库文件夹(adb -d shell "run-as your.package.name ls databases")中的文件和 2)您可能想要获取任何其他相关文件以及数据库,在我的情况下,提取 -smh 和 -wal 文件是让 DB Browser for SQLite 打开数据库的唯一方法 这也仅适用于应用可调试【参考方案5】:

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

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

    点击查看 > 工具窗口 > 设备文件资源管理器。 展开 /data/data/[package-name] 节点。

【讨论】:

谢谢。从模拟器下载的文件,而无法从无根的 Galaxy S4 获取它们。 您可以从任何应用程序中提取数据库,还是仅从您自己的应用程序中提取数据库? 任何应用,但前提是应用必须是可调试的。【参考方案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/*"

【讨论】:

【参考方案7】:

对于 Ubuntu(不仅?):

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

cat appbackup.ab | (dd bs=24 计数=0 跳过=1;猫)| zlib-flat -uncompress > appbackup.tar

否则openssl可能会抛出:

openssl:Error: 'zlib' is an invalid command.

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

【讨论】:

【参考方案8】:

从那以后,没有什么对我真正有用。我根据结合在一起的其他答案创建了一个小的 Windows BATCH 脚本。希望它可以帮助某人。简单用法:backupDatabase [TargetDirectory]。 它使用谢尔盖的备份方法和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

【讨论】:

【参考方案9】:

如果您尝试在 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();
         
     
 

【讨论】:

【参考方案10】:

您也可以使用我的库Ultra Debugger。它允许将数据库下载为文件或直接在浏览器中编辑值。无需root,非常容易使用。

【讨论】:

【参考方案11】:

在 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文件。

【讨论】:

这似乎只在应用程序为调试而编译时才有效。 @DavidBerry 是的,如果为调试而编译,它将提取数据库,否则您可以提取任何应用程序的数据库。这将是应用程序的严重安全问题。 :)【参考方案12】:
 > is it possible to pull in any way a database of an Android device without having to root it? 

是的,如果您的 android 应用程序创建了可供所有人访问的数据库的文件副本。

android 保护应用程序的私有数据,使其不被其他应用程序看到/访问。数据库是私有数据。 您的应用当然可以读取数据库文件,因此它可以将文件复制到某个公共可见文件。

【讨论】:

【参考方案13】:

在有根设备上,您可以:

// 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% 确定,但我认为在需要 pull 之前 > su 并给予许可【参考方案14】:

根据 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

【讨论】:

【参考方案15】:

如果您使用的是 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 已添加到您的个人资料中。

【讨论】:

【参考方案16】:

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

    转到 SDK 文件夹 cd 平台工具

    启动亚行

    cd /sdk/平台工具 ./adb 外壳 然后在终端输入以下命令

    ./adb -d shell "run-as 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"

【讨论】:

【参考方案17】:

我给出了完整的解决方案来“保存”和“恢复”应用程序数据库到/从内部存储(而不是使用 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");
        
    

【讨论】:

【参考方案18】:

如果事情是自动化的总是更好。这就是为什么我编写了简单的python脚本来使用 ADB 从设备复制 db 文件。如果您经常这样做,它可以节省大量的开发时间。

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

Here is link to the gist.

运行为: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")

【讨论】:

【参考方案19】:

如果你想要你的数据库文件

查看 DDMS > 文件探索

从你的包名中找到你的 db 文件

然后单击从设备中提取文件(仅限已获得根的设备)

【讨论】:

这可以在有根设备上完成,这是我的问题的重点,如何在没有根设备上完成 这不适用于非 root 设备。你的回答应该说明这一点。

以上是关于Android - 拉取 SQlite 数据库 android 设备的主要内容,如果未能解决你的问题,请参考以下文章

SQLite 在 Android 的应用

Android Sqlite

android开发之路09(浅谈SQLite数据库01)

Android探索之数据存储Sqlite的介绍及使用

android开发之 SQLite(数据库)

Android SQLite总结[转载]