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 <android\log.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 <android\log.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 <android\log.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM