jni不通过线程c回调java的函数

时间:2022-02-04 07:24:33

整个工程的项目如下:

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