[通过NDK回调在Android中创建消息对话框

问题描述 投票:2回答:1

我有一个android应用程序,其中在Java端设置了OpenGL上下文,并正在从NDK / C ++端发送图形。这一切似乎都很好。

我希望C ++端能够弹出一个对话框。我实现了一个Java MakeADialog函数,该函数通过env->CallVoidMethod(javaClass, javaMethod);从C端被很好地激发了。Java端的接收函数如下所示:

public static void MakeADialog() {  
     Log.w("title", "MakeADialog fired!");
}

这是一个单独的类(不是ActivityRunnable)。上面的工作正常,我可以看到我的MakeADialg日志消息。但是,当我尝试创建一个实际的对话框时,我会崩溃。我可以告诉我,当我从C端调用到Java端时,我并没有担心正在运行的“线程”。尝试创建新的线程/对话框时,似乎遇到了麻烦。

我在这里尝试过很多有关创建Runnable,Thread等的建议-但它们似乎总是给我一个可怕的'无法在未调用Looper.prepare()的线程内创建处理程序的提示。该视图的父级为null。这些方法大多数都围绕着将Activity和Context指针存储为静态,并在进入MakeADialog回调时通过get函数检索它们。

[AlertDialog alertDialog = new AlertDialog.Builder(MyApp.GetMyContext()).create();其中,GetMyContext()函数只是返回我在应用程序启动期间存储的主要活动创建线程的this指针。

有没有人弹出从NDK端启动的对话框,或者可以指出一些相关文档,这些文档将帮助我了解如何从NDK回调中创建新对话框?

提前感谢!

java android opengl-es dialog android-ndk
1个回答
0
投票

也许我们可以使用gist中的示例创建一个模式对话框。我怀疑您是从辅助线程中调用它的,因此“它们似乎总是给我一个可怕的'无法在未调用Looper.prepare()的线程内创建处理程序'”或该视图的父级为null。 (另请参见Can't create handler inside thread that has not called Looper.prepare()。)>

基于官方示例Native Activitythe gist code的键代码:

  1. 在Java方面,>
    package ss.fang.brickgo;
    
    import android.app.AlertDialog;
    import android.app.Dialog;
    import android.app.NativeActivity;
    import android.content.DialogInterface;
    import android.content.pm.ApplicationInfo;
    import android.graphics.Color;
    import android.graphics.drawable.ColorDrawable;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.Window;
    import android.view.WindowManager;
    
    import java.util.concurrent.Semaphore;
    
    public class GameActivity extends NativeActivity {
        // Use a semaphore to create a modal dialog
        private final Semaphore semaphore = new Semaphore(0, true);
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        // This function will be called from C++ by name and signature
        public void showAlert(final String message) {
            ApplicationInfo applicationInfo = getApplicationInfo();
            final CharSequence appName = getPackageManager().getApplicationLabel(applicationInfo);
            this.runOnUiThread(new Runnable() {
                public void run() {
                    AlertDialog.Builder builder = new AlertDialog.Builder(GameActivity.this, AlertDialog.THEME_HOLO_DARK);
                    builder.setTitle(appName);
                    builder.setMessage(message);
                    DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            semaphore.release();
                            if (DialogInterface.BUTTON_POSITIVE == id) {
                                GameActivity.this.finish();
                            }
                        }
                    };
                    builder.setNegativeButton(android.R.string.cancel, listener);
                    builder.setPositiveButton(android.R.string.ok, listener);
                    builder.setCancelable(false);
                    AlertDialog dialog = builder.create();
                    dialog.show();
                }
            });
            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                Log.v("GameActivity", "ignored", e);
            }
        }
    
        protected void showDialog() {
            Dialog dialog = new Dialog(this);
            dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
            dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
            // layout to display
            dialog.setContentView(R.layout.dialog_layout);
    
            // set color transpartent
            dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    
            dialog.show();
        }
    }
    
    1. 在本机(C ++ 11)端,
    void showAlert(struct android_app *state, const char *message);
    
    /** Process the next input event. */
    static int32_t engine_handle_input(struct android_app *app, AInputEvent *event) {
        auto *engine = (struct engine *) app->userData;
        auto type = AInputEvent_getType(event);
        if (AINPUT_EVENT_TYPE_MOTION == type) {
            engine->animating = 1;
            engine->state.x = AMotionEvent_getX(event, 0);
            engine->state.y = AMotionEvent_getY(event, 0);
            return 1;
        } else if (AINPUT_EVENT_TYPE_KEY == type) {
            auto action = AKeyEvent_getAction(event);
            if (AKEY_EVENT_ACTION_DOWN == action && AKEYCODE_BACK == AKeyEvent_getKeyCode(event)) {
                // skip predispatch (all it does is send to the IME)
                //if (!AInputQueue_preDispatchEvent(app->inputQueue, event))
                //int32_t handled = 0;
                //if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
                //AInputQueue_finishEvent(app->inputQueue, event, handled);
                showAlert(app, "Go Back?");
                return 1;
            }
        }
        return 0; //not handled
    }
    
    
    void showAlert(struct android_app *state, const char *message) {
        JNIEnv *jni = NULL;
        state->activity->vm->AttachCurrentThread(&jni, NULL);
    
        jclass clazz = jni->GetObjectClass(state->activity->clazz);
    
        // Get the ID of the method we want to call
        // This must match the name and signature from the Java side Signature has to match java
        // implementation (second string hints a t a java string parameter)
        jmethodID methodID = jni->GetMethodID(clazz, "showAlert", "(Ljava/lang/String;)V");
    
        // Strings passed to the function need to be converted to a java string object
        jstring jmessage = jni->NewStringUTF(message);
    
        jni->CallVoidMethod(state->activity->clazz, methodID, jmessage);
    
        // Remember to clean up passed values
        jni->DeleteLocalRef(jmessage);
    
        state->activity->vm->DetachCurrentThread();
    }
    
    
© www.soinside.com 2019 - 2024. All rights reserved.