[[FrontPage]]

#contents

** Demo [#m85fa6b6]

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:http://gimite.net/archive/NativeExe-0.2.apk]]~
Source code: [[on Github:https://github.com/gimite/android-native-exe-demo]] (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? [#pd3b337d]

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:http://code.google.com/p/market-enabler/wiki/ShellCommands]]. Thanks yussi to let me know this by comment.

** OK, but how can I put my own native executable in Android App? [#hddd196e]

First, you need to cross-compile your native executable for ARM. Here's [[a way (dynamic link version):http://honeypod.blogspot.com/2007/12/dynamically-linked-hello-world-for.html]]. Or [[you can use Scratchbox:http://d.hatena.ne.jp/Gimite/20071117/1195287778]] (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)
-- If you want to put the executable to YOUR phone connected with adb command in Android SDK and you have root, you can put the executable by:
 % adb shell
 $ su
 # mkdir /data/tmp
 # chmod 777 /data/tmp
 # exit
 $ exit
 % adb push yourapp /data/tmp
 % adb shell
 $ chmod 744 /data/tmp/yourapp
 $ /data/tmp/yourapp
-- Note that you cannot make files executable in /sdcard.

** Old way which no longer works [#t773569f]

''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:http://github.com/android/platform_development/tree/master/apps/Term/src/com/android/term]].

** Comments [#la1ee296]
- Thank you so much. It is very nice tutorial and excellent stuff. -- [[mmdnazar]] &new{2009-04-02 (Thu) 12:28:39};
- 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]] &new{2009-04-14 (Tue) 02:34:26};
- 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]] &new{2009-06-02 (Tue) 08:04:58};
- It might be, though I don't know about rmmod/insmod. The command is executed in application user permission, not root. -- [[Gimite]] &new{2009-06-03 (Wed) 12:17:41};
- @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]] &new{2009-06-07 (Sun) 09:23:01};
- 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]] &new{2009-06-08 (Mon) 04:15:32};
- 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]] &new{2009-06-08 (Mon) 16:53:39};
- sorry, posted wrong name... was the reply to Gimite -- [[rac]] &new{2009-06-08 (Mon) 16:54:36};
- i doesn't work with v.1.5 (jf firmware with root!) and suid flag to shell script!  :-( any ideas? -- [[alex]] &new{2009-06-09 (Tue) 19:15:31};
- ups, posted wrong...not "i" but "it" doesnt`t work... -- [[alex]] &new{2009-06-10 (Wed) 10:42:20};
- 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...]] &new{2009-08-06 (Thu) 13:22:27};
- can you please tell me how to do it wiout su....!!! -- [[raj]] &new{2009-08-06 (Thu) 13:23:59};
- You don't need su if you chmod it. -- [[fnerg]] &new{2009-08-18 (Tue) 22:19:54};
- 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]] &new{2009-10-14 (Wed) 00:08:53};
- Never mind, I found a much neater solution at: http://code.google.com/p/market-enabler/wiki/ShellCommands, check it out. -- [[yussi]] &new{2009-10-14 (Wed) 17:43:42};
- Using sample code i tried to chmod but an error occured Operation not permitted please help me -- [[nikil]] &new{2010-01-06 (Wed) 07:34:21};
- 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]] &new{2010-01-06 (Wed) 15:14:21};
- chmod of a file in sdcard -- [[nikil]] &new{2010-01-07 (Thu) 06:59:13};
- chmod of a file in sdcard -- [[nikil]] &new{2010-01-07 (Thu) 06:59:48};
- 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]] &new{2010-01-07 (Thu) 12:32:33};
- write --  &new{2010-01-23 (Sat) 09:44:22};
- 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]] &new{2010-03-24 (Wed) 16:20:56};
- 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]] &new{2010-03-28 (Sun) 19:23:33};
- 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]] &new{2010-04-12 (Mon) 12:42:23};
- Never mind, forgot to set the INTERNET permission in the manifest, now it works fine -- [[henka]] &new{2010-04-12 (Mon) 13:16:42};
- The getAssets() method won't work if you have a very large executable.  (greater than UNCOMPRESS_DATA_MAX size) -- [[Nick]] &new{2010-08-31 (Tue) 21:19:31};
- hi, i tried to put "insmod abc.ko; sendevent ....." into the script, but it failed to run. any ideas? thanks. -- [[rushier]] &new{2010-11-02 (Tue) 18:50:54};
- 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]] &new{2010-11-04 (Thu) 06:18:23};
- See http://code.google.com/p/market-enabler/wiki/ShellCommands , linked from "better way" link above. -- [[Gimite]] &new{2010-11-05 (Fri) 16:26:32};
- Thanks great, I have convert your tutorial to Chinese to forum: www.meegozu.com ,a MeeGo community. -- [[Aries]] &new{2010-12-23 (Thu) 06:39:13};
- I succesfully installed apk on android 2.2. but execution fail with android.os.Exec Exception -- [[husq510]] &new{2011-01-18 (Tue) 23:55:11};
- 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]] &new{2011-01-18 (Tue) 23:55:49};
- can you help? I success with the "su" trick, but im looking a way to run without privilege escalation. -- [[husq510]] &new{2011-01-18 (Tue) 23:56:56};
- I am tring third option usinf adb and getting this problem /data/tmp/basic: not found, where basic is my native app -- [[arya]] &new{2011-01-19 (Wed) 01:07:59};
- 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]] &new{2011-01-23 (Sun) 12:14:41};

#comment

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS