How to execute shell commands in android? - android

I am trying to execute shell command through my code for adding entry in Iptables. The following is my piece of code
private void createShellCommand(String uidValue_param, String interface_param) {
// TODO Auto-generated method stub
StringBuilder cmdScript=new StringBuilder();
script.append("iptables -A OUTPUT " + interface_param + "-m owner --uid-owner " + uidValue_param + "-j REJECT");
writeIptables(cmdScript);
}
private void writeIptables(StringBuilder scriptfile) {
// TODO Auto-generated method stub
String cmd=scriptfile.toString();
if(RootTools.isRootAvailable())
{
Process exec;
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c"});
final OutputStreamWriter out = new OutputStreamWriter(exec.getOutputStream());
out.write(cmd);
// Terminating the "su" session
out.write("exit\n");
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("IPtables updation failed", "Iptable write failed"+e);
}
}
else
{
Log.e("Root Access denied", "Access Denied");
}
}
Here there are two methods i.e, createshellCommand() for building the shell command and writeIptables() for updating the iptables. But whenever I run the program logcat is displaying the following warning
"W 19913 su request rejected (0->0 /system/bin/sh)"
But I can manually add the entry through command prompt and its adding to the iptables but by using the above code its not updating. My phone is rooted and I am using android 2.3.4 with linux kernel 2.6.29. And I am using external library "Roottools" for checking the root access.
Please help me to rectify the error.

This Works:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
execute_reboot();
}
void execute_reboot()
{
Process reboot;
try {
reboot=Runtime.getRuntime().exec("su");
DataOutputStream os =
new DataOutputStream(reboot.getOutputStream());
os.writeBytes("reboot\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
reboot.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This Code Works fine. There are couple of small mistakes in your program. Try the one i pasted. Its working charm. All the best. I kept it as simple as possible so that it is easy to understand. You can still use arrays and other stuff to fancy your coding.
And yaa the same one also works for chmod command where you need to pass more than one argument.
For this Just replace
"os.writeBytes("reboot\n");"
with
"chmod 777 /dev/video0\n"(or any other system file).
Thanks. LEt me know if there is something tat i can do.

public static void rebootNow() {
Log.d(TAG, "Rebooting");
try {
#SuppressWarnings("unused")
Process proc = Runtime.getRuntime().exec(
new String[] { "su", "-c", "reboot" });
} catch (Exception ex) {
Log.d(TAG, "Rebooting failed (Terminal Error)");
}
}
This one is a little more compact
You can add "proc.waitFor();" after the Process proc... line to get rid of the unused warning, but rebooting your device takes a few seconds time and if you want to disable some features during the few seconds in your UI-thread, I think its better to not wait for the process to end.

Trying using the iptables command (with sudo and without), rather than just clobbering the iptables config file.

Related

How to trigger Android OS to kill my background service for testing purpose?

We know Android OS will select some activities or services to kill if the system needs more resource. I want to run a test to see if my service will be the candidate to be killed. How can I create a situation to trigger the event?
method 1
command kill -9 pid
This is actually a shell command. We know that the bottom layer of Android is Linux. Therefore, all Linux terminal commands can be used on Android. Paste a piece of code to show how do you incorporate it into the code.
private void killProcess(String pid) {
Process sh = null;
DataOutputStream os = null;
try {
sh = Runtime.getRuntime().exec("su");
os = new DataOutputStream(sh.getOutputStream());
final String Command = "kill -9 " + pid + "\n";
os.writeBytes(Command);
os.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
sh.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The most important function of this method is to tell you how to execute Linux shell commands in an Android program.
method 2
Kill the background service without automatic startup:
am (Activity Manager) command
The am command is a command in the /system/bin/ directory of the Android system. You can not only start an application on the terminal, but also start a service, send broadcast, intent action, and force stop process. We're going to use a function that is to force the application to stop.
For the description and usage of the am command, see the Android official website at http://developer.android.com/tools/help/adb.html#am.
The following is an example of code: am force-stop <PACKAGE>
private void forceStopAPK(String pkgName){
Process sh = null;
DataOutputStream os = null;
try {
sh = Runtime.getRuntime().exec("su");
os = new DataOutputStream(sh.getOutputStream());
final String Command = "am force-stop "+pkgName+ "\n";
os.writeBytes(Command);
os.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
sh.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In the preceding code, we call the forceStopAPK method to pass the package name of an application. Then we can kill the corresponding Android application without starting it automatically.

Blank File is saved when using screencap programatically in Android

code snippet
void takeSnapShot()
{
Process process = null;
try
{
process = Runtime.getRuntime().exec("/system/bin/screencap -p /sdcard/snapshot/test_2.png" );
try
{
process.waitFor();
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I am gettin an empty file saved whereas If i use the same command through adb shell, i get my screen captured.
Any help will be appreciatable
Edit: my previous answer was mistaken, any app can use the screen capture command.
It might be a permission issue. Are you sure you have permission to write to sdcard?
Check this post, which covers your topic:
How to run android system app without root permisson?
I solved this by adding the following permission to my Manifest.
<uses-permission
android:name="android.permission.READ_FRAME_BUFFER"
tools:ignore="ProtectedPermissions"/>
NOTE: This is a protected permission, my application is a system app and also signed using the platform key.

How to delete a system file from an Android App?

I'm using Root Tools and I'm not getting too far with it...
I want to have access to delete files from /system/app and other directories that require root. I would love to do it programmatically through Java, but if I can do it through shell commands, that's OK. Too. My phone is rooted. Here's what I've tried so far.
RootTools.remount("/system", "rw");
try {
RootTools.sendShell("rm /system/app/Videos.apk", -1);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (RootToolsException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (TimeoutException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
I've also tried:
public static void sendShell(List<String> cmds) throws Exception {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd+"\n");
}
os.writeBytes("exit\n");
os.flush();
os.close();
process.waitFor();
}
I have no idea what to do from here...
Based on our conversations it looks like you need a different rom as there were issues remounting partitions on your device.
I would bet that flashing a new rom would alleviate this issue and allow RootTools to properly remount /system as rw and allow you to delete your file.

How to check root access in android?

I created a method for checking whether the android phone is rooted or not. This is done as follows
public int checkrootcommand(String string) {
// TODO Auto-generated method stub
Process exec;
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c"});
final OutputStreamWriter out = new OutputStreamWriter(exec.getOutputStream());
out.write("exit");
out.flush();
Log.i(SUPER_USER_COMMAND, "su command executed successfully");
return 0; // returns zero when the command is executed successfully
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 1; //returns one when the command execution fails
}
But the problem is that the method checkrootcommand() is executed first it works perfectly, but when the same method called again the superuser session is still running. Is there any way to end the superuser session once the method is executed??
There is no reliable means of detecting a rooted condition on a device where hardware protections have been overcome by exploiting software vulnerabilities.
At best you can detect the presence of particular toolsets or scan for things that aren't supposed to be there or changes in files that are - but that requires knowledge of what a given installation should look like, and assumes that the OS functionality you are using to make the checks hasn't been modified to hide the changes.
To reliably scan, you need to be sure trusted code runs at a lower level than untrusted code; a rooted device is one where this assurance has been fundamentally broken, or where the end user is trusted more than you the developer are.
In your case, you should kill the process after executing it for the job which is done before returning. The following changes to your code should do the thing.
public int checkrootcommand(String string) {
// TODO Auto-generated method stub
Process exec = null;
try {
exec = Runtime.getRuntime().exec(new String[]{"su","-c"});
final OutputStreamWriter out = new OutputStreamWriter(exec.getOutputStream());
out.write("exit");
out.flush();
Log.i(SUPER_USER_COMMAND, "su command executed successfully");
return 0; // returns zero when the command is executed successfully
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (exec != null) {
try {
exec.destroy();
} catch (Exception ignored) {
}
}
}
return 1; //returns one when the command execution fails
}
You may not be able to universally detect whether phone is rooted or not but you should be able to request and then confirm is your app can access root by running id as root e.g., su -c id validate if the command executed successfully and the output contains uid=0 i.e., the uid of the root user.
Method 1 : Application asks for ROOT access :
Add this in your app-level gradle build file :
dependencies {
compile 'eu.chainfire:libsuperuser:201501111220'
}
Now,
System.out.println(Shell.Su.available());
//Outputs true if user-granted else false
Method 2 : Application doesn't asks for ROOT :
boolean deviceisRooted() {
String[] filespaths = {"/system/app/Superuser.apk","/sbin/su", "/system/bin/su","/system/xbin/su"};
for (String xyz : filespaths) {
if (new File(xyz).exists()) return true;
}
return false;
}
System.out.prinln(deviceisRooted());
//Outputs true if device is ROOTED else false
//Doesn't asks user
//Also returns true IF NOT PROPERLY ROOTED (But ROOTED somehow)
Use this code:
Process executor = Runtime.getRuntime().exec("su -c ls /data/data");
executor.waitFor();
int iabd = executor.exitValue();
if(iabd != 0){ /*process exit value is not 0, so user is not root*/ }else{ /* user is root*/ }
You can achieve this from a terminal command and you can run terminal commands within an app.
if [ ! -z "$(/system/bin/ps -A | grep -v grep | grep -c daemonsu)" ]; then echo "device is rooted"; else echo "device is not rooted"; fi
Your application also doesn't require root access this way.

More than one Superuser command Android

I'm tring to run this:
String[] hin1 = { "su", "-c",
"mount -o remount,rw -t yaffs2 /dev/block/mtdblk3 /system" };
try {
Runtime.getRuntime().exec(hin1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String[] hin2 = { "su", "-c", "m /system/etc/hosts" };
try {
Runtime.getRuntime().exec(hin2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String[] hin = { "su", "-c",
"cp /sdcard/hosts /system/etc/" };
try {
Runtime.getRuntime().exec(hin);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Sadly it is only working when I make for every action a new button.. :(
Is there a way to run more than one command at once??
Thanks
Don't think so its working also , I tried the following code :
public class GainrootActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void gainroot(View view)
{
String[] hin1 = { "su", "-c","chmod 777 dev/test1" };
try {
Runtime.getRuntime().exec(hin1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
only button for command su -c chmod 777 dev/test1 (for changing the permission of one log file in dev directory) but it didn't work.
Whats wrong in this.Can some one point out whats missing.
I have even put this line in the Androidmanifest.xml as well
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
Rgds,
Saurabh
Depending on how the su command is implemented (ie, if it's launching something approaching a capable shell as it would on a more typical linux), you may be able to combine multiple commands into one string by separating them with semicolons.
You could also make a shell script containing multiple commands and use su to launch that, though you may need to put it in an executable location.
You're not letting one command finish before the next one starts. Try adding a waitFor after the exec:
Runtime.getRuntime().exec(hin1).waitFor();

Categories

Resources