[工作积累] Android system dialog with native callback
2015-01-23 10:16
375 查看
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:
C (for C++, JNI calls are simpler & different)
native usage sample:
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:
public static native void nativeOnSystemDialogResult(long nativeFuncAddr); class DialogRunnable implements Runnable { public String mTitle; public String mMessage; public String mYes; public String mNo; public long mOnYesAddr; public long mOnNoAddr; public boolean mTwoButton; ////////////////////////////////////////////////////////////////////////// ///title, message, localized Yes No DialogRunnable(String tittle, String message, String locYes, String locNo, long onYesAddr, long onNoAddr, boolean twoButton) { mTitle = tittle; mMessage = message; mYes = locYes; mNo = locNo; mOnYesAddr = onYesAddr; mOnNoAddr = onNoAddr; mTwoButton = twoButton; } ////////////////////////////////////////////////////////////////////////// public void run() { if( mTwoButton ) { Dialog dialog = new AlertDialog.Builder( GameActivity.getInstance() ) .setTitle(mTitle) .setMessage(mMessage) .setPositiveButton( mYes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { GameActivity.getInstance().nativeOnSystemDialogResult( mOnYesAddr ); } }) .setNegativeButton( mNo, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { GameActivity.getInstance().nativeOnSystemDialogResult( mOnNoAddr ); } }) .setCancelable(false) .create(); dialog.show(); }else { Dialog dialog = new AlertDialog.Builder( GameActivity.getInstance() ) .setTitle(mTitle) .setMessage(mMessage) .setPositiveButton( mNo, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { GameActivity.getInstance().nativeOnSystemDialogResult( mOnYesAddr ); } }) .setCancelable(false) .create(); dialog.show(); } } } ////////////////////////////////////////////////////////////////////////// //Cooperate with native code. DO NOT call on Java ////////////////////////////////////////////////////////////////////////// public void showDialogYesNo(String title, String showText, String locYes, String locNo, long onYesAddr, long onNoAddr) { this.runOnUiThread( new DialogRunnable(title, showText, locYes, locNo, onYesAddr, onNoAddr, true) ); }
C (for C++, JNI calls are simpler & different)
JNIEXPORT void JNICALL Java_com_org_package_GameActivity_nativeOnSystemDialogResult(JNIEnv *env, jobject thiz, jlong functionAddr) { typedef void(*FUNCPTR)(void); FUNCPTR ptr = (FUNCPTR)(void*)function; if( ptr != null ) ptr(); }
////////////////////////////////////////////////////////////////////////// //Note: onOK & onCancel can be NULL void Android_SystemDialog(const char* title, const char* message, const char* yes, const char* no, void(*onOK)(void), void(*onCancel)(void) ) { android_app* app = GetApp(); JNIEnv* env = app->activity->env; //note: we need to attach dalvik VM to current thread, as it is not main thread JavaVM* vm = app->activity->vm; if ( (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) < 0 ) (*vm)->AttachCurrentThread(vm, &env, NULL); jclass ActivityClass = (*env)->GetObjectClass(env, app->activity->clazz); jmethodID java_method = (*env)->GetMethodID(env, ActivityClass, (char8*)"showDialogYesNo", (char8*)"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJ)V"); assert( java_method != NULL ); jstring jTitle = (*env)->NewStringUTF(env, title, strlen(title) ); jstring jMsg = (*env)->NewStringUTF(env, message, strlen(message) ); jstring jOK = (*env)->NewStringUTF(env, yes, strlen(yes) ); jstring jCancel = (*env)->NewStringUTF(env, no, strlen(no) ); //Note: jlong is 64 bit jlong jOnOK = (intptr_t)onOK; jlong jOnCancel = (intptr_t)onCancel; //invoke UI Dialog in another thread (*env)->CallVoidMethod(env, app->activity->clazz , java_method, jTitle, jMsg, jOK, jCancel, jOnOK, jOnCancel); (*env)->DeleteLocalRef(env, jTitle); (*env)->DeleteLocalRef(env, jMsg); (*env)->DeleteLocalRef(env, jOK); (*env)->DeleteLocalRef(env, jCancel); (*env)->DeleteLocalRef(env, ActivityClass); }
native usage sample:
static void OnExit() { exit(0); } void Android_Confirm_Exit() { const char* title = "Quit"; const char* message = "Unsaved progress will be lost.\nAre you sure you want to quit game?"; const char* yes = "Ok"; const char* no = "Cancel"; Android_SystemDialog(title, message, yes, no, &OnExit, NULL); }
相关文章推荐
- native programming with android building system
- Android 6.0 应用权限(二) -- 与系统权限一起工作(Working with System Permissions) 使用MarkDown重新整理了排版
- native programming with android building system
- native programming with android building system
- Android 6.0 应用权限(二) -- 与系统权限一起工作(Working with System Permissions)
- [工作积累] Android dynamic library & JNI_OnLoad
- [工作积累] Android: Hide Navigation bar 隐藏导航条
- Port SDL/TinySDGL to android with native C
- Android--Camera.addCallbackBuffer/setPreviewCallbackWithBuffer模式使用总结
- The import android.content.DialogInterface.OnClickListener collides with another import statement
- How to debug Android Native Application with eclipse
- [工作积累] android 中添加libssl和libcurl
- Flashing your Android Dev Phone with a Factory System Image
- Android项目中New package not yet registered with the system的解决方法
- Android错误之New package not yet registered with the system
- swtbot deal with native dialog
- DPF.Android.Native.Components.v2.8.1 for delphi xe6 使用DPFJAlertDialog遇到的问题
- Include Native *.so Library in APK With Android Studio
- ISO C++forbids declaration of 'SystemSetDialog' with no type的问题解决
- Android: setPreviewCallbackWithBuffer, buffer in the queue and no callbacks