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:

 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) < )
(*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();
} 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);
}

[工作积累] Android system dialog with native callback的更多相关文章

  1. [工作积累] android 中添加libssl和libcurl

    1. libssl https://github.com/guardianproject/openssl-android 然后执行ndk-build 2.libcurl 源代码组织结构, 下面的mak ...

  2. [工作积累] Android dynamic library & JNI_OnLoad

    Bionic libc doesn't load dependencies for current .so file (diff from Windows or Linux) so a explici ...

  3. [工作积累] Android: Hide Navigation bar 隐藏导航条

    https://developer.android.com/training/system-ui/navigation.html View decorView = getWindow().getDec ...

  4. Android PopupWindow Dialog 关于 is your activity running 崩溃详解

    Android PopupWindow Dialog 关于 is your activity running 崩溃详解 [TOC] 起因 对于 PopupWindow Dialog 需要 Activi ...

  5. Android 封装Dialog

    package com.example.myandroid01; import android.support.v7.app.ActionBarActivity; import android.os. ...

  6. [工作记录] Android OpenGL ES: non-square texture - continue

    previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found ...

  7. at android.view.Surface.unlockCanvasAndPost(Native Method)

    at android.view.Surface.unlockCanvasAndPost(Native Method) 在绘制动画特效的时候点击back键会报以上异常. 主要原因:当点击back按钮时A ...

  8. Android Theme.Dialog 到光 AppCompatDialog

    我用在我的 style.xml 作为主要应用程序主题 <style name="AppTheme" parent="Theme.AppCompat.Light&qu ...

  9. Error处理: android.media.MediaRecorder.start(Native Method) 报错:start failed: -19【转】

    本文转载自:http://blog.csdn.net/netwalk/article/details/17686993 Error处理: android.media.MediaRecorder.sta ...

随机推荐

  1. OJ推荐【转】

    来自:http://blog.csdn.net/zdp072/article/details/16207111 一. Online Judge简介: Online Judge系统(简称OJ)是一个在线 ...

  2. BufferedInputSream和BufferedOutputSream,,,

    package cd.itcast.bufferinputstream; import java.io.BufferedInputStream; import java.io.File; import ...

  3. Delphi初学者应小心的六大陷阱

    Delphi初学者应小心的六大陷阱   作者:子夜编译       初学DelphiI的人,由于各种原因,对DelphiI中的许多概念不能很好的理解,并由此带来了许多的问题,或者是开发出的程序稳性不好 ...

  4. C#高级功能(三)Action、Func,Tuple

    Action和Func泛型委托实际上就是一个.NET Framework预定义的委托,3.5引入的特性.基本涵盖了所有常用的委托,所以一般不用用户重新声明. Action系列泛型委托,是没有返回参数的 ...

  5. C#模糊查询绑定datagridview

    private CollectionViewSource wgdData = new CollectionViewSource(); private DataTable Ds_wgd { get { ...

  6. 一个.net程序员教你使用less

    我是一个.net 程序员,虽然说一直做后台,但是web 前端也会去学,虽然说技术只是层窗户纸,但是像我这种多动症患者,不捅破我心难受啊! 好!废话不多提,下面直接正题,至于less 是什么这里不多讲因 ...

  7. http压力测试

    一.http_load程序非常小,解压后也不到100Khttp_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载.但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不会把 ...

  8. 纯真IP数据库导入mysql

    下载纯真IP数据库 安装后解压到本地为ip.txt 格式为: 1.1.145.0       1.1.147.255     泰国 沙功那空 1.1.148.0       1.1.149.255   ...

  9. 常用gradle命令

    1.build.gradle ext { profile = "dev" tag='web' if (project.hasProperty('pro')) { temp = pr ...

  10. [转]rpcndr.h和wtypes.h冲突Bug的解决方案

    [转]rpcndr.h和wtypes.h冲突Bug的解决方案 http://blog.csdn.net/tzwh_86/article/details/9495133 rpcndr.h和wtypes. ...