I need to run a script in debug mode that will pull all sharedpreferences into a folder. From my research i can only pull from debug builds. I tried from a non-rooted phone to get the sharedpreferences like this:
$adb shell
$adb run-as mypackagename
then i was able to traverse to /data/data/mypackagename/shared_prefs
but i'd like to be able to put this in a script. I can only call adb pull from outside adb shell. how can i get the shared_prefs entire folder pulled out of a normal non-rooted device on a debug application ? there must be a way because how is facebook setho doing it ?
This question is about retrieving sharedPreferences not a database retrieval.
I created the following shell script
#!/bin/bash
pname=$1
if [ -z "${pname}" ]; then
echo "Please enter a package name"
exit 1
fi
adb shell "run-as $pname chmod 776 shared_prefs"
adb pull /data/data/$pname/shared_prefs ./${pname}_shared_prefs
adb shell "run-as $pname chmod 771 shared_prefs"
name it pullsharedprefs.sh (or whatever you want) and from terminal run the command:
chmod +x pullsharedprefs.sh
./pullsharedprefs.sh some.package.name
shared_prefs will be pulled to the current working directory and named {package-name}_shared_prefs
Tested using genymotion (Android 5.1.1)
Related
I need to delete a shared preferences file using an adb command. Is there a way to do that without uninstalling the app?
I could not find anything that did it?
If you want to clear all the preferences, a single command will do it:
adb shell pm clear <package name>
Definitely not on an unrooted phone. On normal consumer builds (user builds), only the application itself can access the app's data.
If you have root, you can access the shell via
adb shell
Then navigate to the app's data directory (/data/data/<package name>), find the file and rm it.
Alternatively, you can do it all at once with
adb shell rm /data/data/<package name>/<file name>
You can try this on a DEBUG application only:
$ adb shell
$ adb run-as mypackagename
$ cd /data/data/mypackagename/shared_prefs
//then remove whatever you want
Is there a way to write a script that will copy files from an ADB shell using run-as?
The only way I know of to copy in the adb shell is using cat source > dest (edit: modern android versions have the cp command, which makes this question unnecessary), but I am only able to quote the greater-than sign one level deep - so my script can pass it to adb shell, but not to adb shell run-as.
For example, this works:
adb shell "cat source > dest"
But this does not:
adb shell run-as "cat source > dest"
Nor this:
adb shell "run-as cat source \> dest"
I even tried created a small script and uploading it to the device, but I can't seem to run the script from the adb shell - it tells me "permission denied". I can't chmod the script, either.
The reason I want to do this is to copy a file into an app's private storage area - specifically, I am using a script to modify shared preferences and put the modified preferences back. Only the app itself or root can write to the file I want, however.
The use case in this scenario is coping a file to a protected location on the device, not retrieving it; for retrieving, there are already good answers in this question.
The OP tried to combine the following 3 commands (that he had no problem executing one after another in the interactive shell session) into a single non-interactive command:
adb shell
run-as com.example.app
cat /sdcard/temp_prefs.xml > shared_prefs/com.example.app_preferences.xml
For simplicity let's start from within an interactive adb shell session. If we just try to combine the last two commands into a single line:
run-as com.example.app cat /sdcard/temp_prefs.xml > shared_prefs/com.example.app_preferences.xml
This would not work because of how shell redirection works - only the cat /sdcard/temp_prefs.xml part of the command would be run with com.example.app UID
Many people "know" to put the part of the command around redirection into quotes:
run-as com.example.app "cat /sdcard/temp_prefs.xml > shared_prefs/com.example.app_preferences.xml"
This does not work because the run-as command is not smart enough to parse the whole command. It expects an executable as the next parameter. The proper way to do it would be to use sh instead:
run-as com.example.app sh -c "cat /sdcard/temp_prefs.xml > shared_prefs/com.example.app_preferences.xml"
So can we just prepend adb shell to the command and be done with it? Not necessarily. By running the command from your PC you also add another local shell and its parser. Specific escape requirements would depend on your OS. In Linux or OSX (if your command does not already contain any ') it is easy to single-quote the whole command like so:
adb shell 'run-as com.example.app sh -c "cat /sdcard/temp_prefs.xml > shared_prefs/com.example.app_preferences.xml"'
But sometimes it is just easier to use an alternative solutions with (-out or less) quotes:
adb shell run-as com.example.app cp /sdcard/temp_prefs.xml shared_prefs/com.example.app_preferences.xml
Or if your device does not have the cp command:
adb shell run-as com.example.app dd if=/sdcard/temp_prefs.xml of=shared_prefs/com.example.app_preferences.xml
Also notice how I used shared_prefs/com.example.app_preferences.xml instead of full /data/data/com.example.app/shared_prefs/com.example.app_preferences.xml - normally inside of run-as command your current directory is the HOME dir of your package.
Following Chris Stratton's advice, the way I eventually got this to work was as follows (for copying shared preferences back to the device):
adb push shared_prefs.xml /sdcard/temp_prefs.xml
cat <<EOF | adb shell
run-as com.example.app
cat /sdcard/temp_prefs.xml > /data/data/com.example.app/shared_prefs/com.example.app_preferences.xml
exit
exit
EOF
Piping directly to adb shell run-as did not work, and I do not know why, but piping to adb shell does. The trick is to then call run-as from the interactive shell, and it continues to accept input from the pipe.
The HERE doc lets me easily embed the newlines to separate commands and in general just makes it readable; I did not have much luck with semicolons, but that might have been because of the way I was doing things. I believe it might work with other methods of piping multiple commands/newlines; I stopped the experiment once I finally got it to work.
The two exits are necessary to prevent a hanging shell (killable with CTRL-C); one for run-as, and the other for adb shell itself. Adb's shell doesn't respond to end-of-file very nicely, it seems.
you could just change the permission of the directory and then pull all the files out. but for me i was looking for just one shared preference file and i was able to get the data like this:
PACKAGE='com.mypackage.cool'
SHAREDPREF_FILE="${PACKAGE}_preferences.xml"
adb shell "run-as $PACKAGE cat /data/data/$PACKAGE/shared_prefs/$SHAREDPREF_FILE">$SHAREDPREF_FILE
now we have the data of the sharedpreference file stored in a file of the same name.
Using the latest adb (ADB v1.0.41 / Version 33.0.3) and a Play Store emulator image I experienced adb root not being granted. I also could not copy from /data/local/ or /storage/emulated/0/ due to not having permissions when run-as com.myapp.app
new_prefs_path="my_machine.xml"
config="$(cat $new_prefs_path)"
my_app_uri="com.myapp.app"
adb shell "run-as $my_app_uri sh -c 'echo \"$config\" > shared_prefs/on_android.xml'"
This fixes it for me as a bash script. It's made slightly more complicated by needing to be configurable for different apps and complex payloads.
We take a file (could be generated earlier in this script) and read it to a variable.
We then start shell, do run-as my app and run echo expanding the read file to a file in shared_prefs.
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.
I am unable to pull a the database from the device even after changing the permission. I have a rooted phone.
It used to work. I could pull before. For some unknown reason now I cannot.
The error I receive is
remote object '/data/data/com.thuptencho.transitbus/databases/ttc.db' does not exist
Does anybody know why this is happening?
Below is what I did in command window.
C:\users\thupten>adb shell
shell#android:/ $ su
su
root#android:/ # cd /data/data/com.thuptencho.transitbus/databases/
cd /data/data/com.thuptencho.transitbus/databases/
root#android:/data/data/com.thuptencho.transitbus/databases # ls
ls
ttc.db
ttc.db-journal
webview.db
webview.db-journal
webviewCookiesChromium.db
webviewCookiesChromiumPrivate.db
root#android:/data/data/com.thuptencho.transitbus/databases # chmod 755 ttc.db
5 ttc.db <
root#android:/data/data/com.thuptencho.transitbus/databases # chmod 777 ttc.db
7 ttc.db <
root#android:/data/data/com.thuptencho.transitbus/databases # exit
exit
shell#android:/ $ exit
exit
C:\users\thupten>adb pull /data/data/com.thuptencho.transitbus/databases/ttc.db
remote object '/data/data/com.thuptencho.transitbus/databases/ttc.db' does not exist
I using these commands to get data from /data/data folders, no changing permission required
adb kill-server
adb root
I figured it out.
I had to chmod the databases folder as well and then the file.
The problem is that you need permission not just to the file, but also to its parent directories.
(That permission should not be 777 though!)
Rather than trying to change the permission, what you probably want to do is get adb running as root if that is supported, (ie, if you have an engineering build, rather than an aftermarket "rooting" of a secured device) or else use your root access (or the app itself, or the stock run-as command if you have a debug apk) to copy the file of interest somewhere accessible and then adb pull the copy.
My preferred solution was:
Install Chainfire's adbd insecure app
From within the adbd insecure app, select "Enable Insecure adbd"
adb pull /data/data/com.package.name/databases/database.db
Caution - adb insecure means adb is running as root on your device.
for i in `adb shell ls /data/ -1`;do adb pull /data/$i data; done
Can anyone tell me, is it possible to use the ADB to pull and push a database from an app, without root privileges on the phone?
For example, I know the location on my rooted magic and dream is:
/data/data/com.xxxx.xxxx/databases/xxxx
I know that you can use ADB without root, but when trying to use the shell - you can't view that location without root privaliges. But I have been told you can use push and pull if you know the file you want?
Basically I want to pull a database from MY app on a non rooted phone modify it and push it back on.
Only trouble I have is, the two phones I have are both root and I don't have access to a non root one to try it out.
While Nilhcem's answer didn't work for me, it lead me in the right direction (for that I upvoted) and I now have a working solution.
Old answer that may not work with newer versions of Android:
#Transfer file from app databases directory to PC
adb shell
$ run-as package.name
$ cd ./databases/
$ ls -l #Find the current permissions - r=4, w=2, x=1
$ chmod 666 ./dbname.db
$ exit
$ exit
adb pull /data/data/package.name/databases/dbname.db ~/Desktop/
#Transfer file from PC to app databases directory (requires the above permission change)
adb push ~/Desktop/dbname.db /data/data/package.name/databases/dbname.db
adb shell
$ run-as package.name
$ chmod 660 ./databases/dbname.db #Restore original permissions
$ exit
$ exit
Alternate method using external storage (confirmed to work with 6.0.1):
#Transfer file from app databases directory to external storage
adb shell
$ run-as package.name
$ cp ./databases/dbname.db /sdcard/
$ exit
$ exit
#Transfer file from external storage to app databases directory
adb shell
$ run-as package.name
$ cp /sdcard/dbname.db ./databases/
$ exit
$ exit
A quick workaround is to use the run-as command to copy the database in a folder where you can have access, such as /sdcard and then, do a normal adb pull
adb shell
$ run-as package.name cp /data/data/package.name/dbname.db /sdcard/
$ exit
adb pull /sdcard/dbname.db
More information on the run-as command here
Note that the run-as command is available since API level 8 (Android 2.2) and can only be used if the application is debbugable.
On OxygenOS (based on Android 5.2) I've combined the two solutions provided by Pilot_51.
First, I used run-as to gain access to /data/data/package.name/databases, but from here I wasn't able to copy directly to /sdcard/ so I changed the permissions of the file. After that, I exited from run-as mode and used cp to copy the file in /sdcard/ storage. Finally, I was able to use adb pull
$ adb -s <DEVICE_ID> shell
$ run-as package.name
$ chmod 666 databases/dbname.db
$ exit
$ cp /data/data/package.name/databases/dbname.db /sdcard/dbname.db
$ exit
$ adb pull /sdcard/dbname.db ./dbname.db
We set the file permissions to readable for all users from within the app.
if (BuildConfig.DEBUG)
{
new File(mDB.getPath()).setReadable(true, false);
}
Then just pull the .db off with adb normally.
adb -d pull //data/data/xxxxx/databases/xxxxx.db .
NOTE: I've discovered that this needs to be done each time the database file is opened, for example in onCreate as well as the constructor of your SQLiteOpenHelper wrapper (when your database is not null) or perhaps onOpen. If only in onCreate, then the next time you run your app and the .db already exists, for some reason the permissions have been changed back. This might have something to do with how Android manages its data.
if you want to push db file into the application
first of all, place "file.db" under "/storage/emulated/0/" because of permission issue. then you should pretend as application to access data folder.
adb shell
$ run-as com.package.name
:/data/data/com.package.name $ cp /storage/emulated/0/file.db /data/data/com.package.name/databases/
it copies the file.db that in main folder to databases.