关于ndk开发使用jni回掉java方法更新UI的问题

来源:互联网 发布:资管业务 知乎 编辑:程序博客网 时间:2024/06/10 23:11

重新整理,

原理:

应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件, 进行事件分发。

耗时的操作,放在一个子线程中,如果子线程涉及到UI更新,那就要用到handler,Android主线程是线程不安全的, 也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。

Handler运行在主线程中(UI线程中),  它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)  , 把这些消息放入主线程队列中,配合主线程进行更新UI。

重点关注这里

MyHandler myHandler; 
static MyHandler mHandler;

要用这个mHandler才能保证回调的方法还在当前环境下,否则调不到,会报错。

代码如下:

[java] view plain copy
  1. Java代码:  
  2. package com.example.hellojni;  
  3. public class callbyc extends Activity{  
  4.     TextView  textpin;   
  5.     static Context context;  
  6.     MyHandler myHandler;   
  7.     static MyHandler mHandler;  
  8.      
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState)  
  11.     {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.callbyc);    
  14.           
  15.         JniInterface.nativeInit();  
  16.         textpin = (TextView)findViewById(R.id.textinfo);         
  17.   
  18.         myHandler = new MyHandler();   
  19.         mHandler = myHandler;//重要,保存全局静态handler句柄,以便回掉的时候能找到该上下文  
  20.         MyThread m = new MyThread();   
  21.         new Thread(m).start();   
  22.           
  23.     }  
  24.     class MyHandler extends Handler {   
  25.         public MyHandler() {   
  26.         }   
  27.    
  28.         public MyHandler(Looper L) {   
  29.             super(L);   
  30.         }   
  31.    
  32.         // 子类必须重写此方法,接受数据   
  33.         @Override   
  34.         public void handleMessage(Message msg) {   
  35.             // TODO Auto-generated method stub   
  36.             System.out.println("handleMessage。。。。。。");   
  37.             super.handleMessage(msg);   
  38.               
  39.             // 此处可以更新UI   
  40.             Bundle b = msg.getData();   
  41.             String color = b.getString("color");   
  42.             System.out.println("color:"+color);   
  43.             textpin.setText(color);  
  44.   
  45.         }   
  46.     }   
  47.     class MyThread implements Runnable {   
  48.         public void run() {   
  49.    
  50.             try {   
  51.                 Thread.sleep(1000);   
  52.             } catch (InterruptedException e) {   
  53.                 // TODO Auto-generated catch block   
  54.                 e.printStackTrace();   
  55.             }   
  56.    
  57.             System.out.println("mThread。。。。。。。。");   
  58.             JniInterface.pinTest();//jni里面方法回调inputPin   
  59.         }   
  60.     }       
  61.     public  void myCallbackFunc(String nMsg)  
  62.     {  
  63.         System.out.println("myCallbackFunc。。。。。。。。");   
  64.         Message msg = new Message();   
  65.         Bundle b = new Bundle();// 存放数据   
  66.         b.putString("color","我的");   
  67.         msg.setData(b);   
  68.         System.out.println("。。。。。。。。");   
  69.           
  70.        // callbyc.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI   
  71.     }  
  72.       
  73.     private static void DispInfo(int value)  
  74.     {  
  75.         System.out.println("this is called by c value:"+value);  
  76.         //Toast.makeText(mainContext, "this is from c:"+value,Toast.LENGTH_LONG).show();  
  77.     }   
  78.    
  79.     private  String inputPin()  
  80.     {  
  81.         System.out.println("pls input pin");  
  82.   
  83.   
  84.         Message msg = new Message();   
  85.         Bundle b = new Bundle();// 存放数据   
  86.         b.putString("color","123456");   
  87.         msg.setData(b);   
  88.         mHandler.sendMessage(msg);//这里用静态mHandler才能在回掉该方法的时候正确执行  
  89.         //callbyc.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI           
  90.         return "123456";  
  91.         //textpin.setText("bbb");  
  92.     }   
  93. }  
  94.    
  95. jni代码:  
  96. #include <jni.h>  
  97.   
  98. jmethodID gOnNativeID;  
  99. JNIEnv* genv;  
  100. jobject mObject;  
  101. jclass mClass;  
  102. JavaVM* gs_jvm;  
  103. //native初始化函数  
  104. void Java_com_example_hellojni_JniInterface_nativeInit(JNIEnv* env,jobject thiz)  
  105. {  
  106.   
  107.   
  108.     printf("CalledForJni_nativeInit................");  
  109.       
  110.     //获取类  
  111.     jclass clazz = (*env)->FindClass(env,"com/example/hellojni/callbyc");  
  112.     if(clazz==NULL)  
  113.     {  
  114.         printf("clazz IS NULL................");  
  115.         return;  
  116.     }  
  117.   
  118.     mObject = (jobject)(*env)->NewGlobalRef(env,thiz);//永久保存mClass  
  119.     //获取方法ID  
  120.     gOnNativeID = (*env)->GetMethodID(env,clazz,"inputPin","()Ljava/lang/String;");    
  121.       
  122.     if(gOnNativeID==NULL)  
  123.     {  
  124.         printf("gOnNativeID IS NULL................");  
  125.         return;  
  126.     }  
  127.     //得到JAVA VM,为了在其他没有传env参数的函数获取emv调用java方法  
  128.     (*env)->GetJavaVM(env,&gs_jvm);   
  129.     printf("CalledForJni_nativeInit end................");  
  130.   
  131.   
  132. }  
  133. void Java_com_example_hellojni_JniInterface_pinTest(JNIEnv* env,jobject thiz)  
  134. {  
  135.     UTIL_OnlinePIN();  
  136. }  
  137. uchar UTIL_OnlinePIN()  
  138. {  
  139.     char message[]="PLS INPUT PIN";  
  140.     int nStatus;      
  141.     JNIEnv *env;  
  142.     jstring recv;  
  143.     char *precvbuf;  
  144.     int i=0;  
  145.     //JNI_VERSION_1_2  
  146.     //nStatus = gs_jvm->GetEnv((void**)&env,JNI_VERSION_1_2);  
  147.     //得到当前线程的env,为了在没有传env参数的函数获取env调用java方法  
  148.     nStatus = (*gs_jvm)->AttachCurrentThread(gs_jvm, (void**)&env, NULL);  
  149.     if(nStatus<0)  
  150.     {  
  151.         printf("getenv faild");  
  152.     }  
  153.     printf("PLS INPUT PIN %s-%d",__FUNCTION__,__LINE__);  
  154.     //(*env)->CallStaticVoidMethod(env,mObject,gOnNativeID,99);  
  155.     recv = (*env)->CallObjectMethod(env,mObject,gOnNativeID);  
  156.     precvbuf = (*env)->GetStringUTFChars(env,recv,0);  
  157.       
  158.     dumpData("recvpin",precvbuf,6);  
  159.       
  160.     (*env)->ReleaseStringUTFChars(env,recv,precvbuf);  
  161.     printf("%s-%d",__FUNCTION__,__LINE__);  
  162.       
  163.     //退出当前线程要调用DetachCurrentThread()释放对应的资源  
  164.   
  165.   
  166. }  
阅读全文
0 0
原创粉丝点击