FrontPage
Demo †
Here's demo application called "Run Native Exe" to:
- run local UNIX commands
- run native executable downloaded from the Web
Package: NativeExe-0.1.apk
Source code: NativeExe-0.1.zip (ADT project)
To install the package,
- Go to Settings→Application and check "Unknown sources"
- Open the package link above using Android Browser
or type "adb install NativeExe?-*.apk" in your PC if you have Android SDK.
How can I run UNIX commands in Android App? †
Here's a better way. Thanks yussi to let me know by comment.
Here's sample code to run /system/bin/ls /sdcard in Android App:
try {
// android.os.Exec is not included in android.jar so we need to use reflection.
Class<?> execClass = Class.forName("android.os.Exec");
Method createSubprocess = execClass.getMethod("createSubprocess",
String.class, String.class, String.class, int[].class);
Method waitFor = execClass.getMethod("waitFor", int.class);
// Executes the command.
// NOTE: createSubprocess() is asynchronous.
int[] pid = new int[1];
FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(
null, "/system/bin/ls", "/sdcard", null, pid);
// Reads stdout.
// NOTE: You can write to stdin of the command using new FileOutputStream(fd).
FileInputStream in = new FileInputStream(fd);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String output = "";
try {
String line;
while ((line = reader.readLine()) != null) {
output += line + "\n";
}
} catch (IOException e) {
// It seems IOException is thrown when it reaches EOF.
}
// Waits for the command to finish.
waitFor.invoke(null, pid[0]);
return output;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage());
} catch (SecurityException e) {
throw new RuntimeException(e.getMessage());
} catch (NoSuchMethodException e) {
throw new RuntimeException(e.getMessage());
} catch (IllegalArgumentException e) {
throw new RuntimeException(e.getMessage());
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage());
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getMessage());
}
You can run UNIX commands using android.os.Exec, but it's not documented and not even in android.jar, so you cannot use it in usual way. But you can use it using reflection.
This code is based on source code of Android Terminal Emulator.
OK, but how can I put my own native executable in Android App? †
First, you need to cross-compile your native executable for ARM. Here's a way (dynamic link version). Or you can use Scratchbox (Japanese). If you get a file with a format like this, it's probably OK:
% file yourapp
yourapp: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.14, statically linked, not stripped
You have three ways to put the binary to the phone:
- From Android Java app, using assets folder (by fnerg in comment below)
- Include the binary in the assets folder.
- Use getAssets().open("YourBinaryHere?") to get an InputStream?.
- Write it to /data/data/app-package-name (e.g. /data/data/net.gimite.nativeexe), where your application has access to write files and make it executable.
- Run "/system/bin/chmod 744 /data/data/app-package-name/yourapp" using the code above.
- Run your executable using the code above.
- From Android Java app, downloading via HTTP (which I use in my demo application above)
- Dowload the executable using HTTP and put it to /data/data/app-package-name (e.g. /data/data/net.gimite.nativeexe), where your application has access to write files and make it executable. You can use standard Java FileOutputStream? to write files there.
- Run "/system/bin/chmod 744 /data/data/app-package-name/yourapp" using the code above.
- Run your executable using the code above.
- By adb (needs SDK and root)
Some notes †
- It seems Android Dev Phone (or at least my phone) has /system/xbin/su which doesn't require any password. So your Android App can do anything with root privilege. Looks dangerous... Maybe the command is not there in usual G1 because I found someone said su is not in his phone.
- I tested this with Android Dev Phone. I'm not sure this works for usual G1 too. If Android Terminal Emulator (available on Android Market) works on G1, I believe this method works too.
- android.os.Exec.createSubprocess has weird limitation that it accepts at most three args including the command name. If you want to pass more than three args, I guess you can do it by passing the command line to stdin of /system/bin/sh.
Comments †
- Thank you so much. It is very nice tutorial and excellent stuff. -- mmdnazar
- You can actualy just include the binary in the assets folder, then use getAssets().open("YourBinaryHere?") get get an InputStream?. At that point, just copy the file to your chosen directory, chmod it and run it. -- fnerg
- Hi, It works well for executing some ls shell command,, while when I try to use it for "rmmof" or insmod" it seems not work...,, any hint? permission ? -- chueh8?
- It might be, though I don't know about rmmod/insmod. The command is executed in application user permission, not root. -- Gimite
- @chueh8 you have to run the application as system user or if the app just should run on a custom image with su command installed you can execute /system/bin/su instead of /system/bin/sh -- rac?
- FYI Looks like normal application user is not allowed to run su in coming version of Android (SDK 1.5). You can still use that from adb. -- Gimite
- 1.5 coming? yes it was gone with v.1.5 that's why i mentioned that you have to install su or at least copy sh to su and set the suid flag but if you run your application as system user you can do root stuff without su ;-) -- @Gimite?
- sorry, posted wrong name... was the reply to Gimite -- rac?
- i doesn't work with v.1.5 (jf firmware with root!) and suid flag to shell script! :-( any ideas? -- alex?
- ups, posted wrong...not "i" but "it" doesnt`t work... -- alex?
- I have a c native which will read the frame buffer.. when I try to execute that from my application I am not able to do that one.. what is the problem... Can you please check that one.... -- raj...?
- can you please tell me how to do it wiout su....!!! -- raj?
- You don't need su if you chmod it. -- fnerg
- I can't seem to be able to do sh,"-" and then to write commands. i used both '\r' and '\n' but i don't think it "pushes" either of those to the sh.any ideas? -- yussi?
- Never mind, I found a much neater solution at: http://code.google.com/p/market-enabler/wiki/ShellCommands, check it out. -- yussi?
- Using sample code i tried to chmod but an error occured Operation not permitted please help me -- nikil?
- What file are you trying to chmod? The command is executed as application user so you cannot chmod files created by system and other application. -- Gimite
- chmod of a file in sdcard -- nikil?
- chmod of a file in sdcard -- nikil?
- You cannot add exec permission to files in SD card. You need to copy it to /data/data/app-package-name, chmod it and run it. -- Gimite
- write --