Edit an app SharedPreferences [duplicate] - android

Attempting to pull a single file using
adb pull /data/data/com.corp.appName/files/myFile.txt myFile.txt
fails with
failed to copy '/data/data/com.corp.appName/files/myFile.txt myFile.txt' to 'myFile.txt': Permission denied
despite that USB debugging is enabled on the device.
We can go around the problem through the archaic route
adb shell
run-as com.corp.appName
cat files/myFile.txt > myFile.txt
but this is unwieldy for more than one file.
How can I pull the directory /data/data/com.corp.appName/files to my MacBook?
Doing this either directly or through a transit in `/storage/sdcard0/myDir (from where I can continue with Android File Transfer) is fine.
Additional Comment
It may be that just running
adb backup -f myFiles com.corp.appName
will generate the files I am looking for. In that case I am looking for a way to untar/unzip the resulting backup!

adb backup will write an Android-specific archive:
adb backup -f myAndroidBackup.ab com.corp.appName
This archive can be converted to tar format using:
dd if=myAndroidBackup.ab bs=4K iflag=skip_bytes skip=24 | openssl zlib -d > myAndroidBackup.tar
Reference:
http://nelenkov.blogspot.ca/2012/06/unpacking-android-backups.html
Search for "Update" at that link.
Alternatively, use Android backup extractor to extract files from the Android backup (.ab) file.

I had the same problem but solved it running following:
$ adb shell
$ run-as {app-package-name}
$ cd /data/data/{app-package-name}
$ chmod 777 {file}
$ cp {file} /mnt/sdcard/
After this you can run
$ adb pull /mnt/sdcard/{file}

Here is what worked for me:
adb -d shell "run-as com.example.test cat /data/data/com.example.test/databases/data.db" > data.db
I'm printing the database directly into local file.

On MacOSX, by combining the answers from Calaf and Ollie Ford, the following worked for me.
On the command line (be sure adb is in your path, mine was at ~/Library/Android/sdk/platform-tools/adb) and with your android device plugged in and in USB debugging mode, run:
adb backup -f backup com.mypackage.myapp
Your android device will ask you for permission to backup your data. Select "BACKUP MY DATA"
Wait a few moments.
The file backup will appear in the directory where you ran adb.
Now run:
dd if=backup bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" > backup.tar
Now you'll you have a backup.tar file you can untar like this:
tar xvf backup.tar
And see all the files stored by your application.

Newer versions of Android Studio include the Device File Explorer which I've found to be a handy GUI method of downloading files from my development Nexus 7.
You Must make sure you have enabled USB Debugging on the device
Click View > Tool Windows > Device File Explorer or click the Device File Explorer button in the tool window bar to open the Device File Explorer.
Select a device from the drop down list.
Interact with the device content in the file explorer window. Right-click on a file or directory to create a new file or directory, save the selected file or directory to your machine, upload, delete, or synchronize. Double-click a file to open it in Android Studio.
Android Studio saves files you open this way in a temporary directory outside of your project. If you make modifications to a file you opened using the Device File Explorer, and would like to save your changes back to the device, you must manually upload the modified version of the file to the device.
Full Documentation

You may use this shell script below. It is able to pull files from app cache as well, not like the adb backup tool:
#!/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'"
Then you can use it like this:
./pull.sh files/myFile.txt
./pull.sh cache/someCachedData.txt

If you are using a Mac machine and a Samsung phone, this is what you have to do (since run-as doesn't work on Samsung and zlib doesn't work on Mac)
Take a backup of your app's data directory
adb backup -f /Users/username/Desktop/data.ab com.example
You will be asked for a password to encrypt in your Phone, don't enter any. Just tap on "Back up my data". See How to take BackUp?
Once successfully backed up, you will see data.ab file in your Desktop. Now we need to convert this to tar format.
Use Android Backup Extractor for this. Download | SourceCode
Download it and you will see abe.jar file. Add this to your PATH variable.
Execute this to generate the tar file: java -jar abe.jar unpack /Users/username/Desktop/data.ab /Users/username/Desktop/data.tar
Extract the data.tar file to access all the files

After setting the right permissions by adding the following code:
File myFile = ...;
myFile.setReadable(true, false); // readable, not only for the owner
adb pull works as desired.
see File.setReadable()

This answer is based on my experience with other answers, and comments in the answers. My hope is I can help someone in a similar situation.
I am doing this on OSX via terminal.
Previously Vinicius Avellar's answer worked great for me. I was only ever most of the time needing the database from the device from a debug application.
Today I had a use case where I needed multiple private files. I ended up with two solutions that worked good for this case.
Use the accepted answer along with Someone Somewhere's OSX specific comments. Create a backup and use the 3rd party solution,
sourceforge.net/projects/adbextractor/files/?source=navbar to unpack
into a tar. I'll write more about my experience with this solution at the bottom of this answer. Scroll down if
this is what you are looking for.
A faster solution which I settled with. I created a script for pulling multiple files similar to Tamas' answer. I am able to do it
this way because my app is a debug app and I have access to run-as on
my device. If you don't have access to run-as this method won't work
for you on OSX.
Here is my script for pulling multiple private files that I'll share with you, the reader, who is also investigating this awesome question ;) :
#!/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"`"
Gist:
https://gist.github.com/davethomas11/6c88f92c6221ffe6bc26de7335107dd4
Back to method 1, decrypting a backup using Android Backup Extractor
Here are the steps I took on my Mac, and issues I came across:
First I queued up a backup ( and set a password to encrypt my backup, my device required it ):
adb backup -f myAndroidBackup.ab com.corp.appName
Second I downloaded just abe.jar from here: https://sourceforge.net/projects/adbextractor/files/abe.jar/download
Next I ran:
java -jar ./abe.jar unpack myAndroidBackup.ab myAndroidBackup.tar
At this point I got an error message. Because my archive is encrypted, java gave me an error that I needed to install some security policy libraries.
So I went to http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html and downloaded the security policy jars I needed. Now in my case the install instructions told me the wrong location to put the jar files. It says that the proper location is <java-home>/lib/security. I put them there first and still got the error message. So I investigated and on my Mac with Java 1.8 the correct place to put them was: <java-home>/jre/lib/security. I made sure to backup the original policy jars, and put them there. Vola I was able to enter a password with abe.jar and decrypt to a tar file.
Lastly I just ran ( after running previous command again )
tar xvf myAndroidBackup.tar
Now it is important to note that if you can just run-as and cat, it is much much faster. One, you only get the files you want and not the entire application. Two, the more files ( + encryption for me ) makes it slower to transfer. So knowing to do this way is important if you don't have run-as on OSX, but the script should be first goto for a debug application.
Mind you I just wrote it today and tested it a few times, so please notify me of any bugs!

Similar to Tamas's answer, here is a one-liner for Mac OS X to fetch all of the files for app with your.app.id from your device and save them to (in this case) ~/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
)
Exclude the -d to pull from emulator
Doesn't stomp your session variables
You can paste the whole block into Terminal.app (or remove newlines if desired)

Starting form Dave Thomas script I've been able to write my own solution to overcome 2 problems:
my backup was containing only the manifest file
binary files got with Dave Thomas where unreadable
This is my script, that copies app data to sdcard and then pull it
#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

Backed up Game data with apk. Nougat Oneplus 2.
**adb backup "-apk com.nekki.shadowfight" -f "c:\myapk\samsung2.ab"**

Does that mean that one could chmod the directory from world:--x to world:r-x long enough to be able to fetch the files?
Yes, exactly. Weirdly enough, you also need the file to have the x bit set. (at least on Android 2.3)
chmod 755 all the way down worked to copy a file (but you should revert permissions afterwards, if you plan to continue using the device).

you can do:
adb pull /storage/emulated/0/Android/data//

Related

How to pull photos with ADB from local storage - android device

i have some problems with my Asus Zenfone 2 device (no root).
In particular, some days ago, while i was travelling abroad, my device decided to no more turn on, staying permanently in the loading ASUS screen.
Before doing the hard reset, i want to try to save at least all my photos located in the internal storage (N.B: i do not have an external SDCARD).
i correctly set up the ADB software to recognize my device but i am not able to find the photo directory.
Till now i have only pull successfully 2 directory: "sys" and "cache", using this command:
adb pull / C:\Myfile
It seems to transfer only some file system.
Doas anyone know how to pull photos or other file?
Use adb pull sdcard/DCIM/Camera C:\MyFile
If it didn't work use:
adb shell
echo $EXTERNAL_STORAGE
It will print path to your simulated external storage. Then:
cd $EXTERNAL_STORAGE/DCIM
ls
It will print folder which will contain camera app folders. Lastly, use:
adb pull HERE_PUT_PATH_TO_EXTERNAL/DCIM/SELECTED_CAMERA_APP_FOLDER C:\MyFiles
Note: To leave adb shell type exit
I did 3 things to pull all files of the same type, in this case *.mp4 (all videos)
1. First copy the output of: {all videos listed} with xargs to a file.txt
adb shell ls /storage/7C17-B4FD/DCIM/Camera/*.mp4 | xargs -t -I % echo % >> file.txt
adb shell ls /storage/7C17-B4FD/DCIM/Camera/*.mp4 returns all videos listed in device.
The argument -t show the output from XARGS, and -I lets you use a variable, in this case represented with % then you write the command you want to do. In this case, echo % each line and add it to the file.txt
2. You need to clean the file.txt from spaces and the '\r' you do it with the command tr
tr -d '\r' < file.txt > text-clean.txt
the input file is < file.txt and the new output file is > text-clean.txt
3.Now you can cat the new clean file text-clean.txt and use that input with XARGS command to pass the command adb pull for each file.
cat text-clean.txt | xargs -t -I % adb pull % ./
we cat the content of text-clean.txt and send the output to XARGS, then we see what is the result of command with -t and -I to add variables. adb pull to request file from path which is represented with % and ./ means copy to this directory or currrent directory of where you are.
if you just need to copy one file. just need to find the file with adb shell ls /path/to/file and the just copy to your location with adb pull. example
adb pull /storage/7C717-B4FD/DCIM/Camera/video1.mp4 ./

Retrieve database or any other file from the Internal Storage using run-as

On a non-rooted android device, I can navigate to the data folder containing the database using the run-as command with my package name. Most files types I am content with just viewing, but with the database I would like to pull if from the android device.
Is there a download copy or move command from this part of adb shell? I would like to download the database file and view its content using a database browser.
One answer here involves turning entire application package into a compressed archive, but there is no further answer on how to extract that archive once this is done and moved to the machine, leaving me very sidetracked when there might be a more direct solution to begin with
By design user build of Android (that's what you have on your phone until you unlock the bootloader and flash the phone with userdebug or eng software) restricts access to the Internal Storage - every app can only access its own files. Fortunately for software developers not willing to root their phones Google provides a way to access the Internal Storage of debuggable versions of their packages using run-as command.
To download the /data/data/debuggable.app.package.name/databases/file from an Android 5.1+ device run the following command:
adb exec-out run-as debuggable.app.package.name cat databases/file > file
To download multiple files in a folder under the /data/data/debuggable.app.package.name/ at once - use tar:
adb exec-out run-as debuggable.app.package.name tar c databases/ > databases.tar
adb exec-out run-as debuggable.app.package.name tar c shared_prefs/ > shared_prefs.tar
The accepted answer doesn't work anymore for me (blocked by Android?)
So instead I did this:
> adb shell
shell $ run-as com.example.package
shell $ chmod 666 databases/file
shell $ exit ## exit out of 'run-as'
shell $ cp /data/data/package.name/databases/file /sdcard/
shell $ run-as com.example.package
shell $ chmod 600 databases/file
> adb pull /sdcard/file .
If anyone looking for pulling database from debug application may use the procedure below:
search and open device file explorer
Select your handset and then browse to data/data directory
Now find your application package and go to databases folder. You can see the databases there and upon right click, you will get option
to save this in your drive.
I've published a simple shell script for dumping databases:
https://github.com/Pixplicity/humpty-dumpty-android
It performs two distinct methods described here:
First, it tries to make the file accessible for other users, and attempting to pull it from the device.
If that fails, it streams the contents of the file over the terminal to the local machine. It performs an additional trick to remove \r characters that some devices output to the shell.
From here you can use a variety of CLI or GUI SQLite applications, such as sqlite3 or sqlitebrowser, to browse the contents of the database.
I couldn't get anything else to work for me but this:
adb shell
run-as package.name
cat /databases/databaseFileName.db > /sdcard/copiedDatabaseFileName.db
exit
exit
adb pull /sdcard/copiedDatabaseFileName.db /file/location/on/computer/
The first exit is to exit out of the run-as, the second exit is to exit out of adb shell to do the pull.
For app's debug version, it's very convenient to use command adb exec-out run-as xxx.yyy.zzz cat somefile > somefile to extract a single file. But you have to do multiple times for multiple files. Here is a simple script I use to extract the directory.
#!/bin/bash
P=
F=
D=
function usage()
{
echo "$(basename $0) [-f file] [-d directory] -p package"
exit 1
}
while getopts ":p:f:d:" opt
do
case $opt in
p)
P=$OPTARG
echo package is $OPTARG
;;
f)
F=$OPTARG
echo file is $OPTARG
;;
d)
D=$OPTARG
echo directory is $OPTARG
;;
\?)
echo Unknown option -$OPTARG
usage
;;
\:)
echo Required argument not found -$OPTARG
usage
;;
esac
done
[ x$P == x ] && {
echo "package can not be empty"
usage
exit 1
}
[[ x$F == x && x$D == x ]] && {
echo "file or directory can not be empty"
usage
exit 1
}
function file_type()
{
# use printf to avoid carriage return
__t=$(adb shell run-as $P "sh -c \"[ -f $1 ] && printf f || printf d\"")
echo $__t
}
function list_and_pull()
{
t=$(file_type $1)
if [ $t == d ]; then
for f in $(adb shell run-as $P ls $1)
do
# the carriage return output from adb shell should
# be removed
mkdir -p $(echo -e $1 |sed $'s/\r//')
list_and_pull $(echo -e $1/$f |sed $'s/\r//')
done
else
echo pull file $1
[ ! -e $(dirname $1) ] && mkdir -p $(dirname $1)
$(adb exec-out run-as $P cat $1 > $1)
fi
}
[ ! -z $D ] && list_and_pull $D
[ ! -z $F ] && list_and_pull $F
Hope it would be helpful. This script is also available at gist.
Typical usage is
$ ./exec_out.sh -p com.example.myapplication -d databases
then it will extract all files under your apps databases directory, which is /data/data/com.example.myapplication/databases, into current directory.
Much much simpler approach to download the file onto your local computer:
In your PC shell run:
adb -d shell 'run-as <package_name> cat /data/data/<package_name>/databases/<db_name>' > <local_file_name>
#!/bin/bash
#export for adb
export PATH=$PATH:/Users/userMe/Library/Android/sdk/platform-tools
export PATH=$PATH:/Users/userMe/Library/Android/sdk/tools
adb -d shell 'run-as com.android.app cp /data/data/com.android.app/files/db.realm /sdcard'
adb pull sdcard/db.realm /Users/userMe/Desktop/db
You can use this script for get Realm database.
The database file is emtpy when using adb run-as. This can be resolved by calling close() on the RoomDatabase instance. Call close() to let SQLite write its journal to disk.
I've created this button that closes the database connection on request: via GIPHY
Here is how to call close on the RoomDatabase instance.
Steps to pull app db(installed in debug mode) from device
Close DB connection if opened
Open cmd (command prompt) (Change dir to your adb path)
cd C:\Program Files (x86)\Android\android-sdk\platform-tools
(list the app files)
adb -d shell "run-as com.xyz.name ls
/data/data/com.xyz.name/files/"
(copy required file to sdcard)
adb -d shell "run-as com.xyz.name cp
/data/data/com.xyz.name/files/abc.db /sdcard/abc.db"
(copy from sdcard to machine adb folder)
adb pull /sdcard/abc.db
Open DB connection
Destination file path in my case C:\Users{userName}\AppData\Local\VirtualStore\Program Files (x86)\Android\android-sdk\platform-tools
Or Device storage
If someone is looking for another answer that can be used to retrieve Database as well as Shared Preferences then follow this step:
In your build.gradle file of your app add line
debugCompile 'com.amitshekhar.android:debug-db:1.0.0'
now when you run your app in non-release mode then your app will automatically open 8080 port from your device IP address make sure your device is connected via wifi and your laptop is sharing the same network. Now simply visit the url
http://your_mobile_device_ip:8080/
to watch all data of database along with shared preferences.
Here's a solution that works on a device running Android 5.1. The following example is for Windows.
You need sed (or sed.exe on windows, e.g. from cygwin.) ( On Unix, it'll just be there ;) ). To remove bad '\r' characters, at least on windows.
Now just run the following command:
adb exec-out "run-as com.yourcompany.yourapp /data/data/com.yourcompany.yourapp/databases/YourDatabaseName" | c:\cygwin\bin\sed.exe 's/\x0D\x0A/\x0A/'>YourDatabaseName.db
The sed command strips out trailing /r characters.
Of course you should replace "com.yourcompany.yourapp" with the package name of the app and "YourDatabaseName" with the name of the database in the app.

How can one pull the (private) data of one's own Android app?

Attempting to pull a single file using
adb pull /data/data/com.corp.appName/files/myFile.txt myFile.txt
fails with
failed to copy '/data/data/com.corp.appName/files/myFile.txt myFile.txt' to 'myFile.txt': Permission denied
despite that USB debugging is enabled on the device.
We can go around the problem through the archaic route
adb shell
run-as com.corp.appName
cat files/myFile.txt > myFile.txt
but this is unwieldy for more than one file.
How can I pull the directory /data/data/com.corp.appName/files to my MacBook?
Doing this either directly or through a transit in `/storage/sdcard0/myDir (from where I can continue with Android File Transfer) is fine.
Additional Comment
It may be that just running
adb backup -f myFiles com.corp.appName
will generate the files I am looking for. In that case I am looking for a way to untar/unzip the resulting backup!
adb backup will write an Android-specific archive:
adb backup -f myAndroidBackup.ab com.corp.appName
This archive can be converted to tar format using:
dd if=myAndroidBackup.ab bs=4K iflag=skip_bytes skip=24 | openssl zlib -d > myAndroidBackup.tar
Reference:
http://nelenkov.blogspot.ca/2012/06/unpacking-android-backups.html
Search for "Update" at that link.
Alternatively, use Android backup extractor to extract files from the Android backup (.ab) file.
I had the same problem but solved it running following:
$ adb shell
$ run-as {app-package-name}
$ cd /data/data/{app-package-name}
$ chmod 777 {file}
$ cp {file} /mnt/sdcard/
After this you can run
$ adb pull /mnt/sdcard/{file}
Here is what worked for me:
adb -d shell "run-as com.example.test cat /data/data/com.example.test/databases/data.db" > data.db
I'm printing the database directly into local file.
On MacOSX, by combining the answers from Calaf and Ollie Ford, the following worked for me.
On the command line (be sure adb is in your path, mine was at ~/Library/Android/sdk/platform-tools/adb) and with your android device plugged in and in USB debugging mode, run:
adb backup -f backup com.mypackage.myapp
Your android device will ask you for permission to backup your data. Select "BACKUP MY DATA"
Wait a few moments.
The file backup will appear in the directory where you ran adb.
Now run:
dd if=backup bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" > backup.tar
Now you'll you have a backup.tar file you can untar like this:
tar xvf backup.tar
And see all the files stored by your application.
Newer versions of Android Studio include the Device File Explorer which I've found to be a handy GUI method of downloading files from my development Nexus 7.
You Must make sure you have enabled USB Debugging on the device
Click View > Tool Windows > Device File Explorer or click the Device File Explorer button in the tool window bar to open the Device File Explorer.
Select a device from the drop down list.
Interact with the device content in the file explorer window. Right-click on a file or directory to create a new file or directory, save the selected file or directory to your machine, upload, delete, or synchronize. Double-click a file to open it in Android Studio.
Android Studio saves files you open this way in a temporary directory outside of your project. If you make modifications to a file you opened using the Device File Explorer, and would like to save your changes back to the device, you must manually upload the modified version of the file to the device.
Full Documentation
You may use this shell script below. It is able to pull files from app cache as well, not like the adb backup tool:
#!/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'"
Then you can use it like this:
./pull.sh files/myFile.txt
./pull.sh cache/someCachedData.txt
If you are using a Mac machine and a Samsung phone, this is what you have to do (since run-as doesn't work on Samsung and zlib doesn't work on Mac)
Take a backup of your app's data directory
adb backup -f /Users/username/Desktop/data.ab com.example
You will be asked for a password to encrypt in your Phone, don't enter any. Just tap on "Back up my data". See How to take BackUp?
Once successfully backed up, you will see data.ab file in your Desktop. Now we need to convert this to tar format.
Use Android Backup Extractor for this. Download | SourceCode
Download it and you will see abe.jar file. Add this to your PATH variable.
Execute this to generate the tar file: java -jar abe.jar unpack /Users/username/Desktop/data.ab /Users/username/Desktop/data.tar
Extract the data.tar file to access all the files
After setting the right permissions by adding the following code:
File myFile = ...;
myFile.setReadable(true, false); // readable, not only for the owner
adb pull works as desired.
see File.setReadable()
This answer is based on my experience with other answers, and comments in the answers. My hope is I can help someone in a similar situation.
I am doing this on OSX via terminal.
Previously Vinicius Avellar's answer worked great for me. I was only ever most of the time needing the database from the device from a debug application.
Today I had a use case where I needed multiple private files. I ended up with two solutions that worked good for this case.
Use the accepted answer along with Someone Somewhere's OSX specific comments. Create a backup and use the 3rd party solution,
sourceforge.net/projects/adbextractor/files/?source=navbar to unpack
into a tar. I'll write more about my experience with this solution at the bottom of this answer. Scroll down if
this is what you are looking for.
A faster solution which I settled with. I created a script for pulling multiple files similar to Tamas' answer. I am able to do it
this way because my app is a debug app and I have access to run-as on
my device. If you don't have access to run-as this method won't work
for you on OSX.
Here is my script for pulling multiple private files that I'll share with you, the reader, who is also investigating this awesome question ;) :
#!/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"`"
Gist:
https://gist.github.com/davethomas11/6c88f92c6221ffe6bc26de7335107dd4
Back to method 1, decrypting a backup using Android Backup Extractor
Here are the steps I took on my Mac, and issues I came across:
First I queued up a backup ( and set a password to encrypt my backup, my device required it ):
adb backup -f myAndroidBackup.ab com.corp.appName
Second I downloaded just abe.jar from here: https://sourceforge.net/projects/adbextractor/files/abe.jar/download
Next I ran:
java -jar ./abe.jar unpack myAndroidBackup.ab myAndroidBackup.tar
At this point I got an error message. Because my archive is encrypted, java gave me an error that I needed to install some security policy libraries.
So I went to http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html and downloaded the security policy jars I needed. Now in my case the install instructions told me the wrong location to put the jar files. It says that the proper location is <java-home>/lib/security. I put them there first and still got the error message. So I investigated and on my Mac with Java 1.8 the correct place to put them was: <java-home>/jre/lib/security. I made sure to backup the original policy jars, and put them there. Vola I was able to enter a password with abe.jar and decrypt to a tar file.
Lastly I just ran ( after running previous command again )
tar xvf myAndroidBackup.tar
Now it is important to note that if you can just run-as and cat, it is much much faster. One, you only get the files you want and not the entire application. Two, the more files ( + encryption for me ) makes it slower to transfer. So knowing to do this way is important if you don't have run-as on OSX, but the script should be first goto for a debug application.
Mind you I just wrote it today and tested it a few times, so please notify me of any bugs!
Similar to Tamas's answer, here is a one-liner for Mac OS X to fetch all of the files for app with your.app.id from your device and save them to (in this case) ~/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
)
Exclude the -d to pull from emulator
Doesn't stomp your session variables
You can paste the whole block into Terminal.app (or remove newlines if desired)
Starting form Dave Thomas script I've been able to write my own solution to overcome 2 problems:
my backup was containing only the manifest file
binary files got with Dave Thomas where unreadable
This is my script, that copies app data to sdcard and then pull it
#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
Backed up Game data with apk. Nougat Oneplus 2.
**adb backup "-apk com.nekki.shadowfight" -f "c:\myapk\samsung2.ab"**
Does that mean that one could chmod the directory from world:--x to world:r-x long enough to be able to fetch the files?
Yes, exactly. Weirdly enough, you also need the file to have the x bit set. (at least on Android 2.3)
chmod 755 all the way down worked to copy a file (but you should revert permissions afterwards, if you plan to continue using the device).
you can do:
adb pull /storage/emulated/0/Android/data//

Simple script brings back nonesense error

I have been trying to make a shell script for android that removes certain files to harden the device slightly against attack. This script has worked on an android emulator on ubuntu running froyo i think. when i try to run it on a windows box running 4.2 it brings up the error at the bottom. I have checked all the directories and they exist. I am running this using the adb.
echo ANDROID
echo HARDENING STARTED
#removing files in the /system/xbin directory
mount -o rw,remount /dev/block/mdblock0 /system
rm /system/xbin/tcpdump
rm /system/xbin/su
#removing files in the /system/bin directory
rm /system/bin/bootanimation
rm /system/bin/dumpstate
rm /system/bin/ping
rm /system/bin/ping6
mount -o ro,remount /dev/block/mdblock0 /system
echo ANDROID
echo HARDENING COMPLETE
Brings back this error.. I have no idea whats going on.
ANDROID
HARDENING STARTED
mount:No such file or directory
, No such file or directorytcpdump
, No such file or directorysu
, No such file or directoryootanimation
, No such file or directoryumpstate
, No such file or directorying
, No such file or directorying6
mount:No such file or directory
ANDROID
HARDENING COMPLETE
PLEASE HELP
Ryan
The directory /system does not exists, so your mount command fails.
Next you try to delete a couple of files from the non-existing and thus not mounted /system directory, which result in more errors.
Finally, you try to remount the /system, which still does not exists, resulting in your last error.
Only thing is that the errors messages are a bit garbled, the filenames are overwritten by the message somehow.
Edit: To answer your additional question...
If you can check if the file exists you can handle this situation properly (instead of using wildcards):
# Check which device to use
if [ -e /dev/block/mdblock0 ]; then
device=/dev/block/mdblock0
elif [ -e /dev/block/mtdblock0 ]; then
device=/dev/block/mtdblock0
else
echo "Device not found";
exit 1;
fi
mount -o rw,remount $device /system
# etc...
I do not know the exact Android shell commands, but assuming it is quite similar to bash this should work.
Change the line ending to Unix style, will solve all your problem.

backup full sms/mms contents via adb

I've been attempting to use adb to pull the sms/mms inbox in its entirety from the device but am having some trouble. The phone is rooted and I've tried the following commands:
Input
./adb pull /data/data/com.android.providers.telephony/databases/mmssms.db
output
Permission denied
Input
./adb pull su /data/data/com.android.providers.telephony/databases/mmssms.db
Output
The help menu
Am I flawed in my thinking that I can pull the sms inbox via commands similar to the ones I've tried? If it can be done what is wrong with my command?
Thanks
One way to fetch contents of the /data directory is to first copy the sqlite db to somewhere that is accessible, and then using adb pull to copy from there to the host.
For example, the following commands use the android bridge to grab the sms data (assuming it is contained in /data/data/com.android.providers.telephony/databases/mmssms.db):
adb shell
$ mkdir /mnt/sdcard/tmp
# su
# cat /data/data/com.android.providers.telephony/databases/mmssms.db > /mnt/sdcard/tmp/mmssms.db
# exit
$ exit
adb pull /mnt/sdcard/tmp/mmssms.db .
Now you have the mms/sms database on your host machine, probe to find most popular recipient, for example:
sqlite3 -header mmssms.db 'select address from sms' | sort -n | uniq -c | sort -n
Finally, tidy up the temp area:
adb shell
$ rm /mnt/sdcard/tmp/mmssms.db
$ rmdir /mnt/sdcard/tmp
$ exit
You have to give ADB root privalages before you pull that database
adb root
adb pull /data/data/com.android.providers.telephony/databases/mmssms.db ./
Thanks to #Bonlenfum's answer I was able to come up with a reusable script for copying any file/directory on a rooted device to a Windows path (local or UNC).
Edit: Fixed bug with paths containing spaces.
Save the following as: adbSuPull.bat
#echo off
SetLocal
set RemotePath=%~1
set LocalPath=%~f2
if [%1] == [] goto Usage
if "%~1" == "/?" goto Usage
if not [%3] == [] goto Usage
:: Replace " " with "\ " (escape spaces)
set RemotePath=%RemotePath: =\ %
set TimeStamp=%date:~-4,4%-%date:~-10,2%-%date:~-7,2%_%time:~-11,2%-%time:~-8,2%-%time:~-5,2%
:: Replace spaces with zeros
set TimeStamp=%TimeStamp: =0%
if "%LocalPath%" == "" set LocalPath=adbSuPull_%UserName%_%TimeStamp%
set SdCardPath=/mnt/sdcard
set TempPath=%SdCardPath%/adbSuPull_temp_%TimeStamp%/
echo.
echo Copying to temp location "%TempPath%"
echo.
adb shell "su -c 'mkdir -p %TempPath%; cp -RLv %RemotePath% %TempPath%'"
echo.
echo Copying to destination "%LocalPath%"
echo.
adb pull "%TempPath%" "%LocalPath%"
if ErrorLevel 0 goto Cleanup
:Error
echo.
echo Operation failed. Is USB Storage in use?
echo.
pause
call Cleanup
exit /b 1
:Cleanup
echo.
echo Removing temp location "%TempPath%"
echo.
adb shell "rm -Rf '%TempPath%'"
exit /b ErrorLevel
:Usage
echo.
echo.adbSuPull ^<RemotePath^> [^<LocalPath^>]
echo.
echo Copies files/directories from a rooted Android device to a Windows path.
echo Author: Ben Lemmond benlemmond#codeglue.org
echo.
echo. RemotePath (required) Specifies the path to the file or directory on
echo. the rooted Android device.
echo.
echo. LocalPath (optional) Specifies the destination path. This can be a
echo. Windows local path (C:\folder) or a UNC path
echo. (\\server\share).
echo. Defaults to adbSuPull_%%UserName%%_%%TimeStamp%%
echo. in the current working directory.
exit /b 1
Usage:
adbSuPull <RemotePath> [<LocalPath>]
Copies files/directories from a rooted Android device to a Windows path.
Author: Ben Lemmond benlemmond#codeglue.org
RemotePath (required) Specifies the path to the file or directory on
the rooted Android device.
LocalPath (optional) Specifies the destination path. This can be a
Windows local path (C:\folder) or a UNC path
(\\server\share).
Defaults to adbSuPull_%UserName%_%TimeStamp%
in the current working directory.

Categories

Resources