Android JNI原生C函数调用杀死活动

什么有效:我有一个运行TUN / TAP服务的ac可执行文件,以及两个在终端运行正常的shell脚本(用于配置“ip route”和“iptables”),都以root身份运行。

什么行不通:我试图创建一个Android应用程序来按下按钮后运行c可执行文件和shell脚本。 我最初做的就是onClick会用processBuilder创建一个进程,如下所示:

final Button button1 = ... ... public void onClick(View v) { String ip_address = edIPAddress.getText().toString(); Process process; try { process = new ProcessBuilder() .command("/system/bin/su", "-c", "/data/tuntapserv/armeabi/mytunserv " + ip_address) .redirectErrorStream(true) .start(); InputStream in = process.getInputStream(); OutputStream out = process.getOutputStream(); pOutput.append("TUN/TAP IS CONFIGURED!\n"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } 

据我所知,这本来应该没问题,但在实践中,mytunserv会在一段随机的时间后停止工作。 mytunserv会启动我的TUN / TAP但是当我在几分钟后检查“ip route”时,我会看到tun / tap已停止并消失。 类似地,我尝试了runtime.exec,即使这似乎使用了processbuilder,并且遇到了同样的问题。

然后我开始使用线程而不是进程,这似乎适用于shell脚本。

 ... final Button button2 = ... ... public void onClick(View v) { sThread = new ScriptThread(); sThread.start(); } ... private class ScriptThread extends Thread { @Override public void run() { Process process; try { process = new ProcessBuilder() .command("/system/bin/su","-c","/system/bin/sh /data/tuntapserv/armeabi/setup_ip.sh") .redirectErrorStream(true) .start(); InputStream in = process.getInputStream(); OutputStream out = process.getOutputStream(); pOutput.append("SCRIPT FINISHED!\n"); while(true) { Thread.sleep(0); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

这似乎至少适用于两个shell脚本。 我最终放弃了这个调用mytunserv的方法,认为进程或线程必须被java线程处理程序杀死,这在我的研究中似乎是不可预知的。 相反,我转移到JNI,因为这似乎比硬编码我的c可执行文件和shell脚本的路径更合适。

所以这是我最近的问题,我正在寻找帮助。

这是我的JNI设置:

 #include  ... JNIEXPORT jint JNICALL Java_android_1sp_1api_sample_SetupTunTap_runtun(JNIEnv * env,jobject obj,jstring ip_address) { jchar *ip; jboolean iscopy; ip=(*env)->GetStringUTFChars(env, ip_address, &iscopy); ... (*env)->ReleaseStringUTFChars(env, ip_address, ip); ... } ... 

上面的c代码变成了liblmytunserv.so。

 package android_sp_api.sample; ... public class SetupTunTap extends AnotherActivity { static { System.loadLibrary("lmytunserv"); } public native int runtun(String ip_address); ... final Button button1 = ... ... public void onClick(View v) { String ip_address = edIPAddress.getText().toString(); SetupTunTap myTun = new SetupTunTap(); myTun.runtun(ip_address); pOutput.append("TUN/TAP IS CONFIGURED!\n"); } ... 

据我所知,c代码应该能够调用c代码中不是JNIEXPORT的其他函数。 JNIExport只是让Java代码与我想象的c代码交互的一种方式。

无论如何,现在我的问题是,在按下按钮1时,在手机上调试或运行应用程序时,活动将关闭并返回到我的主菜单活动。 在Debug中,它说“…… DalvikVM [localhost:8602]”,在DDMS中,设备保持“在线”状态。 LogCat不输出任何暗示活动退出/崩溃的事情。 在进入SetupTunTap活动后,LogCat会通过显示信息来恢复,但是当按下button1并且屏幕闪烁黑色并恢复到我的主菜单活动时,它永远不会输出任何内容。 这是在LogCat中加载liblmytunserv的部分:

LogCat输出:

 ... 07-30 16:30:19.531: D/dalvikvm(4716): Trying to load lib /data/data/android_sp_api.sample/lib/liblmytunserv.so 0x41688d20 07-30 16:30:19.531: D/dalvikvm(4716): Added shared lib /data/data/android_sp_api.sample/lib/liblmytunserv.so 0x41688d20 07-30 16:30:19.531: D/dalvikvm(4716): No JNI_OnLoad found in /data/data/android_sp_api.sample/lib/liblmytunserv.so 0x41688d20, skipping init 

我该如何进一步调试? 如果我在“myTun.runtun(ip_address);”设置断点 然后我可以在Eclipse上的Debug接口中看到所有变量。 如果我继续这一点,活动将断开连接,我只在LogCat中看到.so lib文件加载。 我猜我的JNI设置一定是错的,所以在我的思考过程中的任何建议都会很精彩。

硬件:三星Galaxy Nexus v4.0.4(Rooted)

文件:

  • mytunserv = c exectuable

  • setup_ip.sh = shell脚本

  • setup_ip1.sh = shell脚本

  • SetupTunTap.java

  • liblmytunserv.so(放在/ libs / armeabi,/ libs / armeabi-v7a,/ libs / x86中)

我需要的:C库liblmytunserv.so中的原生“runtun”函数在while(1)无限循环中永远运行。 当Java代码调用该函数时(一旦按下button1),我需要该函数永远运行。 一旦c可执行文件运行,就会运行Shell脚本setup_ip.sh和setup_ip1.sh。 如何让c可执行文件永远运行?

如果您需要更多信息,请告诉我,谢谢您的时间。

在你的JNI中

 JNIEXPORT jint JNICALL Java_android_1sp_1api_sample_SetupTunTap_runtun(JNIEnv * env,jobject obj,jstring ip_address) 

在活动中

 package android_sp_api.sample; 

这些需要匹配;)

编辑:五次中的四次就是这样。 同样,也发布了java方面,但我希望它看起来像

 class SetupTunTap { public native int runtun(String ip_address); 

///}

所以发布SetupTunTap类也是如此

edit2:whoopse,编辑不需要。 它只是包名。