You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JNI调用Java弹出Android对话框并回传用户选择结果的实现问题

问题根源

Android 系统的AlertDialog.show()是异步执行逻辑,调用后不会阻塞当前线程等待用户操作,会直接继续执行后续代码,所以你现有的同步调用逻辑无法拿到用户的选择结果。

实现方案

这里提供两种可行方案,你可以根据自己的业务场景选择:


方案1:同步阻塞返回(适配你现有JNI调用逻辑,改动最小)

前置要求

JNI层调用GetOption()的线程必须是非主线程,否则会阻塞主线程触发ANR,对话框也无法正常显示。

Java侧代码修改

public class appJNI extends Activity {
    // 存储选择结果
    private Short selectResult = null;
    // 同步锁对象
    private final Object dialogLock = new Object();

    // 注意方法签名要和JNI层查找的`()S`完全对齐,不要多余参数
    private short getSelectedOption() {
        // 对话框必须在主线程弹出,所以先post到主线程执行
        runOnUiThread(() -> {
            AlertDialog alertDialog = new AlertDialog.Builder(appJNI.this).create();
            alertDialog.setTitle("Title");
            alertDialog.setMessage("What is your option?");
            // 禁止点击对话框外部关闭,避免无限等待
            alertDialog.setCancelable(false);
            
            // 第一个选项
            alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "选项1", (dialog, which) -> {
                dialog.dismiss();
                synchronized (dialogLock) {
                    selectResult = 1;
                    // 唤醒等待的线程
                    dialogLock.notifyAll();
                }
            });
            
            // 第二个选项
            alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "选项2", (dialog, which) -> {
                dialog.dismiss();
                synchronized (dialogLock) {
                    selectResult = 2;
                    dialogLock.notifyAll();
                }
            });
            
            alertDialog.show();
        });

        // 阻塞当前调用线程,等待用户选择完成
        synchronized (dialogLock) {
            while (selectResult == null) {
                try {
                    dialogLock.wait();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    // 线程被中断返回错误码
                    return -1;
                }
            }
            short result = selectResult;
            // 重置状态,方便下次调用
            selectResult = null;
            return result;
        }
    }
}

JNI侧代码修改

你原有JNI代码不需要大改,只需要确认GetMethodID查找的方法签名()S和Java侧方法完全匹配即可。


方案2:异步回调(无阻塞,更灵活)

如果你的JNI调用线程不能被阻塞,可以选择JNI被动接收回调的方案:

1. Java侧新增native回调方法

// 声明native回调方法,用户选择后调用该方法通知JNI层
public native void onOptionSelected(short result);

2. 对话框点击逻辑里触发回调

alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "选项1", (dialog, which) -> {
    dialog.dismiss();
    onOptionSelected((short)1);
});
alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "选项2", (dialog, which) -> {
    dialog.dismiss();
    onOptionSelected((short)2);
});

3. JNI侧实现回调方法

JNIEXPORT void JNICALL Java_com_myapp_main_appJNI_onOptionSelected(JNIEnv *env, jobject thiz, jshort result) {
    // 这里直接拿到用户选择的result,处理后续逻辑即可
    // your logic here
}

这种方案不需要JNI侧主动同步调用拿结果,也不存在线程阻塞问题,更推荐用于主线程调用的场景。

内容的提问来源于stack exchange,提问作者Palantiir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 04:24:02