首页 > 代码库 > [工作积累] Android system dialog with native callback
[工作积累] 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 No15 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 Java65 //////////////////////////////////////////////////////////////////////////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 bit23 jlong jOnOK = (intptr_t)onOK;24 jlong jOnCancel = (intptr_t)onCancel;25 //invoke UI Dialog in another thread26 (*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.\nAre 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 }
[工作积累] Android system dialog with native callback
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。