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
Related
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)
When I just run adb shell, I get shell running from uid=2000(shell) gid=2000(shell), without ptrace access to my application.
How to open a shell with the same UID as launched application?
Use run-as <your package name> to switch to your app's UID or run-as <your package name> <command> to run a single command with your app's UID.
From this answer:
The packages.xml file present in /data/system
The packages.list file present in /data/system
Contain the list of applications installed and their corresponding UID's.
Another answer in the same question suggests:
adb shell dumpsys package com.example.myapp | grep userId=
You can then open your shell as normal and run:
$ su <UID>
You should then have the same access and privileges as the app that uses that UID.
Workaround way using socat:
Add android.permission.INTERNET to your application;
Put socat binary (mirror) to /data/local/tmp/. Ensure everybody can start it;
Add Runtime.getRuntime().exec("/data/local/tmp/socat tcp-l:4446,fork,reuseaddr exec:/system/bin/sh,pty,stderr,setsid"); at startup of your Java-based application;
adb forward tcp:4446 tcp:4446
Use socat `tty`,raw,echo=0,opost=1 tcp:127.0.0.1:4446 on host to connect to the shell in your application context.
Note that this setup is not secure and should not be left in production app.
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.
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.