深入浅析jni中的java接口使用
作者:程序员老张 发布时间:2023-07-22 19:54:23
标签:jni,java,接口,使用
JNI中的java接口使用
项目需求,需要在c++函数中监听相应的状态,并在java端进行一些列的处理。
这个需要在JNI中写一个subscriber,注册后在需要的地方进行引入使用。
目录结构
初始化是AS上的c++工程文件,这边先暂时实现简单的demo,CdemoActivity是NativeActivity的实现,我们暂时别管,因为实现是c++层控制的,有兴趣可以去百度下
主要涉及jnicallback等c文件和JNIUtil这java文件
JNIUtil
public class JNIUtil {
static {
System.loadLibrary("native-event");
}
// 注册函数
public static native void setJniCallBack(JniCallBack callBack);
// 解注册函数
public static native void unJniCallBack();
public interface JniCallBack{
void onReceiveCInfo();
}
}
jnicallback.h
//
// Created by 86130 on 2020/9/9.
//
#ifndef CDEMO_JNICALLBACK_H
#define CDEMO_JNICALLBACK_H
#ifdef __cplusplus
extern "C"{
#endif
//方法回调
void onReceiveMsg();
#ifdef __cplusplus
}
#endif
#endif //CDEMO_JNICALLBACK_H
jnicallback.cpp
#include <jni.h>
#include <malloc.h>
#include <cstring>
#include "jnicallback.h"
#ifdef __cplusplus
extern "C"{
#endif
JavaVM *g_VM;
jobject subscriber;
extern "C"
JNIEXPORT void JNICALL Java_com_demo_cdemo_JNIUtil_setJniCallBack(JNIEnv* env,jclass clazz, jobject call_back) {
env->GetJavaVM(&g_VM);
subscriber = env->NewGlobalRef(call_back);
}
extern "C"
JNIEXPORT void JNICALL Java_com_demo_cdemo_JNIUtil_unJniCallBack(JNIEnv* env, jclass clazz) {
if (subscriber != NULL)
{
env->DeleteGlobalRef(subscriber);
}
}
JNIEnv *getEnv()
{
JNIEnv *env;
if (g_VM ==NULL)
{
return NULL;
}
int envStat = g_VM->GetEnv((void **) &env, JNI_VERSION_1_6);
if (envStat == JNI_EDETACHED)
{
if (g_VM->AttachCurrentThread(&env, NULL) != 0)
{
return NULL;
}
}
return env;
}
jmethodID getMethodIdByNameAndSig(JNIEnv *env, const char *name, const char *sig)
{
if (env == NULL || subscriber == NULL)
{
return NULL;
}
jclass subscriberClass = env->GetObjectClass(subscriber);
if (subscriber == 0)
{
return NULL;
}
jmethodID methodId = env->GetMethodID(subscriberClass, name, sig);
if (methodId == 0)
{
return NULL;
}
return methodId;
}
// 头文件方法实现
void onReceiveMsg()
{
JNIEnv *env = getEnv();
jmethodID onReceiveMethodId = getMethodIdByNameAndSig(env, "onReceiveCInfo", "()V");
if (onReceiveMethodId == NULL)
{
return;
}
env->CallVoidMethod(subscriber, onReceiveMethodId);
}
#ifdef __cplusplus
}
#endif
在其他的cpp文件中引入jnicallback的头文件就可以使用相应的方法。
CMake文件
project(Native-Activity)
cmake_minimum_required(VERSION 3.4.1)
#引入native_app_glue头文件
include_directories(F:/AndroidSdk/Sdk/ndk-bundle/sources/android/native_app_glue)
add_library(native-activity SHARED
main.cpp
jnicallback.cpp)
add_library(native-event SHARED jnicallback.cpp)
find_library(log-lib log)
find_library(OPENGLES3_LIBRARY GLESv3 "OpenGL ES v3.0 library")
find_library(EGL_LIBRARY EGL "EGL 1.4 library")
find_library(android-lib android)
#编译为静态库
add_library(app_glue STATIC
android_native_app_glue.c)
target_link_libraries(native-event
${log-lib} #链接log库
${android-lib} #链接android库
)
target_link_libraries(native-activity
app_glue #链接静态库native_app_glue
${log-lib} #链接log库
${android-lib} #链接android库
${OPENGLES3_LIBRARY} #链接OpenGLES库
${EGL_LIBRARY} #链接EGL库
)
JNIUtil的使用
package com.demo.cdemo;
import android.app.NativeActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
public class CdemoActivity extends NativeActivity {
static {
System.loadLibrary("native-activity");
}
boolean isFirst = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
JNIUtil.setJniCallBack(new JNIUtil.JniCallBack() {
@Override
public void onReceiveCInfo() {
boolean isMain = isMainThread();
Log.d("zzkk",
"CdemoActivity onReceiveCInfo isMain = " + isMain);
if (!isFirst)
{
isFirst = true;
runOnUiThread(new Runnable() {
@Override public void run() {
Intent intent = new Intent(CdemoActivity.this
, MainActivity.class);
startActivity(intent);
}
});
}
}
});
}
private boolean isMainThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
}
可以看见onReceiveCInfo这行日志的打印
综上
来源:https://blog.csdn.net/ZKhero/article/details/108488802
0
投稿
猜你喜欢
- 题目描述Java创建线程的几种方式Java使用Thread类代表线程,所有线程对象都必须是Thread类或者其子类的实例。Java可以用以下
- 前言Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expe
- 一:本文使用范围此文不仅仅局限于spring boot,普通的spring工程,甚至是servlet工程,都是一样的,只不过配置一些 * 的
- FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化
- 有很多同学肯定想学习opencv相关的知识,但是有些情况下每建一次项目都要重新引入下各种文件是不是很苦恼,所以我也面临了这个问题,在网上看到
- maven3 安装:安装 Maven 之前要求先确定你的 JDK 已经安装配置完成。Maven是 Apache 下的一个项目,目前最新版本是
- 一个简单的HelloSpringMVC程序先在web,xml中注册一个前端控制器(DispatcherServlet) <?xml v
- 一、整体设计1、需求分析池化技术是计算机中的一种设计模式,内存池是常见的池化技术之一,它能够有效的提高内存的申请和释放效率以及内存碎片等问题
- 字节流和字符流对于文件必然有读和写的操作,读和写就对应了输入和输出流,流又分成字节和字符流。1.从对文件的操作来讲,有读和写的操作——也就是
- 需要注意的一点是,feign好像是无法传递list集合类型的,但是你可以通过传递对象类型,然后在接收方再次将对象装在集合中达到集合传递的效果
- 什么是队列结构一种线性结构,具有特殊的运算法则【只能在一端(队头)删除,在另一端(队尾)插入】。分类:顺序队列结构链式队列结构基本操作:入队
- 路径分隔符:Windows下是“\”unix|linux下是“/”考虑到程序的可移植性,创建文件时建议大家选用"/",因
- 介绍Java命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而使不同的请求可以进行参数化,并支持请
- 概述java移位符主要包括3种:运算符名称>>左移运算符<<有符号右移运算符<<<无符号右移运算符
- What内含一个或多个maven模块的SpringBoot项目称为SpringBoot多模块项目Why便于维护 将一个大的单体项目分成多个子
- 一、实战-内存溢出堆内存溢出栈内存溢出方法区溢出直接内存溢出二、实战-堆内存溢出演示堆内存溢出代码,并且定位问题总结堆内存溢出的场景与解决方
- 首先对于一个SpringBoot工程来说,最明显的标志的就是 @SpringBootApplication它标记了这是一个SpringBoo
- static 表示静态,它可以修饰属性,方法和代码块。1.static修饰属性(类变量),那么这个属性就可以用类名.属性名来访问,也就是使这
- Interface Segregation Principle,ISP接口隔离原则主张使用多个专门的接口比使用单一的总接口要好。一个类对另外
- 一、实验目的1. 掌握输入输出流的总体结构;2. 掌握流的概念;3. 掌握FileInputStream类、FileOutputStream