zoukankan      html  css  js  c++  java
  • jni不通过线程c回调java的函数

    整个工程的项目如下:

    1、项目的思路是在activity中启动MyService这个服务,在服务中调用

    JniScsManger类中的本地方法startNativeScsService,在
    startNativeScsService的c代码实现中回调JniScsManger中的scsConnectStatus方法。
    下面我们来看下两种代码的实现:
    package com.cetcs.ecmapplication.jni.scs;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    
    public class MyService extends Service {
        public MyService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            JniScsManger.getInstances().startNativeScsService();
        }
    }

    activity的代码:

    package im.weiyuan.com.jni2;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.Toast;
    
    import com.cetcs.ecmapplication.jni.scs.JniScsManger;
    import com.cetcs.ecmapplication.jni.scs.MyService;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent = new Intent(MainActivity.this, MyService.class);
            startService(intent);
        }
    }
    package com.cetcs.ecmapplication.jni.scs;
    
    import android.util.Log;
    
    /**
     * Created by wei.yuan on 2017/6/7.
     */
    
    public class JniScsManger {
        static {
            System.loadLibrary("jniscs");
        }
    
        private  static JniScsManger jniScsManger = null;
        private JniScsManger(){
    
        }
    
        public static JniScsManger getInstances(){
            if(jniScsManger == null){
                jniScsManger = new JniScsManger();
            }
            return  jniScsManger;
        }
    
        public native int startNativeScsService();
    
    
        public  void  scsConnectStatus(int status,String reason){
    
            Log.d("123456",""+status+","+reason);
    
        }
    
        public  void getScsStatus(){
            Log.d("123456",""+",");
        }
    
        public int onProgressCallBack(long total, long already) {
            //自行执行回调后的操作
            Log.d("123456",""+"onProgressCallBack");
            System.out.println("total123456:"+total);
            System.out.println("already:"+already);
            return 1;
        }
    
    }

    我们来看看本地native层实现的代码:

    第一种方式:

    //
    // Created by wei.yuan on 2017/6/7.
    //
    #include <android/log.h>
    #include <string.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <time.h>
    #include <dlfcn.h>
    #include <jni.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dlfcn.h>
    #include <assert.h>
    #include <androidlog.h>
    #include <errno.h>
    #include <pthread.h>
    
    #include "com_cetcs_ecmapplication_jni_scs_JniScsManger.h"
    //动态链接库路径
    #define LIB_SCS_PATH "libServerCenter.so"
    #define LOG_TAG "SCS123456"
    #define LOGI_JniSCS(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    
    
    JNIEXPORT jint JNICALL Java_com_cetcs_ecmapplication_jni_scs_JniScsManger_startNativeScsService(JNIEnv * env, jobject jobj){
        LOGI_JniSCS("start native ServerCenterService");
    
        //jobj对象就是java层调用startNativeScsService的对象,那个类调用startNativeScsService对应的jobj就是那个对象
        jclass javaClass = (*env)->FindClass(env, "com/cetcs/ecmapplication/jni/scs/JniScsManger");
        if (javaClass == 0) {
                  LOGI_JniSCS("Unable to find class");
                return;
            }
            //获取要回调的方法ID
            jmethodID javaCallbackId = (*env)->GetMethodID(env, javaClass,"scsConnectStatus", "(ILjava/lang/String;)V");
            if (javaCallbackId == NULL) {
                 LOGI_JniSCS("Unable to find method:onProgressCallBack");
                return;
            }
            //执行回调,注意第二个参数是jobj,不是javaClass
                (*env)->CallVoidMethod(env, jobj, javaCallbackId,1,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!"));
    
        return 4000000;
    
    }

    第二种方式:

    //
    // Created by wei.yuan on 2017/6/7.
    //
    #include <android/log.h>
    #include <string.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <time.h>
    #include <dlfcn.h>
    #include <jni.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dlfcn.h>
    #include <assert.h>
    #include <androidlog.h>
    #include <errno.h>
    #include <pthread.h>
    
    #include "com_cetcs_ecmapplication_jni_scs_JniScsManger.h"
    //动态链接库路径
    #define LIB_SCS_PATH "libServerCenter.so"
    #define LOG_TAG "SCS123456"
    #define LOGI_JniSCS(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    
    
    JNIEXPORT jint JNICALL Java_com_cetcs_ecmapplication_jni_scs_JniScsManger_startNativeScsService(JNIEnv * env, jobject jobj){
        LOGI_JniSCS("start native ServerCenterService");
    
        //jobj对象就是java层调用startNativeScsService的对象,那个类调用startNativeScsService对应的jobj就是那个对象
        jclass javaClass = (*env)->GetObjectClass(env, jobj);
        if (javaClass == 0) {
                  LOGI_JniSCS("Unable to find class");
                return;
            }
            //获取要回调的方法ID
            jmethodID javaCallbackId = (*env)->GetMethodID(env, javaClass,"scsConnectStatus", "(ILjava/lang/String;)V");
            if (javaCallbackId == NULL) {
                 LOGI_JniSCS("Unable to find method:onProgressCallBack");
                return;
            }
            //执行回调,注意第二个参数是jobj,不是javaClass
                (*env)->CallVoidMethod(env, jobj, javaCallbackId,1,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!"));
    
        return 4000000;
    
    }

    注意点:

    FindClass是通过传java中完整的类名来查找java的class, 而GetObjectClass是通过传入jni中的一个java的引用来获取该引用的类型。 前者要求你必须知道完整的类名,后者要求在Jni有一个类的引用。
    上面中传入的
    (JNIEnv * env, jobject jobj)中的jobj就是调用startNativeScsService的对象,就是JniScsManger的一个对象实例。
    FindClass是通过类名获得该对象的实例,
    GetObjectClass是获得该对象的一个引用。

    现在增加一个需求:
    我们在上传新增加一个类:
    我们要在startNativeScsService的c代码实现中回调Sb中的scsConnectStatus方法如何实现了,我们来看c层的代码
    package com.cetcs.ecmapplication.jni.scs;
    
    import android.util.Log;
    
    /**
     * Created by wei.yuan on 2017/6/26.
     */
    
    public class Sb {
        public  void  scsConnectStatus(int status,String reason){
    
            Log.d("123456",""+status+","+reason);
    
        }
    }
    //
    // Created by wei.yuan on 2017/6/7.
    //
    #include <android/log.h>
    #include <string.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <time.h>
    #include <dlfcn.h>
    #include <jni.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dlfcn.h>
    #include <assert.h>
    #include <androidlog.h>
    #include <errno.h>
    #include <pthread.h>
    
    #include "com_cetcs_ecmapplication_jni_scs_JniScsManger.h"
    //动态链接库路径
    #define LIB_SCS_PATH "libServerCenter.so"
    #define LOG_TAG "SCS123456"
    #define LOGI_JniSCS(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    
    
    JNIEXPORT jint JNICALL Java_com_cetcs_ecmapplication_jni_scs_JniScsManger_startNativeScsService(JNIEnv * env, jobject jobj){
        LOGI_JniSCS("start native ServerCenterService");
    
        //jobj对象就是java层调用startNativeScsService的对象,那个调用startNativeScsService对应的jobj就是那个对象
        jclass javaClass = (*env)->FindClass(env, "com/cetcs/ecmapplication/jni/scs/Sb");
        if (javaClass == 0) {
            LOGI_JniSCS("Unable to find class");
            return;
        }
        //构造Sb这个对象
        jmethodID constructor = (*env)->GetMethodID(env, javaClass, "<init>", "()V");
        //获取要回调的方法ID
        jmethodID javaCallbackId = (*env)->GetMethodID(env, javaClass,"scsConnectStatus", "(ILjava/lang/String;)V");
        if (javaCallbackId == NULL) {
            LOGI_JniSCS("Unable to find method:onProgressCallBack");
            return;
        }
        jobject obj = (*env)->NewObject(env, javaClass, constructor);
        //执行回调,注意第二个参数是obj,不是jobj
        (*env)->CallVoidMethod(env, obj, javaCallbackId,1,(*env)->NewStringUTF(env, "Hello from JNI000.0.0.!0..22"));
    
        return 4000000;
    
    }

    程序代码的下载地址是:

    https://pan.baidu.com/s/1gfosrp5

  • 相关阅读:
    cookie.js插件
    cookie.js插件的案例
    解决mysqli的中文乱码问题
    mysqli字符编码
    小人行走的动画案例
    原生js中用Ajax进行get传参
    php操作数据库
    数据库的信息处理
    数据库的dos命令
    面向对象php 接口 抽象类
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/7080373.html
Copyright © 2011-2022 走看看