我到处寻找,如果有可能的话,我找不到真正准确的答案或教程。
是否可以以任何方式提取Android设备的数据库而无需root用户?我只需要以任何方式提取数据,以便将它收集到我的电脑上,那么我该如何执行此操作呢?我是否需要重新编程应用程序或您知道的任何方法,但请记住,不要使用设备。感谢
答案 0 :(得分:177)
如果您的设备运行的是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。
答案 1 :(得分:76)
实现所需目标的常用方法是使用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" />
答案 2 :(得分:68)
对于非root设备上的 debuggable apps 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
为Enviroment Variables设置PATH adb或使用cd命令到android sdk文件夹platform-tools。
示例:
cd /folder/android-sdk/platform-tools/
然后使用上面的命令
1 请注意,Play商店中的大多数应用都是无法调试,因为它需要在清单中设置debuggable flag。
答案 3 :(得分:52)
这里的大部分答案都比以前更加复杂。如果您只想将应用程序的数据库从手机复制到计算机,那么您只需要以下命令:
adb -d shell "run-as your.package.name cat databases/database.name" > target.sqlite
您需要在上面的命令中填写的是您的应用程序的包名称,数据库的调用内容以及您希望将数据库复制到的位置/位置。
<子>
请注意,只有当您的计算机只连接了一台设备时,此特定命令才有效。 -d
参数表示将定位唯一连接的设备。但是您可以使用其他参数:
-e
将定位唯一正在运行的模拟器-s <serialnumber>
将定位具有特定序列号的设备。
答案 4 :(得分:33)
如果应用程序在非root设备上以调试模式运行,则使用Android Studio 3.0或更高版本可以提取数据库(也可以是共享首选项,缓存目录等)。
使用android studio提取数据库请按照以下步骤操作。
答案 5 :(得分: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/*"
答案 6 :(得分:5)
对于Ubuntu(不仅仅是?):
请参阅Sergeis Answer,但请使用zlib-flate代替openssl:
cat appbackup.ab | (dd bs = 24 count = 0 skip = 1; cat)| zlib的-flate -uncompress&gt; appbackup.tar
否则openssl可能会抛出:
openssl:错误:'zlib'是无效的命令。
因为在Ubuntu中没有使用zlib支持编译openssl
答案 7 :(得分:1)
因为,没有什么对我有用。我根据其他答案组合在一起创建一个小的Windows BATCH脚本。希望它对某人有所帮助。简单用法:backupDatabase&lt; PackageName&gt; &LT; ApplicationName&gt; [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
答案 8 :(得分:1)
您可以轻松地从设备中提取sqlite文件(根本没必要)
启动adb
cd / sdk / platform-tools
./adb shell
然后在终端
./ adb -d shell“run-as com.your_packagename cat /data/data/com.your_packagename/databases/jokhanaNepal> /sdcard/jokhana.sqlite”
例如
./adb -d shell“run-as com.yuvii.app cat /data/data/com.yuvii.app/databases/jokhanaNepal> /sdcard/jokhana.sqlite”
答案 9 :(得分:1)
或者,您可以使用我的库Ultra Debugger。它允许将数据库作为文件下载或直接在浏览器中编辑值。不需要root,非常容易使用。
答案 10 :(得分: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")
答案 11 :(得分:0)
> is it possible to pull in any way a database of an Android device without having to root it?
是的,如果您的Android应用程序创建了每个人都可以访问的数据库的文件副本。
android保护应用私有数据,因此其他应用无法看到/访问它们。数据库是私有数据。 您的应用程序当然可以读取数据库文件,以便它可以将文件复制到一些公共可见文件。
答案 12 :(得分: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");
}
}
答案 13 :(得分:0)
如果您尝试在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();
}
}
}
答案 14 :(得分: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 -`
运行 - &gt; ruby your_ruby_file_name.rb
这个脚本是&#34;快乐的道路&#34;但是,请确保您的设备已连接,并且该adb已添加到您的个人资料中。
答案 15 :(得分: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
答案 16 :(得分:0)
在root设备上,您可以:
// 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
答案 17 :(得分:-1)
如果您需要数据库文件
参见DDMS&gt;文件探索
从包名中找到您的db文件
然后点击从设备中提取文件(仅限Root设备)