一个人如何获取自己的Android应用程序的(私有)数据?


97

尝试使用拉出单个文件

adb pull /data/data/com.corp.appName/files/myFile.txt myFile.txt

失败于

failed to copy '/data/data/com.corp.appName/files/myFile.txt myFile.txt' to 'myFile.txt': Permission denied

尽管在设备上启用了USB调试。

我们可以通过古老的途径解决问题

adb shell
run-as com.corp.appName
cat files/myFile.txt > myFile.txt

但这对于一个以上的文件来说非常繁琐。

如何将目录/data/data/com.corp.appName/files拉到MacBook?

可以直接执行此操作,也可以通过`/ storage / sdcard0 / myDir(可以从此处继续进行Android文件传输)中的传输来执行此操作。

附加评论

可能只是在跑步

adb backup  -f myFiles com.corp.appName

将生成我要查找的文件。在这种情况下,我正在寻找一种方法来解压缩/解压生成的备份!


5
除非设备植根,否则您将无法做到这一点。
323go 2013年

我希望您错了,但以防万一,请提出您的评论以作为答复。您能否添加某种参考来备份您的想法?我想保存程序的错误版本所保存的所有垃圾文件,以确保将来我的较新版本的程序可以正常处理各种输入文件。
卡拉夫

1
这是否意味着可以将目录从world:-x更改为world:rx足够长的时间,以便能够提取文件?
卡拉夫

1
@Knossos尽管它是我的应用程序,但用户能够保存应用程序已存储在其设备上的私人数据的副本是否合法?毕竟,数据大概属于设备所有者,而不是应用程序作者。
卡拉夫

1
问题在于您如何区分所有者和恶意应用程序/程序,以尝试与您的应用程序私有数据进行交互。(其中可能包含用户的个人数据)
Knossos 2013年

Answers:


101

adb备份将写入一个特定于Android的存档:

adb backup  -f myAndroidBackup.ab  com.corp.appName

可以使用以下命令将该存档转换为tar格式:

dd if=myAndroidBackup.ab bs=4K iflag=skip_bytes skip=24 | openssl zlib -d > myAndroidBackup.tar

参考:

http://nelenkov.blogspot.ca/2012/06/unpacking-android-backups.html

在该链接中搜索“更新”。


或者,使用Android备份提取器从Android备份(.ab)文件提取文件。


5
bs=24 skip=1速度比bs=1 skip=24(在我的系统上,38.6 MB / s和1.7 MB / s
快得多

18
尚未使用zlib编译openssl的Python替代方法:(dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -来自上述来源)
OJFord 2014年

6
dd我的MacBook上的命令在工作中从未取得任何成功。相反,我使用java -jar ./abe.jar unpack data.ab data.tar。您可以从sourceforge.net/projects/adbextractor/files/?source=navbar
某处某人2014年

3
另外,我注意到我不得不强制关闭要备份其数据的应用程序,否则备份为空!(Android 4.4.2)与清单显示时的效果相同android:allowBackup="false"
某处某人

2
更好的是,直接将文件提取到本地目录中:dd if=myAndroidBackup.ab bs=24 skip=1 | openssl zlib -d | tar -x
mreichelt 2014年

50

我遇到了同样的问题,但是按照以下步骤解决了它:

$ adb shell
$ run-as {app-package-name}
$ cd /data/data/{app-package-name}
$ chmod 777 {file}
$ cp {file} /mnt/sdcard/

之后,您可以运行

$ adb pull /mnt/sdcard/{file}

1
谢啦!您还需要使用“ cp -r”使其成为递归副本。stackoverflow.com/questions/39961621/...
朱西西

31

这是对我有用的东西:

adb -d shell "run-as com.example.test cat /data/data/com.example.test/databases/data.db" > data.db

我将数据库直接打印到本地文件中。


3
正是这个命令导致我的数据库文件损坏。但我可以按照以下步骤进行操作:------ adb shell ------在shell运行run-as com.example.test 内------在shell运行内cat ...db > /mnt/sdcard/file.db------ adb pull /mnt/sdcard/file.db .------结束(对不起,换行符不起作用)
Kirill Oficerov '16

@KirillOficerov如果可以将这些命令写在一行中会很好
emen 16-10-8

需要1个文件时很好。一直在使用这个数据库。现在面对需要多个文件的情况。
戴夫·托马斯

由于某种原因,使用adb shell对我而言不起作用,但是遵循此答案并使用adb exec-out它就可以了!
EpicPandaForce

21

在MacOSX上,通过结合Calaf和Ollie Ford的回答,以下内容对我有用。

在命令行上(确保adb在您的路径中,我的位置在〜/ Library / Android / sdk / platform-tools / adb),并在您的android设备已插入并处于USB调试模式下,运行:

 adb backup -f backup com.mypackage.myapp

您的android设备会询问您是否允许备份数据。选择“备份我的数据”

等一下

文件备份将显示在运行adb的目录中。

现在运行:

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

现在,您将拥有一个backup.tar文件,您可以像这样解压缩:

 tar xvf backup.tar

并查看您的应用程序存储的所有文件。


您的Mac版本适用!注意:tar转换步骤adb backupddtar转换步骤在工作时均不提供任何状态,如果有大量数据,则可能需要几分钟。耐心一点!
MechEthan

2
我得到:“ zlib.error:解压缩数据时出错-3:不正确的标头检查”虽然我的备份要求输入密码进行加密。此python方法不要求输入密码来解密备份。上面示例中的注释中的abe.jar要求输入密码,但是使用该方法解压缩后,我没有获得所有文件。
戴夫·托马斯

我对abe.jar进行第二次加密备份的尝试成功了。
戴夫·托马斯

7

较新版本的Android Studio包括设备文件资源管理器,我发现这是一种方便的GUI方法,可以从开发的Nexus 7下载文件。

您必须确保已在设备上启用USB调试

  1. 单击视图>工具窗口>设备文件资源管理器,或单击工具窗口栏中的设备文件资源管理器按钮以打开设备文件资源管理器。
  2. 从下拉列表中选择一个设备。
  3. 在文件浏览器窗口中与设备内容进行交互。右键单击文件或目录以创建新文件或目录,将所选文件或目录保存到您的计算机上,上载,删除或同步。双击文件以在Android Studio中将其打开。

    Android Studio会将您以此方式打开的文件保存在项目外部的临时目录中。如果您对使用设备文件资源管理器打开的文件进行了修改,并且想要将所做的更改保存回设备,则必须手动将文件的修改后的版本上传到设备。

文件管理器

完整文件


6

您可以在下面使用此Shell脚本。它也可以从应用程序缓存中拉出文件,而不像该adb backup工具那样:

#!/bin/sh

if [ -z "$1" ]; then 
    echo "Sorry script requires an argument for the file you want to pull."
    exit 1
fi

adb shell "run-as com.corp.appName cat '/data/data/com.corp.appNamepp/$1' > '/sdcard/$1'"
adb pull "/sdcard/$1"
adb shell "rm '/sdcard/$1'"

然后,您可以像这样使用它:

./pull.sh files/myFile.txt
./pull.sh cache/someCachedData.txt

10
最好的部分是,当您不给出论据然后进行rm /sdcard/替代时,幸运的是没有-rf
TWiStErRob 2014年

3
您可以直接将其指向主机上的文件:“ adb shell运行-com.whatever.Fnord cat /data/data/com.whatever.Fnord/databases/logging.db> / tmp / foo”(其中/ tmp / foo是主机上的文件,而不是android设备上的文件)
James Moore

刚刚意识到@ dave-thomas不久前解决了这个问题。删除我的下注。
唐·哈奇

否:-(“除非修改此答案,否则您的投票现已锁定。”
Don Hatch

TBH我不明白这件事。除非目录为空,否则(原始)脚本将永远不会删除该目录(缺少-rf开关)。我没有检查,但是即使目录为空,我也怀疑脚本会删除目录,因为它是安装点。剧本看上去很危险,但是从来没有……
Tamas

5

如果您使用的是Mac机和一台三星手机,这是你必须做什么(因为run-as 不工作对三星和zlib 不工作在Mac)

  1. 备份应用程序的数据目录 adb backup -f /Users/username/Desktop/data.ab com.example

  2. 系统将要求您输入密码以在手机中加密,请勿输入任何密码。只需点击“备份我的数据”。请参阅如何进行备份?

  3. 成功备份后,您将data.ab在桌面中看到文件。现在我们需要将其转换为tar格式。

  4. 为此使用Android Backup Extractor下载 | 源代码

  5. 下载它,您将看到abe.jar文件。将此添加到您的PATH变量。

  6. 执行此操作以生成tar文件:java -jar abe.jar unpack /Users/username/Desktop/data.ab /Users/username/Desktop/data.tar

  7. 解压缩data.tar文件以访问所有文件


2
准确地遵循了这一点,data.tar只是将其提取为data.tar.cpgz@henry
user-44651

2

该答案基于我对其他答案的经验以及答案中的评论。我希望我可以帮助处于类似情况的人。

我正在通过终端在OSX上执行此操作。

以前,Vinicius Avellar的答案对我很有用。我只是大多数时候需要调试应用程序从设备中获取数据库。

今天,我有一个用例,其中需要多个私有文件。最后,我找到了两种适用于这种情况的解决方案。

  1. 将接受的答案与Someone Somewhere的OSX特定注释一起使用。创建一个备份,并使用第三方解决方案 sourceforge.net/projects/adbextractor/files/?source=navbar解压缩为tar。我将在此答案的底部写下有关该解决方案的更多经验。如果这是您想要的,请向下滚动。

  2. 我解决的一个更快的解决方案。我创建了一个脚本,用于提取多个文件,类似于Tamas的答案。之所以能够这样做,是因为我的应用程序是调试应用程序,并且可以在设备上运行方式。如果您无权运行-因为此方法不适用于OSX。

这是我的脚本,用于提取与读者共享的多个私人文件,读者也正在调查这个令人敬畏的问题;):

#!/bin/bash
#
# Strict mode: http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'

# 
# Usage: script -f fileToPull -p packageName
# 

# This script is for pulling private files from an Android device
# using run-as. Note: not all devices have run-as access, and
# application must be a debug version for run-as to work.
# 
# If run-as is deactivated on your device use one of the
# alternative methods here:
# http://stackoverflow.com/questions/15558353/how-can-one-pull-the-private-data-of-ones-own-android-app
# 
# If you have encrypted backup files use:
# sourceforge.net/projects/adbextractor/files/?source=navbar 
# From comments in the accepted answer in the above SO question
# 
# If your files aren't encrypted use the accepted answer 
# ( see comments and other answers for OSX compatibility )
# 
# This script is open to expansions to allow selecting 
# device used. Currently first selected device from
# adb shell will be used.

#Check we have one connected device
adb devices -l | grep -e 'device\b' > /dev/null

if [ $? -gt 0 ]; then
    echo "No device connected to adb."
    exit 1
fi

# Set filename or directory to pull from device
# Set package name we will run as
while getopts f:p: opt; do
    case $opt in
        f)
            fileToPull=$OPTARG
            ;;
        p)
            packageName=$OPTARG
            ;;
    esac
done;

# Block file arg from being blank
if [ -z "$fileToPull" ]; then
    echo "Please specify file or folder to pull with -f argument"
    exit 1
fi

# Block package name arg from being blank
if [ -z "$packageName" ]; then
    echo "Please specify package name to run as when pulling file"
    exit 1
fi

# Check package exists
adb shell pm list packages | grep "$packageName" > /dev/null
if [ $? -gt 0 ]; then
    echo "Package name $packageName does not exist on device"
    exit 1
fi

# Check file exists and has permission with run-as
fileCheck=`adb shell "run-as $packageName ls $fileToPull"`
if [[ $fileCheck =~ "Permission denied" ]] || [[ $fileCheck =~ "No such file or directory" ]]; then
    echo "Error: $fileCheck"
    echo "With file -> $fileToPull"
    exit 1
fi

# Function to pull private file
#
# param 1 = package name
# param 2 = file to pull
# param 3 = output file
function pull_private_file () {

    mkdir -p `dirname $3`

    echo -e "\033[0;35m***" >&2
    echo -e "\033[0;36m Coping file $2 -> $3" >&2
    echo -e "\033[0;35m***\033[0m" >&2

    adb shell "run-as $1 cat $2" > $3
}

# Check if a file is a directory
# 
# param 1 = directory to check
function is_file_dir() {

    adb shell "if [ -d \"$1\" ]; then echo TRUE; fi"
}

# Check if a file is a symbolic link
# 
# param 1 = directory to check
function is_file_symlink() {

    adb shell "if [ -L \"$1\" ]; then echo TRUE; fi"
}

# recursively pull files from device connected to adb
# 
# param 1 = package name
# param 2 = file to pull
# param 3 = output file
function recurse_pull_private_files() {

    is_dir=`is_file_dir "$2"`
    is_symlink=`is_file_symlink "$2"`

    if [ -n "$is_dir" ]; then

        files=`adb shell "run-as $1 ls \"$2\""`

        # Handle the case where directory is a symbolic link
        if [ -n "$is_symlink" ]; then
            correctPath=`adb shell "run-as $1 ls -l \"$2\"" | sed 's/.*-> //' | tr -d '\r'`
            files=`adb shell "run-as $1 ls \"$correctPath\""`
        fi

        for i in $files; do

            # Android adds nasty carriage return that screws with bash vars
            # This removes it. Otherwise weird behavior happens
            fileName=`echo "$i" | tr -d '\r'` 

            nextFile="$2/$fileName"
            nextOutput="$3/$fileName"
            recurse_pull_private_files "$1" "$nextFile" "$nextOutput"
        done
    else

        pull_private_file "$1" "$2" "$3"
    fi
}

recurse_pull_private_files "$packageName" "$fileToPull" "`basename "$fileToPull"`"

要旨: https //gist.github.com/davethomas11/6c88f92c6221ffe6bc26de7335107dd4


返回方法1,使用解密备份 Android Backup Extractor

以下是我在Mac上执行的步骤以及遇到的问题:

首先,我将备份排队(并设置密码以加密备份,我的设备需要它):

adb backup -f myAndroidBackup.ab  com.corp.appName

其次,我从这里下载了abe.jar:https ://sourceforge.net/projects/adbextractor/files/abe.jar/download

接下来我跑了:

java -jar ./abe.jar unpack myAndroidBackup.ab myAndroidBackup.tar

此时,我收到一条错误消息。因为我的存档已加密,所以java给我一个错误,我需要安装一些安全策略库。

  • 因此,我去了http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html并下载了我需要的安全策略jar。现在,就我而言,安装说明告诉我放置jar文件的位置错误。它说正确的位置是<java-home> / lib / security。我先把它们放在那里,仍然收到错误消息。因此,我进行了调查,在装有Java 1.8的Mac上,放置它们的正确位置是:<java-home> / jre / lib / security。我确保备份了原始的策略jar,并将其放在那里。我可以使用abe.jar输入密码,然后解密为tar文件。

最后,我刚运行(再次运行上一个命令后

tar xvf myAndroidBackup.tar

现在,重要的是要注意,如果您可以同时运行和运行,则速度要快得多。一,您只获得所需的文件,而不是整个应用程序。第二,更多的文件(对我而言+加密)使传输速度变慢。因此,如果您没有在OSX上运行,那么知道这样做的方法很重要,但是该脚本应该首先用于调试应用程序。

请注意,我今天才写它,并对其进行了几次测试,因此,如有任何错误,请通知我!


1
感谢您对方法1的答复,我已经能够从安装在生产环境中的无根设备上的调试目标应用程序获取并探索软件包备份,但是备份仅包含清单文件。使用方法2,我下载了所有应用程序的数据,但是二进制文件(即SQLite文件)不可读。我根据您的脚本添加了对我有用的解决方案。
Paolone

1

通过添加以下代码设置正确的权限后:

File myFile = ...;
myFile.setReadable(true, false); // readable, not only for the owner

adb pull 根据需要工作。

参见File.setReadable()


可以在调试时更改权限,但是在释放时这样做会破坏默认情况下提供的保护(以防止其他应用访问/处理文件)。因此,更希望开发人员即使文件只是用户可读/可写的方式访问文件。
卡拉夫

1

从Dave Thomas脚本开始,我已经能够编写自己的解决方案来克服2个问题:

  1. 我的备份仅包含清单文件
  2. Dave Thomas附带的二进制文件不可读

这是我的脚本,将应用程序数据复制到sdcard,然后将其拉出

#Check we have one connected device
adb devices -l | grep -e 'device\b' > /dev/null

if [ $? -gt 0 ]; then
    echo "No device connected to adb."
    exit 1
fi

# Set filename or directory to pull from device
# Set package name we will run as
while getopts f:p: opt; do
    case $opt in
        f)
            fileToPull=$OPTARG
            ;;
        p)
            packageName=$OPTARG
            ;;
    esac
done;

# Block package name arg from being blank
if [ -z "$packageName" ]; then
    echo "Please specify package name to run as when pulling file"
    exit 1
fi

# Check package exists
adb shell pm list packages | grep "$packageName" > /dev/null
if [ $? -gt 0 ]; then
    echo "Package name $packageName does not exist on device"
    exit 1
fi

    adb shell "run-as $packageName cp -r /data/data/$packageName/ /sdcard/$packageName"
    adb pull /sdcard/$packageName
    adb shell rm -rf /sdcard/$packageName

1

Tamas的答案类似,这是Mac OS X的一种方法,可your.app.id从您的设备中获取应用程序的所有文件并将其保存到(在这种情况下)~/Desktop/your.app.id

(
    id=your.app.id &&
    dest=~/Desktop &&
    adb shell "run-as $id cp -r /data/data/$id /sdcard" &&
    adb -d pull "/sdcard/$id" "$dest" &&
    if [ -n "$id" ]; then adb shell "rm -rf /sdcard/$id"; fi
)
  • -d从仿真器中排除
  • 不脚你的会话变量
  • 您可以将整个块粘贴到Terminal.app中(或根据需要删除换行符)

0

用apk备份游戏数据。牛轧糖Oneplus 2。

**adb backup "-apk com.nekki.shadowfight" -f "c:\myapk\samsung2.ab"**

adb backup -f myapp.ab -apk com.myapp # backup on one device adb restore myapp.ab # restore to the same or any other device
史蒂文·林恩

0

这是否意味着可以将目录从world:-x更改为world:rx足够长的时间,以便能够提取文件?

对,就是这样。奇怪的是,您还需要文件x设置该位。(至少在Android 2.3上)

chmod 755 一直以来都可以复制文件(但如果您打算继续使用该设备,则应在之后还原权限)。


0

你可以做:

adb pull / storage / emulated / 0 / Android / data //


2
别误会我的意思,但是,您是否已正确阅读问题?OP要求提取“私人”数据而不是 “公共” 数据
baburao
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.