使用本机活动时关闭软键盘时崩溃

Pet*_*iak 5 android android-ndk android-layout native-activity

我们正在为Android开发一个独立游戏,并希望用户选择他的昵称.我们选择使用NDK提供的Native Activity,因为这似乎是最简单的方法.

我们用键盘遇到的第一个问题是,该功能ANativeActivity_showSoftInput()似乎做什么都没有(如例如这里),所以我们使用JNI调用函数调出键盘:

static void showKeyboard(Activity activity) {
  String s = Context.INPUT_METHOD_SERVICE;
  InputMethodManager m = (InputMethodManager)activity.getSystemService(s);
  View w = activity.getWindow().getDecorView();
  m.showSoftInput(w, 0);
}
Run Code Online (Sandbox Code Playgroud)

这适用于调出键盘,并且可以在一些设备上一起正常工作.但在其他设备(例如Nexus 7)上,当用户尝试通过点击"隐藏键盘"按钮关闭键盘时,应用程序会冻结此调试输出:

I/InputDispatcher(  453): Application is not responding: AppWindowToken{429b54a8 token=Token{42661288 ActivityRecord{41bb0b00 u0 com.example.project/android.app.NativeActivity}}} - Window{420d6138 u0 com.example.project/android.app.NativeActivity}.  It has been 5006.7ms since event, 5005.6ms since wait started.  Reason: Waiting because the focused window has not finished processing the input events that were previously delivered to it.
I/WindowManager(  453): Input event dispatching timed out sending to com.example.project/android.app.NativeActivity
Run Code Online (Sandbox Code Playgroud)

然后向用户显示一个对话框,说明:

Project isn't responding. Do you want to close it? [Wait]/[OK]
Run Code Online (Sandbox Code Playgroud)

我们做的事情显然是错的吗?或者这可能是一个错误?像这样的问题似乎表明键盘功能从未在原生胶中正确实现.

另外,我们还没有在很多设备上进行过测试,但是它没有崩溃的是那些拥有较旧Android操作系统的设备.此外,在它崩溃的那些,当键盘出现时,它会改变后退按钮,看起来像这样向后箭头形按钮 到一个看起来像这样的人 V形按钮.也许这对应于一个不同的输入事件,当他们第一次开发原生胶时没有考虑到这些事件?我只是在猜测.

无论如何,如果有人在使用原生活动时使用软键盘,请告诉我们您是如何做到的.

干杯

UPDATE

据报道,作为Android的一个bug 在这里,我们还是会很乐意听到的解决方法,但.如果您也受到影响,您可能希望对该问题进行投票(通过按星号).

krs*_*eve 3

彼得的解决方案效果很好。但是,如果您不想修改 native_app_glue 文件:请注意 process_input 被分配为函数指针。在您的实现文件中,按照 Peter 的描述创建您自己的 process_input 函数:

static void process_input( struct android_app* app, struct android_poll_source* source) {
    AInputEvent* event = NULL;
    if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
        int type = AInputEvent_getType(event);
        LOGV("New input event: type=%d\n", AInputEvent_getType(event));

        bool skip_predispatch
              =  AInputEvent_getType(event)  == AINPUT_EVENT_TYPE_KEY
              && AKeyEvent_getKeyCode(event) == AKEYCODE_BACK;

        // skip predispatch (all it does is send to the IME)
        if (!skip_predispatch && AInputQueue_preDispatchEvent(app->inputQueue, event)) {
            return;
        }

        int32_t handled = 0;
        if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
        AInputQueue_finishEvent(app->inputQueue, event, handled);
    } else {
        LOGE("Failure reading next input event: %s\n", strerror(errno));
    }
}
Run Code Online (Sandbox Code Playgroud)

在android_main函数的开头,将process_input的版本分配给android_app->inputPollSource.process

在事件处理程序中,确保检查后退键 ( AKEYCODE_BACK ) 并拦截它以隐藏键盘(如果可见)。

请注意,此问题似乎存在于 Android 4.1 和 4.2 中 - 已在 4.3 中解决