In my application I'm trying to execute a native code which is present on my SD card.
File sdCard = getExternalFilesDir(null); // directory where native file is placed
String nativeFile = "nativeFile";
String cmd = "shell /system/bin/chmod 0777 " + sdCard.getAbsolutePath() + "/" + nativeFile;
Process proc = Runtime.getRuntime().exec(cmd);
But as soon as Runtime.getRuntime().exec(cmd) is executed, it throws error:
java.io.IOException: Error running exec(). Command: [shell, /system/bin/chmod, 0777, /storage/emulated/0/Android/data/com.example.andridutilproject/files/native] Working Directory: null Environment: null
Any suggestions, how to resolve this?
First, you should wrap calls to exec in a try-catch-clause to catch IOExceptions.
Second, use exec(java.lang.String[]) to execute a command with parameters. For example, similar to
Runtime.getRuntime().exec(new String[]{ "shell", "/system/bin/chmod", "0777", sdCard.getAbsolutePath() + "/" + nativeFile });
The sdcard in an Android system is usually disabled for execution. Therefore even if you correctly execute the chmod command it will fail.
You can test that easily. Start the shell via USB (adb shell) and execute the chmod command. It will fail with an error message like "Bad mode".
Therefore you have to copy the file to a different location where you have write access and then set the executable bit on that copy. You can try to copy the file for example to "/data/local/tmp/" but I am not sure if that path is still usable.
I am going to develop an android app it works as font installer.
the target of my app is rooted device which does not include the desired font, and it goes to install from war\fonts\ to \system\fonts folder.
any help
Try this:
First to test this code you must copy your custom fonts to /sdcard/ I don't know if you are going to put them in assets or download them from internet. Anyways to test, use the following command lines:
cd /<path_to_sdk>/platforms-tools/
./adb root
./adb remount
./adb push sample.ttf /sdcard/
Now the code:
This code only execute a bunch of commands. Note that the important part is that this commands change the default android fonts by your own fonts. Make sure of always make a backup.
Process process;
try {
process = Runtime.getRuntime().exec("mount -o remount /dev/mtdblock4 /system");
process = Runtime.getRuntime().exec("cat /system/fonts/DroidSansFallback.ttf >> /sdcard/DroidSansFallback.ttf");
process = Runtime.getRuntime().exec("cat /sdcard/sample.ttf >> /system/fonts/DroidSansFallback.ttf");
process = Runtime.getRuntime().exec("mount -o ro,remount /dev/mtdblock4 /system");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
Also, you must reboot your device after do this.
my app have root right ,i want to using code to build a dir or file at /system or other dir of device.
i know common java build file as:
File file = new File(destFileName);
if (file.exists()) {
return false;
}
if i can build dir at system like the above code?if i need use su command before build file dir as
Process p = null;
p = Runtime.getRuntime().exec("su");
edit: i have read Create a file in /system directory but i cannot using code write :
" hint: use the "adb shell" and check if the upper steps can lead to success (su && remount -o remount,rw /system && touch /system/test)"
You need to get /system be mounted for write. By default it is read-only. You can use command like mount -o remount,rw /system
You can create dir using mkdir command
You can change the owner user by chown command
After that you can use java code as ususal.
I am developing an app where i am using sqllite3 database to store values. I have Nexus S and Nexus 7 both are unrooted devices. How can i get the database for my app for debugging purpose.
I have tried
(1) I have tried all approach mentioned here
adb shell
run-as app.package.name \
cp /data/data/package.name/databases/application.sqlite /sdcard/
exit
adb pull /sdcard/application.sqlite ~/
This says cp not found..
(2) http://developer.android.com/tools/help/adb.html#sqlite
adb -s emulator-5554 shell
# sqlite3 /data/data/com.example.google.rss.rssexample/databases/rssitems.db
SQLite version 3.3.12
Enter ".help" for instructions
.... enter commands, then quit...
sqlite> .exit
The following solution works only for apps that are debuggable. It may not work well on all devices, since run-as command doesn't work on some devices, especially with Jelly Bean.
Create a *.bat file and copy the following scripts
adb shell run-as [package] chmod 777 /data/data/[package]/databases/
adb shell run-as [package] chmod 777 /data/data/[package]/databases/[db_file_name]
adb shell run-as [package] cp /data/data/[package]/databases/[db_file_name] /sdcard/
adb pull /sdcard/[db_file_name]
Change [package] to the desired application package
Change [db_file_name] to the desired db name Run the bat file and
you should see the copied database in the same folder as the bat
file
The above solution assumes:
You are working on Windows
The device is connected and visible under
"adb devices"
You can write your database to the external memory with the following:
private void writeToSD() throws IOException {
File sd = Environment.getExternalStorageDirectory();
if (sd.canWrite()) {
String currentDBPath = DB_NAME;
String backupDBPath = "backupname.db";
File currentDB = new File(DB_PATH, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
}
Where DB_NAME is the name of my database and DB_PATH is defined as follows:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
DB_PATH = context.getFilesDir().getAbsolutePath().replace("files", "databases") + File.separator;
}
else {
DB_PATH = context.getFilesDir().getPath() + context.getPackageName() + "/databases/";
}
And add the following permission (Thanks to #Sathesh for pointing this out):
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I call this method anytime I have a database write so that my most current database file is in the external memory and I can view it and debug from there.
Then you can use the X-Plore app to view the database from the external memory right on the Android device.
Here's a much simple and straightforward answer: (Tested on Android one: unrooted)
adb -d shell
$ run-as my.package.name
$ cp databases/mydatabase.db /sdcard/mydatabase.db
$ exit
$ exit
now pull your database to the default adb path
adb -d pull /sdcard/mydatabase.db
or, to your Desktop for e.g.
adb -d pull /sdcard/mydatabase.db C:\Users\user\Desktop
you may want to remove the copy with a command below:
adb -d shell "rm /sdcard/mydatabase.db"
-d option chooses the default device if having more than one emulator.
If you don't know your application path then you can use this:
public void copyAppDbToExternalStorage() throws IOException {
File sd = Environment.getExternalStorageDirectory();
File currentDB = getApplicationContext().getDatabasePath("databaseName"); //databaseName=your current application database name, for example "my_data.db"
if (sd.canWrite()) {
File backupDB = new File(sd, "toDatabaseName"); // for example "my_data_backup.db"
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
}
Or if you need copy database to public "Download" folder then you can use this:
public void copyAppDbToDownloadFolder() throws IOException {
File backupDB = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "toDatabaseName"); // for example "my_data_backup.db"
File currentDB = getApplicationContext().getDatabasePath("databaseName"); //databaseName=your current application database name, for example "my_data.db"
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
This is working perfectly on my Nexus 4 device.
I just had to do something like this and there is a way to do it, although it's a pain. You need to cat the file as the application's user account, and then pipe it to a writable location. This worked for me on my Nexus 4 running 4.3.3:
adb shell "run-as org.your.application cat /data/data/org.your.application/your-file > /mnt/sdcard/your-file"
adb pull /mnt/sdcard/your-file
Try using stetho Library developed by facebook , it enables you to view the db via the web browser https://facebook.github.io/stetho/
adb shell "run-as CHR.Droid chmod 666 /data/data/CHR.Droid/files/CHR.db"
adb shell cp /data/data/CHR.Droid/files/CHR.db /sdcard/
In Xamrin.forms I had to replace databases to files
If after running
adb shell "run-as your.package.name"
you receive "run-as: Package 'your.package.name' is unknown", then try to get a database from emulator. See here: https://stackoverflow.com/a/44089632/2914140
In Android Studio 3.0 click View > Tool Windows > Device File Explorer.
Expand /data/data/[package-name] nodes.
I think that this is the easiest way. Add this dependency to your gradle file: debugImplementation 'com.amitshekhar.android:debug-db:1.0.0'
After this when you will start your application in your console you can see the message:
D/DebugDB: Open http://192.168.1.114:8080 in your browser
And there is your database.
You cannot access /data folder on not-rooted device
There is no way to do that. Android has great security mechanisms. Only your app can access its own files.
It isn't possible from a non-rooted phone. You cannot access the /data directory, so you can't copy the database or use sqlite app as in (2). If you need to debug, use the simulator, or from your app run queries to inspect the database.
I am doing a small application for a private circulation so that I do not use google play to install and update the app.
In my MainActivity, I will check whether app updation found or not via an api. If any update found my app download the updated apk file into download folder on the SDCard and install by:
intent.setDataAndType(Uri.fromFile(new File(destination)), "application/vnd.android.package-archive");
it works fine, but my problem is users can get the apk file in the download folder. So that I decided to download the file into /data/data/com.xxx.aaa. This idea, download the file into the /data... path. But I could not be installed the apk file. I make sure the apk file is present into the download folder by the following code:
if(new File(destination).exists()){
// apk file is present into download folder.
}
my method showing Parsing Error as below:
My Questions is:
How can I get install the updated apk file from the /data.... path?
I guess root privilege is the problem to install apk.
please help me.
Edited question:-
To get root access my application I run the following command:
try {
Runtime.getRuntime().exec("su");
}
after executing this command I can list /data/data/com.xxx.aaa path. and I have verified my downloaded apk file is presented here.
To install the apk, as told in the comment I run mount command in various option but no luck. I get Parsing error as shown in the figure.
I have tried the mount in the following ways:
1) mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system
2) mount -o rw,remount -t yaffs2 /data/data.com.xxx.aaa/appinfo.apk
3) mount
4) mount /system
I do not know the right way to mount /data/data/.... path. How to mount the /data/data/.... path.
please help me.
To List Files From /data/app/
[1] su
[2] ls /data/app/
To get apk from "/data/app/" folder
# ls /data/app/
i am getting following apk list
com.android.vending-1.apk
com.google.android.gms-1.apk
com.noshufou.android.su-1.apk
com.corusen.accupedo.te-1.zip
com.microsoft.office.lync-1.apk
com.okythoos.android.tdmpro-1.apk
com.devindia.acr-1.apk
for example i want to get "com.android.vending-1.apk" out to /sdcard
[1] su
[2] cat /data/app/com.android.vending-1.apk > /sdcard/com.android.vending-1.apk
[3] adb pull /sdcard/com.android.vending-1.apk /path-to-your-folder/
To Run application as system app
[1] adb push your-app.apk /sdcard/
[2] adb shell
[3] su
[4] mount -o remount,rw /system
[5] cat /sdcard/your-app.apk > /system/app/your-app.apk
[6] chmod 0644 /system/app/your-app.apk
Run Command As Root User, From Your Android Code :
for example if you want to run command "chmod 0644 /system/app/your-app.apk" form root user
Example Steps :
[1] Execute From Computer
adb push your-app.apk /sdcard/
[2] Execute From Android Code
Exec_SU("mount -o remount,rw /system");
Exec_SU("cat /sdcard/your-app.apk > /system/app/your-app.apk");
Exec_SU("chmod 0644 /system/app/your-app.apk");
Here is implementation of above function "Exec_SU" :
public static void Exec_SU(String str_command)
{
// working well
Runtime runtime = Runtime.getRuntime();
Process proc = null;
OutputStreamWriter osw = null;
StringBuilder sbstdOut = new StringBuilder();
sbstdErr = new StringBuilder();
String command=str_command;
try {
// Run Script
proc = runtime.exec("su");
osw = new OutputStreamWriter(proc.getOutputStream());
osw.write(command);
osw.flush();
osw.close();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
if (proc != null)
proc.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i think this will helpful to you. Thanks.