我有以下仅在 Android 4.1 上出现的奇怪问题:当打开虚拟键盘并且用户按下 BACK 按钮时,我的应用程序只是冻结并且不再反应。过了一会儿会弹出一个系统对话框,通知我该应用程序已死并且将被关闭。我很难想象这是 Android 中的一个错误,因为通过按 BACK 按钮隐藏键盘是应该正常工作的基本功能。不过,我的代码太小了,几乎可以完全排除代码中的错误。
这是我的代码供您查看:
static int quit = 0;
static void engine_handle_cmd(struct android_app *app, int32_t cmd)
{
switch(cmd) {
case APP_CMD_TERM_WINDOW:
quit = 1;
break;
}
}
static int32_t engine_handle_input(struct android_app *app, AInputEvent *event)
{
switch(AInputEvent_getType(event)) {
case AINPUT_EVENT_TYPE_MOTION: {
int action = AMotionEvent_getAction(event);
if((action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) showkeyboard(app);
break;
}
}
return 0;
}
void android_main(struct android_app* state)
{
int events, fd;
struct android_poll_source *source;
app_dummy();
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
while(!quit) {
if(ALooper_pollOnce(-1, &fd, &events, (void **) &source) >= 0) {
if(source) source->process(state, source);
}
}
exit(0);
}
showkeyboard() 函数在 JNI 中实现如下:
static void showkeyboard(struct android_app* state)
{
// Attaches the current thread to the JVM.
jint lResult;
jint lFlags = 0;
JavaVM *lJavaVM = state->activity->vm;
JNIEnv *lJNIEnv = state->activity->env;
JavaVMAttachArgs lJavaVMAttachArgs;
jobject lNativeActivity, INPUT_METHOD_SERVICE;
jclass ClassNativeActivity, ClassContext;
jfieldID FieldINPUT_METHOD_SERVICE;
JNIEnv *env;
int attached = 0;
// must check if we're already attached!
switch((*lJavaVM)->GetEnv(lJavaVM, (void**) &env, JNI_VERSION_1_6)) {
case JNI_OK:
break;
case JNI_EDETACHED:
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
lJavaVMAttachArgs.name = "NativeThread";
lJavaVMAttachArgs.group = NULL;
lResult = (*lJavaVM)->AttachCurrentThread(lJavaVM, &lJNIEnv, &lJavaVMAttachArgs);
if(lResult == JNI_ERR) return;
attached = 1;
break;
case JNI_EVERSION:
return; // Invalid Java version
}
// Retrieves NativeActivity.
lNativeActivity = state->activity->clazz;
ClassNativeActivity = (*lJNIEnv)->GetObjectClass(lJNIEnv, lNativeActivity);
// Retrieves Context.INPUT_METHOD_SERVICE.
ClassContext = (*lJNIEnv)->FindClass(lJNIEnv, "android/content/Context");
FieldINPUT_METHOD_SERVICE = (*lJNIEnv)->GetStaticFieldID(lJNIEnv, ClassContext, "INPUT_METHOD_SERVICE", "Ljava/lang/String;");
INPUT_METHOD_SERVICE = (*lJNIEnv)->GetStaticObjectField(lJNIEnv, ClassContext, FieldINPUT_METHOD_SERVICE);
{
// Runs getSystemService(Context.INPUT_METHOD_SERVICE).
jclass ClassInputMethodManager = (*lJNIEnv)->FindClass(lJNIEnv, "android/view/inputmethod/InputMethodManager");
jmethodID MethodGetSystemService = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassNativeActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
jobject lInputMethodManager = (*lJNIEnv)->CallObjectMethod(lJNIEnv, lNativeActivity, MethodGetSystemService, INPUT_METHOD_SERVICE);
// Runs getWindow().getDecorView().
jmethodID MethodGetWindow = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassNativeActivity, "getWindow", "()Landroid/view/Window;");
jobject lWindow = (*lJNIEnv)->CallObjectMethod(lJNIEnv, lNativeActivity, MethodGetWindow);
jclass ClassWindow = (*lJNIEnv)->FindClass(lJNIEnv, "android/view/Window");
jmethodID MethodGetDecorView = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassWindow, "getDecorView", "()Landroid/view/View;");
jobject lDecorView = (*lJNIEnv)->CallObjectMethod(lJNIEnv, lWindow, MethodGetDecorView);
// Runs lInputMethodManager.showSoftInput(...).
jmethodID MethodShowSoftInput = (*lJNIEnv)->GetMethodID(lJNIEnv, ClassInputMethodManager, "showSoftInput", "(Landroid/view/View;I)Z");
(*lJNIEnv)->CallBooleanMethod(lJNIEnv, lInputMethodManager, MethodShowSoftInput, lDecorView, lFlags);
if(attached) {
// Finished with the JVM.
(*lJavaVM)->DetachCurrentThread(lJavaVM);
}
}
}
要重现,您只需编译应用程序,将其放到带有 Android 4.1 映像的模拟器上,然后单击某个位置,就会显示虚拟键盘。现在尝试使用 BACK 按钮关闭键盘。该应用程序现在将冻结。
请注意,此错误仅在 Android 4.1 上发生。它在 2.3、3.0 和 4.0 上运行良好。这可能是Android本身的一个主要错误吗?我真的没有其他解释,因为我的代码实际上只是一个根本不做任何事情的原始主循环。但是,尝试关闭虚拟键盘仍会使应用程序崩溃。
非常感谢您在这个问题上的帮助!我已经为此苦苦挣扎了好几个小时了:(
更新 1: 该问题也出现在 Android 4.2 上。已在 Android 问题网站上打开了一张票。遇到相同问题的每个人都应该在工单上发表评论,以便 Android 开发人员意识到这一点。这是链接: http ://code.google.com/p/android/issues/detail?id=43817&thanks=43817&ts=1359632204