3

Continue my previous question, I succeeded to execute a process from an Android application. Now I can see two process like I wanted, they both up and running. Now I need to execute an Android application from the native C code.

Found similar questions (1, 2), but the following solutions did NOT work for me.

1. execl("/system/bin/sh", "sh", "-c", "am start -a android.intent.action.MAIN -n   com.android.browser/.BrowserActivity", (char *)NULL);

2. execl("/system/bin/am", "start", "-a", "android.intent.action.MAIN",
                 "-n", "com.android.settings/.Settings", (char *)NULL);

None of the lines above didn't executed anything.

Even executing execl command with fork as follows did NOT help.

if (!fork()) {
    execl...
}

Can you please give me some kind of a clue? Thanks.

UPDATE: I've manage to print the stdout to the Android log, I'm getting errno

"Exec format error"

message from the execl method. Anybody have an idea how I can resolve this?

Community
  • 1
  • 1
Ofir A.
  • 3,112
  • 11
  • 57
  • 83
  • Why do you need to call apps from native C? You could try calling from your native code a java method that launches your desired app (by creating an intent). – lrdTnc Apr 03 '14 at 12:43
  • @Tonoicutzu Yes, you are right, this is kind of weird stuff. What I want is to execute the browser when the user uninstall my application. The only way I know is to execute native C code in a new process from my application, and from there to execute the browser. Because my application is no longer running I can't call java method, but only to use the native code. Please read my previous question, you can find more details there. Thanks. – Ofir A. Apr 03 '14 at 12:51
  • If you did manage to find a solution to your [previous question](http://stackoverflow.com/questions/22781261/create-new-process-with-runtime-getruntime-in-android), do consider adding an answer to that question with the details of your solution. – TheCodeArtist Apr 06 '14 at 10:29
  • @TheCodeArtist I did manage to find a solution to my previous question and I will add my solution later on. I tried the command above with the terminal application I downloaded and it worked, I will try it from the native code. I Will update you. – Ofir A. Apr 06 '14 at 11:20
  • @TheCodeArtist Did you deleted the comment with the line of code? – Ofir A. Apr 06 '14 at 11:25
  • Ah yes. Sorry for the confusion. I thought of putting up an answer and hence deleted the short comment. Anyways, you seem to be on the right track in your latest comment. Try it out and let us know. I suppose you are "almost there" :) – TheCodeArtist Apr 06 '14 at 11:27
  • @TheCodeArtist Can you please write the line of code again? It seems not working again... – Ofir A. Apr 06 '14 at 11:36
  • 2
    **`"am start -a android.intent.action.MAIN -n com.android.browser/.BrowserActivity"`** It is the command from the first example you provided in the question. Since you verified that this command works fine when run from a terminal, now all we need to do is learn how to `exec` a command properly from within C code. – TheCodeArtist Apr 06 '14 at 11:43
  • @TheCodeArtist Thanks, I will continue to work on it. Do you know how I can redirect stdout to logcat, but without Android.mk file, if it's possible? – Ofir A. Apr 06 '14 at 12:15
  • @TheCodeArtist another question, maybe the problem is with how I'm compiling my program? `arm-linux-gnueabi-gcc -static -march=armv7 myFile.c -o myFile` – Ofir A. Apr 06 '14 at 12:22
  • Verify that the binary `myfile` works by launching it from your terminal app as follows: `cd ` followed by `./myfile`. Now, the binary output should be visible in the terminal app and a new process "`myfile`" in the output of `ps ax`. – TheCodeArtist Apr 06 '14 at 12:26
  • @TheCodeArtist It tells me `cannot execute permission denied` I tired to execute chmod also but it says `Operation not permitted`. – Ofir A. Apr 06 '14 at 12:48
  • well you need to first provide the proper permissions(eg. 755) to the executable. Again if your device does NOT allow you to do that as well, then you probably need to work on that first. (eg. root your device?) – TheCodeArtist Apr 06 '14 at 13:11
  • @TheCodeArtist Yes I'm aware of that, but I need it to run on all devices, rooted and un-rooted, How can I ensure that it will work like that? – Ofir A. Apr 06 '14 at 13:16
  • What you are trying is NOT the recommended way of doing things. If you intend to execute an activity. Simply raise an intent for it rather than trying to run C program which tried to do that. – TheCodeArtist Apr 06 '14 at 13:18
  • @TheCodeArtist Yes I know that this is how it suppose to be, but if you read my previous question, the problem is that I want to know when the user uninstalled my application, and then I can't call methods from the java code only from the native. check the answer here please [link](http://stackoverflow.com/questions/21279270/android-can-native-code-get-broadcast-intent-from-android-system). Thanks. – Ofir A. Apr 06 '14 at 13:22
  • You should build your executable using the ndk build system. And you will need to deploy it in a location which is not mounted noexec. Ultimately you should probably be a jni library, but for testing try pushing your executable to /data on an (implicitly rooted) emulator. – Chris Stratton Apr 06 '14 at 16:30
  • @Chris Stratton I'm building my executable using NDK with the next line: `arm-linux-gnueabi-gcc -static -march=armv7 myFile.c -o myFile`. I am taking the executable file and copy it from the assets folder to the data/data/myPackage/files folder and there I'm trying to execute it. Do you think this is not right? Another thing, please take a look on my update above, I'm getting an errno message, maybe you can tell my how to fix it. Thanks. – Ofir A. Apr 06 '14 at 17:50
  • 1
    As I said before, you should use the ndk build system, which you are not. Using its compiler directly is not recommended. Put a hello world printf in your code so you can tell if it even starts, and make sure the execute bit is set. – Chris Stratton Apr 06 '14 at 18:29
  • 1
    Why don't you guys sum up all this comment discussion into a readable answer below ? – chouaib Apr 09 '14 at 02:02

2 Answers2

1

Maybe you can write this from the Android/ Java / VM scope and call it from native code using NDK & JNI (Java Native Interface) ?

Example :

From your app:

class MyActivity extends Activity {

     public native int nativeMethodName();

     public void launchSomeAppMethod() {
         // launch some app
         Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.package.someapp");
         startActivity(LaunchIntent);
     }
 }

Native :

jint Java_com_yourpackage_appname_MyActivity_nativeMethodName(JNIEnv* env, jobject thiz) {
            //....
            // do your native work here
            // ...

            // call your obj instance that can launch another app
            jclass cls = (*env)->GetObjectClass(env, thiz);
            jmethodID method = (*env)->GetMethodID(env, cls, "launchSomeAppMethod", "()V");
            (*env)->CallVoidMethod(env, thiz, method);
}

Hope it helps dude.

ehanoc
  • 2,187
  • 18
  • 23
0

The error printed smells like permission problem.

Are you trying to run the application from an SD card? SD Cards by default are mounted without execute permission, you need to remount it.

Felipe Lavratti
  • 2,887
  • 16
  • 34