【随笔记】Java 调用 Jni 和 Jni 回调 Java 方法

Java

package com.jni.api;

public class ApiNative {

	// 加载指定 jni 库, 并设置为单实例
	static { System.loadLibrary("jni_api");	}
    private final static ApiNative apiNative = new ApiNative();
    public static ApiNative getInstance(){
        return apiNative;
    }
   
	// 初始化接口
    public native int init();

	// 由 Jni 回调类接口
    private void onJniNoticeA(float[] f1, float[] f2){
		
	}
	
    private void onJniNoticeB(int id, boolean isHigh){
	
	}
	
    private void onJniNoticeC(String serial){
	
	}
	
	// 调用 Jni 接口
    public native int getInput(int id);
    public native int setOutput(int id, boolean isHigh);
    public native String getSerial();
}

JNI 被调用

#include <memory>
#include <fcntl.h>
#include <string.h> 
#include <mutex>
#include "jni.h"

#include<android/log.h>
#define LOG_TAG "JNI-API"
#define ALOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##args)
#define ALOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)
#define ALOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args)

JavaVM *jvm = nullptr;
jobject jobj = nullptr;
std::mutex	mMutexMethod;

static jmethodID reqCall(JNIEnv **env, const char *name, const char *args)
{
	JNIEnv *jniEnv = nullptr;
	jclass javaClass = nullptr;
	jmethodID javaCallback = nullptr;
	
	mMutexMethod.lock();
	
	if(jvm->AttachCurrentThread(&jniEnv, nullptr) != JNI_OK || nullptr == jniEnv) {
		ALOGE("Couldn't attach thread");
		mMutexMethod.unlock();
		return nullptr;
	}
	
	javaClass = jniEnv->GetObjectClass(jobj);
	if(nullptr == javaClass){
		ALOGE("GetObjectClass failed...\n");
		jvm->DetachCurrentThread();
		mMutexMethod.unlock();
		return nullptr;
	}

	javaCallback = jniEnv->GetMethodID(javaClass, name, args);
	if(nullptr == javaCallback){
		ALOGE("find onJniSwitchInputNotice failed...\n");
		jvm->DetachCurrentThread();
		mMutexMethod.unlock();
		return nullptr;
	}
	*env = jniEnv;
	
	return javaCallback;
}

static void resCall()
{
	jvm->DetachCurrentThread();
	mMutexMethod.unlock();
}

static jint init(JNIEnv *env, jobject object)
{
	env->GetJavaVM(&jvm);
	jobj = env->NewGlobalRef(object);
	return 0;
}

static jint getInput(JNIEnv *env, jobject object, jint id)
{
	return 0;
}

static jint setOutput(JNIEnv *env, jobject object, jint id, jboolean isHigh)
{
	return 0;
}

static jstring getSerial(JNIEnv *env, jobject object)
{
	char serial[32] = {"123456789"};
	return env->NewStringUTF(serial);
}

// 构建映射表
static JNINativeMethod methods[] ={
	{"init", "()I", (void *)init},
	{"getInput", "(I)I", (void *)getInput},
	{"setOutput", "(IZ)I", (void *)setOutput},
	{"getSerial", "()Ljava/lang/String;", (void *)getSerial},
};

/*入口函数,当apk 加载jni库时被执行。*/
jint JNI_OnLoad(JavaVM * vm, void * reserved)
{
	JNIEnv *env = NULL;
	jclass myclz = NULL;
	reserved = reserved;

	// 判断 JNI 版本
	if(vm->GetEnv((void * * )&env,  JNI_VERSION_1_4)){
		ALOGE("version error, not 1.4......\n");
		return -1;
	}
	
	// 寻找指定APK类路径
	if((myclz = env->FindClass("com/jni/api/ApiNative")) == NULL){
		ALOGE("find class \"com/jni/api/ApiNative\" failed......\n");
		return -1;
	}
	
	// 注册Java方法和C/C++函数之间的映射表
	if(env->RegisterNatives(myclz, methods, sizeof(methods)/sizeof(methods[0])) < 0){
		ALOGE("register natives failed......\n");
		return -1;
	}
	
	return JNI_VERSION_1_4;
}

Jni 回调

void onJniCallNoticeA(int i0[], float f1[], float f2[], unsigned int count)
{
	JNIEnv *env = nullptr;
	jmethodID javaCallback = nullptr;
	//  对应 Java --> private void onJniNoticeA(float[] f1, float[] f2)
	if((javaCallback = reqCall(&env, "onJniNoticeA", "([F[F)V"))){
		jfloatArray jf1 = env->NewFloatArray(chcnt);
		env->SetFloatArrayRegion(jf1, 0, count, f1);
		jfloatArray jf2 = env->NewFloatArray(chcnt);
		env->SetFloatArrayRegion(jf2, 0, count, f2);
		env->CallVoidMethod(jobj, javaCallback, jf1, jf2);
		resCall();
	}
	return ;
}

void onJniCallNoticeB(int id, bool isHigh)
{
	JNIEnv *env;
	jmethodID javaCallback;
	// 对应 Java --> private void onJniNoticeB(int id, boolean isHigh)
	if((javaCallback = reqCall(&env, "onJniNoticeB", "(IZ)V"))){
		env->CallVoidMethod(jobj, javaCallback, id, isHigh);
		resCall();
	}
	return ;
}

void onJniCallNoticeC(const char *serial)
{
	JNIEnv *env = nullptr;
	char _serial[32] = {0};
	jmethodID javaCallback = nullptr;
	// 对应 Java --> private void onJniNoticeC(String serial)
    snprintf(_serial, sizeof(_serial), "%s", serial);
	if((javaCallback = reqCall(&env, "onJniNoticeC", "(Ljava/lang/String;)V"))){
		env->CallVoidMethod(jobj, javaCallback, env->NewStringUTF(_serial));
		resCall();
	}
	return ;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值