zoukankan      html  css  js  c++  java
  • [工作积累] Android system dialog with native callback

    JNI: invoke java dialog with native callback:

    store native function address in java, and invoke native another method to this function.

    key points:

    1.Store callback function pointer(address) in java: to support multiple calls, use data block for each call.

    2.Use primitive long(64bit) in Java to store native callback pointer, for 64 bit native compatibility

    3.intptr_t for pointer in native.

    4.Show dialog  in UI thread (Activity.runOnUiThread )

    5.optional: Let the native code to handle localization (minimize Java code)

    Java:

     1 public static native void nativeOnSystemDialogResult(long nativeFuncAddr);
     2 
     3 
     4     class DialogRunnable implements Runnable {
     5         public String mTitle;
     6         public String mMessage;
     7         public String mYes;
     8         public String mNo;
     9         public long mOnYesAddr;
    10         public long mOnNoAddr;
    11         public boolean mTwoButton;
    12 
    13         //////////////////////////////////////////////////////////////////////////
    14         ///title, message, localized Yes No
    15         DialogRunnable(String tittle, String message, String locYes, String locNo, long onYesAddr, long onNoAddr, boolean twoButton)
    16         {
    17             mTitle = tittle;
    18             mMessage = message;
    19             mYes = locYes;
    20             mNo = locNo;
    21             mOnYesAddr = onYesAddr;
    22             mOnNoAddr = onNoAddr;
    23             mTwoButton = twoButton;
    24         }
    25 
    26         //////////////////////////////////////////////////////////////////////////
    27         public void run() {
    28 
    29             if( mTwoButton ) {
    30                 Dialog dialog = new AlertDialog.Builder( GameActivity.getInstance() )
    31                 .setTitle(mTitle)
    32                 .setMessage(mMessage)
    33                 .setPositiveButton( mYes, new DialogInterface.OnClickListener() {
    34                                                     public void onClick(DialogInterface dialog, int whichButton) {
    35                                                         GameActivity.getInstance().nativeOnSystemDialogResult( mOnYesAddr );
    36                                                     }
    37                                                 })
    38                 .setNegativeButton( mNo, new DialogInterface.OnClickListener() {
    39                                                     public void onClick(DialogInterface dialog, int whichButton) {
    40                                                         GameActivity.getInstance().nativeOnSystemDialogResult( mOnNoAddr );
    41                                                     }
    42                                                 })
    43                 .setCancelable(false)
    44                 .create();
    45                 dialog.show();
    46             }else {
    47                 Dialog dialog = new AlertDialog.Builder( GameActivity.getInstance() )
    48                 .setTitle(mTitle)
    49                 .setMessage(mMessage)
    50                 .setPositiveButton( mNo, new DialogInterface.OnClickListener() {
    51                                                     public void onClick(DialogInterface dialog, int whichButton) {
    52                                                         GameActivity.getInstance().nativeOnSystemDialogResult( mOnYesAddr );
    53                                                     }
    54                                                 })
    55                 .setCancelable(false)
    56                 .create();
    57                 dialog.show();
    58             }
    59         }
    60     }
    61 
    62 
    63     //////////////////////////////////////////////////////////////////////////
    64     //Cooperate with native code. DO NOT call on Java
    65     //////////////////////////////////////////////////////////////////////////
    66     public void showDialogYesNo(String title, String showText, String locYes, String locNo, long onYesAddr, long onNoAddr) {
    67         this.runOnUiThread( new DialogRunnable(title, showText, locYes, locNo, onYesAddr, onNoAddr, true) );
    68     }
    69     
    70     
    71     
    72     

    C (for C++, JNI calls are simpler & different)

    1 JNIEXPORT void JNICALL Java_com_org_package_GameActivity_nativeOnSystemDialogResult(JNIEnv *env, jobject thiz, jlong functionAddr)
    2 {
    3     typedef void(*FUNCPTR)(void);
    4     FUNCPTR ptr = (FUNCPTR)(void*)function;
    5     if( ptr != null )
    6         ptr();
    7 }
     1 //////////////////////////////////////////////////////////////////////////
     2 //Note: onOK & onCancel can be NULL
     3 void    Android_SystemDialog(const char* title, const char* message, const char* yes, const char* no, void(*onOK)(void), void(*onCancel)(void) )
     4 {
     5     android_app* app = GetApp();
     6     JNIEnv* env = app->activity->env;
     7     //note: we need to attach dalvik VM to current thread, as it is not main thread
     8     JavaVM* vm = app->activity->vm;
     9     if ( (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) < 0 )
    10         (*vm)->AttachCurrentThread(vm, &env, NULL);
    11 
    12     jclass ActivityClass = (*env)->GetObjectClass(env, app->activity->clazz);
    13     jmethodID java_method = (*env)->GetMethodID(env, ActivityClass, 
    14         (char8*)"showDialogYesNo", 
    15         (char8*)"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJ)V");
    16     assert( java_method != NULL );
    17 
    18     jstring jTitle = (*env)->NewStringUTF(env, title, strlen(title) );
    19     jstring jMsg = (*env)->NewStringUTF(env, message, strlen(message) );
    20     jstring jOK = (*env)->NewStringUTF(env, yes, strlen(yes) );
    21     jstring jCancel = (*env)->NewStringUTF(env, no, strlen(no) );
    22     //Note: jlong is 64 bit
    23     jlong jOnOK = (intptr_t)onOK;
    24     jlong jOnCancel = (intptr_t)onCancel;
    25     //invoke UI Dialog in another thread
    26     (*env)->CallVoidMethod(env, app->activity->clazz , java_method, jTitle, jMsg, jOK, jCancel, jOnOK, jOnCancel);
    27 
    28     (*env)->DeleteLocalRef(env, jTitle);
    29     (*env)->DeleteLocalRef(env, jMsg);
    30     (*env)->DeleteLocalRef(env, jOK);
    31     (*env)->DeleteLocalRef(env, jCancel);
    32     (*env)->DeleteLocalRef(env, ActivityClass);
    33 }

    native usage sample:

     1 static void OnExit()
     2 {
     3     exit(0);
     4 }
     5 
     6 void Android_Confirm_Exit()
     7 {
     8     const char* title = "Quit";
     9     const char* message = "Unsaved progress will be lost.
    Are you sure you want to quit game?";
    10     const char* yes = "Ok";
    11     const char* no = "Cancel";
    12     Android_SystemDialog(title, message, yes, no, &OnExit, NULL);
    13 }
  • 相关阅读:
    shell命令编程小例
    汇编输出0255ascii码(VGA下)
    linux程序时间控制小例
    Undefined exploded archive location 项目不能部署
    关于org.apache.jasper.JasperException: Unable to compile class for JSP问题的解决
    Some characters cannot be mapped using "GBK" character encoding 的解决办法
    如何处理Windows Forms程序中未处理的异常
    关于bos的edit页面的文件加载顺序
    关于unable to extend lob segment的问题解决方法
    从事ASP.NET开发两年多,谈谈对两三年工作经验的ASP.NET程序员的基本见解
  • 原文地址:https://www.cnblogs.com/crazii/p/4243434.html
Copyright © 2011-2022 走看看