Mount R/W system in android application to edit Read Only files - android

How can I, within my application, edit a file in the /system/ directory?
Do I have to make the system R/W accessible?
I ve tried:
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes("mount -o remount,rw /system\n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();
and many other ways, without success.
If anybody can help me, I'd greatly appreciated it! :)
Also, if i finally made it, will it worked with all rooted phones? Or is it different with some phones?

I use:
os.writeBytes("mount -o remount rw /system/\n");
//instead of a comma, I have a space.
//When I tried it with a comma, mine didn't work either.
And that allows me to successfully mount.
If you exit right after that, of course it will not work. You have to stay within the same process and use the linux commands to edit the file.
I have no idea how to edit the files, but I suggest googling how to do things in linux terminal, and then putting the proper code in os.writeBytes("CODE_HERE");
Though, as far as the mounting process is concerned, I don't know if that command will work universally. It may just fortunately work on my device.
EDIT:
I now use RootTools: http://code.google.com/p/roottools/downloads/list
And here is the Wiki page:
http://code.google.com/p/roottools/w/list
But I now am using:
RootTools.remount(file, mountType);
//For example:
RootTools.remount("/system/", "rw");
I believe that is universal

Edit: All version of codes below DOES NOT mount system as RW.
*Read comments below to see why.
Solution of this is not a simple command.
Edit1: I went on Super User apk, Settings tab, and "tapped" at the last item, to update the su binary. With that update, everything below isnt working.
Edit2: started a whole conversation with my self here. Fix for the current latest binary is at the bottom of the post
==================================================================================
Found out how to do it! Second day of efforts, and finally found it!!!!!
Tried several things, and answer was to a simple change mode,
what i have done:
First Version Code:(doesnt work)
String[] mountRW = { "su", "-c",
"chmod 777 /system/etc/build.prop"};
String[] mountRO = {"su", "-c",
"chmod 755 /system/etc/build.prop"};
//TODO REMOVE testing purposes
File file2 = new File("/system/build.prop");
//Make file Read-Write
process = Runtime.getRuntime().exec(mountRW);
process.waitFor();
//TODO REMOVE testing purposes
Log.d("MOUNT RW?", "RW WRITABLE? "+ file2.canWrite());
///////////////////////
// process the file
//////////////////////
// After editing finish,
//make Read Only file again
process = Runtime.getRuntime().exec(mountRO);
process.waitFor();
//TODO REMOVE
Log.d("MOUNT RO?", "RO WRITABLE? "+ file2.canWrite());
I didnt paste some try catch cases.
Also i got another problem.. And i solved it in Version 2. THe little problem was, that, i was asking for a specific for a su command, and the user, had to accept SU cmd for RO, SU cmd for RW.. and another time for other stuff in my program.
In 2nd version i m using the generic su command, so user has to accept SU privileges only ONE time, and i m using output stream.
Code Version 2(Recomended) (doesnt work):
String mountRW = "chmod 777 /system/build.prop";
String mountRO = "chmod 755 /system/build.prop";
//TODO REMOVE
File file2 = new File("/system/build.prop");
//Make file Read-Write
process = Runtime.getRuntime().exec("su"); //Generic SU Command
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(mountRW + " \n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();
//TODO REMOVE
Log.d("MOUNT RW?", " RW WRITABLE? "+ file2.canWrite());
////////////////////////////
/// mod the file
///////////////////////////
// After editing finish, make Read Only file again
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(mountRO + " \n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();
//TODO REMOVE
Log.d("MOUNT RO?", "RO WRITABLE? "+ file2.canWrite());
Both codes require Root on your device.
Both versions doesnt include catch cases. (Eclpise will found them for you)
Check out your logcat(adb logcat), to see that indeed it works!
With latest su binary, this code changes slightly. The change mode command requires 4 digits. 0777 for rw permissions, and 0755 for ro permissions!
This code by its own, it does nothing to your device.
Only it mounts built.prop RW, and then mounts it back to RO.
Although if you change it, you may brick your device! Take care!

Related

How to get Android getExternalStorageDirectory folder by adb?

I want to generate a file while app is running thus my computer can monitor my app status in time(the cell phone is connected via usb all the time).
Is there anyway to let both adb and app point the same directory?
Also, If there has another way to make android can communicate with computer, please tell me.
Methods I tried:
At first, I though
echo $EXTERNAL_STORAGE
and
Environment.getExternalStorageDirectory()
would return the same value.
The value adb shell returned:
/storage/emulated/legacy
However, the result of calling Environment.getExternalStorageDirectory() In program is:
/storage/emulated/0
Then, I make android run shell command
Process su = Runtime.getRuntime().exec("echo $EXTERNAL_STORAGE");
//also tried "echo \\$EXTERNAL_STORAGE"
su.waitFor();
in = su.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine())!= null){
result = result + line + "\n";
}
reader.close();
in.close();
su.destroy();
return result;
but it return empty string.
echo is not a separate executable but rather a shell's built-in command.
Use Runtime.getRuntime().exec("sh -c 'echo $EXTERNAL_STORAGE'"); instead
Finally, I got the value by following command.
Runtime.getRuntime().exec(new String[] { "sh", "-c", "echo $EXTERNAL_STORAGE" });
Thanks Alex P. inspiring me.

how do I save contents of logcat in a file and change the format of the logcat at the same time?

String fileName = "somefile.txt";
File outputFile = new File(context.getDir("somedirectory", 0), fileName);
Runtime singleton = Runtime.getRuntime();
singleton.exec("logcat -v long"); //set the output format
singleton.exec("logcat -f " + outputFile.getAbsolutePath()); //format somehow reset to default here :/
This code creates a file and stores the logcat in it but I can't get the format to change to long. I believe it is because the exec functions are two different processes and they need to be one. But I'm not sure how do that.
The way you do it now actually executes two logcat commands - the first with -v option and the second with -f option.
The reason you don't see any output from the first command, is that you don't define where it should go.
You should combine the options together: singleton.exec("logcat -v long -f myfile");

implement at command on rooted android and get the result

I'm a beginner in stackoverflow so I cant add a comment.
I saw this page:
Read command output inside su process
and I tried this answer and it is ok:
Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
//from here all commands are executed with su permissions
stdin.writeBytes("ls /data\n"); // \n executes the command
InputStream stdout = p.getInputStream();
byte[] buffer = new byte[BUFF_LEN];
int read;
String out = new String();
//read method will wait forever if there is nothing in the stream
//so we need to read it in another way than while((read=stdout.read(buffer))>0)
while(true){
read = stdout.read(buffer);
out += new String(buffer, 0, read);
if(read<BUFF_LEN){
//we have read everything
break;
}
}
//do something with the output
but when I tried at command in the shell the response was the same command.
I put this command:
stdin.writeBytes("echo AT+CQI?\n");
the answer was:
AT+CQI?
I wrote:
stdin.writeBytes("echo ATinkd\n");
the answer was:
ATinkd
That is mean "bla..bla..bla..". that is mean the android system does not recognize this commands as at commands.
I wonder if any body have an advice or solution.
First I think you are just sending the AT command to stdout in the shell which will not do anything other than giving you an echo which you read back. For this approach to work you have to redirect the echo command to the serial port device file. Android phones use various devices for this, /dev/ttyGS0 and /dev/smd0 seems to be common names.
However I would suggest using the program atinput to send AT commands and capture modem responses. It is specifically written to be used from the command line like that. That will relieve you from communicating directly with the modem and the only thing left is the pipe handling reading the response.

Read private file (/data/data folder) in rooted device

I need to access a file contained in the private folder of another app. I have granted my app the root privilege and changed the permissions - although I think it's not necessary - but when I try to read from the file, I get "permission denied".
This is the code:
File file = new File("/data/data/other.app/shared_prefs/file.xml");
if(file.exists()) {
try {
Runtime.getRuntime().exec("su");
Runtime.getRuntime().exec("chmod 777 " + file.getAbsolutePath());
InputStream in = new FileInputStream(file);
....
} catch (IOException e) {
e.printStackTrace();
}
}
Probably you wont be able to do this, because each app on android has a user with unique permissions.
See this: http://developer.android.com/guide/topics/security/permissions.html#userid
Any data stored by an application will be assigned that application's user ID, and not normally accessible to other packages. When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.
You cannot break up the su and the chmod operations like that.
This code:
Runtime.getRuntime().exec("su");
Runtime.getRuntime().exec("chmod 777 " + file.getAbsolutePath());
Does not result in the chmod being executed in a root shell. Each call to exec kicks off a NEW process.
You need to run the commands you need all within a single process. The easiest way to do that is to write a shell script to your /data/data directory that does these operations for you and then run that through the sh shell processor.
Please note that good security practice would be to chmod the file back to not world readable after you are done with it in your app so that you are not leaving the other app exposed forever.
This answer looks to have what you need: Run binary from with root Android Application
SOLVED
Solved using this code to run the commands:
public static void runAsRoot(String[] cmds){
try {
Process p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd+"\n");
}
os.writeBytes("exit\nexit\n");
os.flush();
p.waitFor();
} catch(IOException e) {
e.printStackTrace();
} catch(InterruptedException e) {
e.printStackTrace();
}
}

Problem with Runtime.getRuntime().exec()

I have rooted my device, then in my application
Process p = Runtime.getRuntime().exec("su");
and it work fine, my application will be root mode. Then I try add wlan address space, but it doesn't work, when I check out in terminal, following error message is shown
busybox ifconfig there is not a new wlan address space.
I try with following way:
Process p = Runtime.getRuntime().exec("su");
p = Runtime.getRuntime().exec("busybox ifconfig wlan0 add xxxxxxxxxxxx");
p.waitfor();
When I run my application, the toast shows that the app is root mode but there is not added wlan0.
The "su -c COMMAND" syntax is not really supported. For better portability, use something like this:
p = Runtime.getRuntime().exec("su");
stream = p.getOutputStream();
stream.write("busybox ifconfig wlan0 add xxxxxxxxxxxx");
The write() command doesn't exists as-is, but I'm sure you'll find how to write your stream to it, maybe encapsulating the output stream in a BufferedOutputWriter or so.
because the process that started with "busybox" is not the same one
which started with "su". you should like this:
Process process = Runtime.getRuntime().exec("su");
OutputStream os = process.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeBytes("busybox ifconfig wlan0 add xxxxxxxxxxxx" + "\n");
dos.flush();
That might be because when you run su, it launches one process. Then you run busybox ..., and it happens in another process, which is not started as a superuser.
Try something like
Process p = Runtime.getRuntime().exec(new String[] {"su", "-c", "busybox ifconfig wlan0 add xxxxxxxxxxxx"});
, i.e. executing it in a single command-line.

Categories

Resources