Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android JNI本机C函数调用终止活动_Java_Android_C_Java Native Interface_Native - Fatal编程技术网

Java Android JNI本机C函数调用终止活动

Java Android JNI本机C函数调用终止活动,java,android,c,java-native-interface,native,Java,Android,C,Java Native Interface,Native,工作原理: 我有一个运行TUN/TAP服务的c可执行文件和两个shell脚本(用于配置“ip路由”和“iptables”),它们在终端中运行良好,都以root用户身份运行 什么不起作用: 我正在尝试创建一个Android应用程序,在按下按钮后运行c可执行文件和shell脚本。我最初是这样做的,onClick将使用processBuilder创建一个流程,如下所示: final Button button1 = ... ... public void onClick(View v) { S

工作原理: 我有一个运行TUN/TAP服务的c可执行文件和两个shell脚本(用于配置“ip路由”和“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路由”时,我会看到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 <jni.h>
...
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代码应该能够调用c代码中没有JNIEXPORT的其他函数。根据我的想象,JNIEXPORT只是让Java代码与c代码交互的一种方式

无论如何,现在我的问题是,在调试或在手机上运行应用程序时,一旦我按下按钮1,活动就会关闭并返回到我的主菜单活动。在Debug中显示“…DalvikVM[localhost:8602]”,而在DDMS中,设备保持“在线”。LogCat不会输出任何提示活动已退出/崩溃的内容。当进入SetupTunTap时,LogCat通过显示信息恢复活动,但当按下按钮1时,不会输出任何内容,屏幕黑色闪烁,并恢复到我的主菜单活动。以下是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_地址);”处设置断点,那么我可以在Eclipse上的调试接口中看到所有变量。如果超过该点,活动将断开连接,我只能在LogCat中看到.so lib文件加载。我猜我的JNI设置一定是错的,所以在我的思考过程中任何地方的任何建议都会很好

硬件: 三星Galaxy Nexus v4.0.4(根目录)

档案:

  • mytunserv=c可执行

  • 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代码调用函数时(按下按钮1),我需要函数永远运行。一旦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);
/// }

因此,在课程结束后,也要继续学习\


编辑2:哇,编辑是不必要的。这只是程序包名称。

根据我学习JNI时使用的一个来源,它似乎建议我需要将“.”和下划线分别替换为下划线和“_1”。JNI/Delphi!??!这里有一个简短的版本,这就是精神,一直打印调试。试着在while(1)中测量你的启动时间,并在进程结束时打印出来。它可能是有价值的日志数据。例如,您可能会注意到该过程以相似的间隔结束,因此可能会显示泄漏。valgrind也能发现漏洞。您的调试建议帮助我解决了问题。我很感激!
class SetupTunTap
{
   public native int runtun(String ip_address);