Mar*_*kus 5 c java java-native-interface android native
什么有效:我有一个运行 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 <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 代码变成了 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,在手机上调试或运行应用程序时,活动就会关闭并返回到我的主菜单活动。在调试中,它说“.... 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 设置一定是错误的,所以在我的思考过程中任何地方的任何建议都会很棒。
硬件:Samsung Galaxy Nexus v4.0.4 (Rooted)
文件:
mytunserv = c 可执行文件
setup_ip.sh = shell 脚本
setup_ip1.sh = shell 脚本
设置TunTap.java
liblmytunserv.so(位于 /libs/armeabi、/libs/armeabi-v7a、/libs/x86)
我需要什么:C 库 liblmytunserv.so 中的本机“runtun”函数在 while(1) 无限循环中永远运行。当 Java 代码调用该函数时(按下 button1 后),我需要该函数永远运行。Shell 脚本 setup_ip.sh 和 setup_ip1.sh 在 c 可执行文件运行后运行。如何让 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:哎呀,不需要编辑。这只是包名称。
| 归档时间: | 
 | 
| 查看次数: | 2031 次 | 
| 最近记录: |