Android JNI 本机 C 函数调用杀死活动

2024-01-13

什么有效: 我有一个运行 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代码变成了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 设置一定是错误的,所以在我的思考过程中任何地方的任何建议都会很棒。

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

Files:

  • 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后),我需要该函数永远运行。一旦 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:哎呀,不需要编辑。这只是包名称。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android JNI 本机 C 函数调用杀死活动 的相关文章

随机推荐

  • 需要帮助根据真值表创建二叉树

    首先 为了充分披露 我想指出这与机器学习课程中的作业有关 这个问题不是家庭作业问题 而是我需要解决的问题 以便完成创建 ID3 决策树算法这一更大的问题 当给定真值表时 我需要生成类似于以下内容的树 let learnedTree Node
  • 将数字截断至小数点后两位而不进行四舍五入

    假设我的值为 15 7784514 我想将其显示为 15 77 不进行舍入 var num parseFloat 15 7784514 document write num toFixed 1 br document write num t
  • 如何在没有选择按钮的情况下在GridView中实现全行选择?

    我正在实现一项功能 当用户按下 GridView 中行中的任何点时 将选择该行而不是 选择 按钮 为了实现这一点 我使用以下代码 protected void GridView1 RowDataBound object sender Gri
  • 动态创建文件输入元素

    我想自定义文件输入按钮 所以我使用此代码创建一个文件输入元素 function inputBtn var input document createElement input input type file setTimeout funct
  • TensorFlow:如何根据历元设置学习率衰减?

    学习率衰减函数tf train exponential decay需要一个decay steps范围 每隔一段时间降低学习率num epochs 你会设置decay steps num epochs num train examples b
  • Apache、SSL 客户端证书、LDAP 授权

    我在 serverfault com 上发布了这个问题 但没有答案 所以我在这里尝试 是否可以混合 mod ssl 和 mod auth ldap 以便使用客户端证书进行身份验证并使用 mod auth ldap 进行授权 需要 ldap
  • javax.servlet.ServletException:包装器找不到 servlet 类

    我已经从 Jasper Reports for Java Developer 第 3 章 中制作了一个 servlet 它将在浏览器上显示 Jasper Report 该 Servlet 如下所示 public class FirstRep
  • 如何抑制 Visual Studio 2017 (C#) 中的初始构建后事件错误?

    我在 Visual Studio 2017 中有一个 C 解决方案 我还有一个名为的批处理脚本foobar bat其中包含以下代码 echo foobar error 1 This is a test error 我的目标是得到only当我
  • new之后直接调用方法?

    PHP 是否允许像这样调用新对象的方法 new CEntry new Control gt actuate 我可以传递一个新对象作为参数 如下所示new Control 然而 它似乎不喜欢 actuate 调用 我收到错误 Parse er
  • 如何使用 C++ 中具有多个参数的 if 语句调用多个函数

    该程序针对每种条件运行所有函数 而它应该只针对每种条件运行一个函数 为什么 我应该编写计算球体 圆柱体和圆锥体的体积和表面积的函数 我无法弄清楚是 if 语句弄乱了 还是函数本身弄乱了 该程序的理想输出如下 选择形状 1 球体 2 圆柱体
  • 从 node-mysql 连接到 Amazon RDS (MySQL) 时出错

    我正在尝试使用 felixge node mysql 包从 Lambda 中托管的 Nodejs 代码连接到我的 Amazon RDS MySQL 实例 我需要帮助来找出我做错了什么 我收到 连接 ETIMEDOUT 错误 我的代码托管在
  • 不同源文件中的 D 模板特化

    我最近问this https stackoverflow com questions 6328444 type classes in d有关如何在 D 中模拟类型类的问题 并建议了一种使用模板专业化来实现此目的的方法 我发现 D 无法识别不
  • 基于不同XAML的样式继承

    如何将样式中的 BasedOn 标记指定为在其他文件中定义的样式 Example Dictionary1 xaml 定义 在 Dictionary2 xaml 中我需要类似的东西
  • 从 pandas 数据框中删除闰年日

    我有福尔 数据框 datetime 2012 01 01 125 5010 2012 01 02 125 5010 2012 01 03 125 5010 2012 02 04 125 5010 2012 02 05 125 5010 20
  • 我是否需要担心“Rc”的开销?

    我是否正确地假设唯一 放慢速度 的事情Rc问题是它会在对象删除时检查是否释放该对象 除此之外 取消引用的开销是 多少 Rc 即我应该关心它吗 这两个函数几乎同样快吗 或者说速度上有明显的区别吗 fn test with box let b
  • 日志记录和同步

    我刚刚编写了自己的日志框架 非常轻量级 不需要大型日志框架 它由一个接口 ILogger 和许多实现该接口的类组成 我有一个问题是 TGUILogger 它采用 TStrings 作为日志记录目标 并将日志记录与主线程同步 以便列表框的 I
  • Linux 中如何给线程命名? [复制]

    这个问题在这里已经有答案了 我有一个用 C C 编写的多线程 Linux 应用程序 我有为我的线程选择名称 https stackoverflow com questions 149932 naming conventions for th
  • Java正则表达式跳过匹配

    我有一些文字 我想提取不以标点符号分隔的单词对 这是代码 n grams Pattern p Pattern compile a z if n 2 p Pattern compile a z a z if n 3 p Pattern com
  • 如何在supervisor中添加延迟到受监督进程 - linux

    我添加了一个使用 python cassandra 库的 Bottle 服务器 但它存在以下错误 Bottle FATAL Exited too quickly process log may have details 日志显示 File
  • Android JNI 本机 C 函数调用杀死活动

    什么有效 我有一个运行 TUN TAP 服务的 c 可执行文件 以及两个在终端中运行良好的 shell 脚本 用于配置 ip 路由 和 iptables 全部以 root 身份运行 什么不起作用 我正在尝试创建一个 Android 应用程序