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.2.apk
Source code: on Github (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? †
You can use Runtime.exec() in standard Java. Here's sample code to run /system/bin/ls /sdcard in Android App:
try {
// Executes the command.
Process process = Runtime.getRuntime().exec("/system/bin/ls /sdcard");
// Reads stdout.
// NOTE: You can write to stdin of the command using
// process.getOutputStream().
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
This code is based on this article. Thanks yussi to let me know this by comment.
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)
Old way which no longer works †
This code doesn't work on Android 2.3 (and probably 2.2).
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());
}
This code is based on source code of Android Terminal Emulator.
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 --
- nicely written for beginners to understand call to native executable. Thanks! but...i'm getting java.lang.RuntimeException? : android.os.Exec... what could be the problem? the apk file fails to insall due to inconsistent certificate... -- svit?
- As described above, http://code.google.com/p/market-enabler/wiki/ShellCommands is better way. For RuntimeException?, do you set permission of the executable file correctly? See section "OK, but how can I put ...". Also the error message of the RuntimeException? may contain more information. For "inconsistent certificate" error, please uninstall the app and install again. -- Gimite
- Nice tutorial! Ive tried both methods in order to start the webserver (httpd) which comes with busybox, but even though it runs perfectly when I start it from the shell, I just get an I/O exception or null pointer exception when I run it by using these methods. Any idea? All other commands I have tried so far works perfectly.. -- henka?
- Never mind, forgot to set the INTERNET permission in the manifest, now it works fine -- henka?
- The getAssets() method won't work if you have a very large executable. (greater than UNCOMPRESS_DATA_MAX size) -- Nick?
- hi, i tried to put "insmod abc.ko; sendevent ....." into the script, but it failed to run. any ideas? thanks. -- rushier?
- Can you update this with a newer way not using the android.os.exec way so it doesn't die? I really need this to pull off some old binary integration -- Mike?
- See http://code.google.com/p/market-enabler/wiki/ShellCommands , linked from "better way" link above. -- Gimite
- Thanks great, I have convert your tutorial to Chinese to forum: www.meegozu.com ,a MeeGo? community. -- Aries?
- I succesfully installed apk on android 2.2. but execution fail with android.os.Exec Exception -- husq510?
- E/AndroidRuntime?(20896): FATAL EXCEPTION: main E/AndroidRuntime?(20896): java.lang.RuntimeException?: android.os.Exec E/AndroidRuntime?(20896): at net.gimite.nativeexe.MainActivity?.exec(MainActivity?.java:107) E/AndroidRuntime?(20896): at net.gimite.nativeexe.MainActivity?.access$1(MainActivity?.java:74) E/AndroidRuntime?(20896): at net.gimite.nativeexe.MainActivity?$1.onClick(MainActivity?.java:50) E/AndroidRuntime?(20896): at android.view.View.performClick(View.java:2461) E/AndroidRuntime?(20896): at android.view.View$PerformClick?.run(View.java:8888) E/AndroidRuntime?(20896): at android.os.Handler.handleCallback(Handler.java:587) E/AndroidRuntime?(20896): at android.os.Handler.dispatchMessage(Handler.java:92) E/AndroidRuntime?(20896): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime?(20896): at android.app.ActivityThread?.main(ActivityThread?.java:4627) E/AndroidRuntime?(20896): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime?(20896): at java.lang.reflect.Method.invoke(Method.java:521) E/AndroidRuntime?(20896): at com.android.internal.os.ZygoteInit?$MethodAndArgsCaller?.run(ZygoteInit?.java:858) E/AndroidRuntime?(20896): at com.android.internal.os.ZygoteInit?.main(ZygoteInit?.java:616) E/AndroidRuntime?(20896): at dalvik.system.NativeStart?.main(Native Method) W/ActivityManager?( 2709): Force finishing activity net.gimite.nativeexe/.MainActivity? I/ ( 2709): dumpmesg > "/data/log/dumpstate_app_error.log" -- husq510?
- can you help? I success with the "su" trick, but im looking a way to run without privilege escalation. -- husq510?
- I am tring third option usinf adb and getting this problem /data/tmp/basic: not found, where basic is my native app -- arya?
- husq510: It seems the way described in this page no longer works in Android 2.2 or later. I just updated the code in this page with the method described at http://code.google.com/p/market-enabler/wiki/ShellCommands . Please try the new code. -- Gimite
- hey can u explain me "how to shutdown emulator in android?" through coding... -- bhavana?
- hey i just want to put NDS or an emulator on my android and be able to play it. im not java learned so this really just hurts my head to read.. -- alan?
- hey i just want to put NDS or an emulator on my android and be able to play it. im not java learned so this really just hurts my head to read.. -- alan?
- Thanks for the tutorial. If the binary is not an ARM file, is there a way to convert to it? It is currently compiled in IA and I do not have the source code. -- Jay?
- Jay: It's probably very hard. You need IA emulator running on ARM. I'm not sure whether it exists. -- Gimite
- Thanks again. Im planning to run it on a device so i probably can ignore this difference. Also, how can you execute a binary file using the "." command? for example if i want to run a shell, "hello.script", i would normally do "./hello.script" on linux. In the android case, would "/system/bin/./hello.script" work? -- Jay?
- Ah got it please ignore the above. Ill just have to give a full path. -- Jay?
- Ah got it please ignore the above. Ill just have to give a full path. -- Jay?
- Ah got it please ignore the above. Ill just have to give a full path. -- Jay?
- Thanks for the easy-to-follow tutorial. I managed to make it work here, but when I try to run an executable which accesses the internet (such as ping or ssh), it fails silently. I have the INTERNET permission set. Do you have any idea on what the problem could be? -- Gorpo?
- When I tried, it seems native app cannot solve host names probably because /etc/resolv.conf is not set properly. I guess you can either do it in Java layer or implement your own DNS lookup. -- Gimite
- Solved my own problem: you also need to monitor the error input stream, otherwise you won't get any feedback in some cases. -- Gorpo?
- @Gimite the problem with the DNS lookup is because you're trying to open a socket (for resolving the DNS) without permissions. If you try connecting to the IP directly, you'll have the same problem when ssh tries to open the socket. The solution is to specify the android.INTERNET permission on your manifest. -- Gorpo?
- vary useful , thx u -- wyChen?
- Hello Gimite, I have tested the program but it gives me an error: -- Zaccaro?
- 12-03 07:23:10.819: E/AndroidRuntime?(5067): java.lang.RuntimeException?: java.io.IOException: Error running exec(). Command: [/system/bin/ls] Working Directory: null Environment: null -- Zaccaro?
- can you please tell us ; how can we make a.out file from cpp code -- Vivek?
- how we can make a.out ... according to our requirement... -- Vivek?
- @Gimite >>can you please provide me the source code to a.out.... -- Vivek?
- Hey can u say me how we can open the launcher directoly by adb command...!!! -- Awdhesh Kumar Jha