其实这个项目没有使用静态注册方法,而是使用了动态注册方法。下面我们分别来讲一下两种方式的区别。
2.1 实现原理
2.2 实现过程
编写.java代码; 编译.java代码,生成.class文件; 用过javah指令,利用生成的.class文件生成JNI的.h文件; 生成后的JNI头文件中包含了Java函数在JNI层的声明。
• 【我的Android进阶之旅】Android Studio中JNI开发如何通过Extranal Tools 快速一键生成.h头文件
https://blog.csdn.net/ouyang_peng/article/details/8715602
• 【我的Android进阶之旅】Android调用JNI出错 java.lang.UnsatisfiedLinkError: No implementation found for的解决方法
https://blog.csdn.net/ouyang_peng/article/details/52997698
• 【我的Android进阶之旅】如果通过NDK编程,使用JNI来调用已经封装完毕的无法修改的so库(第三方)
https://blog.csdn.net/ouyang_peng/article/details/112382141
• 【我的Android进阶之旅】如何通过JNI来封装已有的C源码算法,然后让Java层调用C语言写的算法
https://blog.csdn.net/ouyang_peng/article/details/109299224
2.3 弊端
书写很不方便,因为JNI层函数的名字必须遵循特定的格式,且名字特别长; 会导致程序员的工作量很大,因为必须为所有声明了native函数的java类编写JNI头文件; 程序运行效率低,因为初次调用native函数时需要根据根据函数名在JNI层中搜索对应的本地函数,然后建立对应关系,这个过程比较耗时。
public class MyNativeRender {
... 其他代码
static {
System.loadLibrary("native-render");
}
public native void native_Init();
public native void native_UnInit();
... 其他代码
}
extern "C"
JNIEXPORT void JNICALL
Java_com_byteflow_app_MyNativeRender_native_1Init(JNIEnv *env, jobject thiz) {
// TODO: implement native_Init()
}
2.4 示例
目前我项目中还是使用的这种静态注册的方法。大家可以在下面的github查看。
java 层代码
package com.oyp.openglesdemo.render
import android.app.Activity
import android.content.res.AssetManager
import android.opengl.GLSurfaceView
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
class MyNativeRenderer(activity: Activity) : GLSurfaceView.Renderer, RenderAction {
private var mActivity: Activity = activity
var mSampleType = 0
init {
System.loadLibrary("ouyangpeng-opengles-lib")
}
// 通用的
private external fun nativeSurfaceCreate(assetManager: AssetManager)
private external fun nativeSurfaceChange(width: Int, height: Int)
private external fun nativeDrawFrame()
private external fun nativeSetRenderType(sampleCategoryType: Int, renderSampleType: Int)
private external fun nativeOnDestroy()
// 特定的方法
private external fun nativeSwitchBlendingMode()
// 特定的方法
private external fun nativeSetDelta(x: Float, y: Float)
private external fun nativeSetMinFilter(filter: Int)
private external fun nativeSetMagFilter(filter: Int)
private external fun nativeSetImageData(
format: Int,
width: Int,
height: Int,
imageData: ByteArray?
)
private external fun nativeSetImageDataWithIndex(
index: Int,
format: Int,
width: Int,
height: Int,
imageData: ByteArray?
)
private external fun nativeUpdateTransformMatrix(
rotateX: Float,
rotateY: Float,
scaleX: Float,
scaleY: Float
)
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
val assetManager: AssetManager = mActivity.assets
nativeSurfaceCreate(assetManager)
}
override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
nativeSurfaceChange(width, height)
}
override fun onDrawFrame(gl: GL10) {
nativeDrawFrame()
}
fun setRenderType(sampleCategoryType: Int, renderSampleType: Int) {
if (sampleCategoryType == IMyNativeRendererType.SAMPLE_TYPE) {
mSampleType = renderSampleType
}
nativeSetRenderType(sampleCategoryType, renderSampleType)
}
fun onDestroy() {
nativeOnDestroy()
}
override fun switchBlendingMode() {
nativeSwitchBlendingMode()
}
override fun setMinFilter(filter: Int) {
nativeSetMinFilter(filter)
}
override fun setMagFilter(filter: Int) {
nativeSetMagFilter(filter)
}
override fun setDelta(deltaX: Float, deltaY: Float) {
nativeSetDelta(deltaX, deltaY)
}
override fun setImageData(
format: Int,
width: Int,
height: Int,
imageData: ByteArray
) {
nativeSetImageData(format, width, height, imageData)
}
override fun setImageDataWithIndex(
index: Int,
format: Int,
width: Int,
height: Int,
imageData: ByteArray
) {
nativeSetImageDataWithIndex(index, format, width, height, imageData)
}
override fun updateTransformMatrix(
rotateX: Float,
rotateY: Float,
scaleX: Float,
scaleY: Float
) {
nativeUpdateTransformMatrix(rotateX, rotateY, scaleX, scaleY)
}
}
对应的JNI方法
//
// Created by OuyangPeng on 2021/11/26.
//
#include <jni.h>
#include <MyGLRenderContext.h>
#include <EGLRender.h>
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSurfaceCreate(
JNIEnv *env, jobject thiz, jobject asset_manager) {
MyGLRenderContext::GetInstance()->OnSurfaceCreated(env, asset_manager);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSurfaceChange(
JNIEnv *env, jobject thiz, jint width, jint height) {
MyGLRenderContext::GetInstance()->OnSurfaceChanged(width, height);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeDrawFrame(JNIEnv *env, jobject thiz) {
MyGLRenderContext::GetInstance()->OnDrawFrame();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSetRenderType(
JNIEnv *env, jobject thiz, jint sampleCategoryType, jint renderSampleType) {
MyGLRenderContext::GetInstance()->SetRenderType(sampleCategoryType, renderSampleType);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeOnDestroy(JNIEnv *env, jobject thiz) {
MyGLRenderContext::DestroyInstance();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSwitchBlendingMode(JNIEnv *env, jobject thiz) {
MyGLRenderContext::GetInstance()->SwitchBlendingMode();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSetDelta(
JNIEnv *env, jobject thiz, jfloat x, jfloat y) {
MyGLRenderContext::GetInstance()->SetDelta(x, y);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSetMinFilter(
JNIEnv *env, jobject thiz, jint filter) {
MyGLRenderContext::GetInstance()->SetMinFilter(filter);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSetMagFilter(
JNIEnv *env, jobject thiz, jint filter) {
MyGLRenderContext::GetInstance()->SetMagFilter(filter);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSetImageData(
JNIEnv *env, jobject thiz,
jint format, jint width, jint height, jbyteArray imageData) {
int len = env->GetArrayLength(imageData);
u_int8_t *buf = new u_int8_t[len];
env->GetByteArrayRegion(imageData, 0, len, reinterpret_cast<jbyte *>(buf));
MyGLRenderContext::GetInstance()->SetImageData(format, width, height, buf);
delete[]buf;
env->DeleteLocalRef(imageData);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeSetImageDataWithIndex(
JNIEnv *env, jobject thiz,
jint index, jint format, jint width, jint height, jbyteArray imageData) {
int len = env->GetArrayLength(imageData);
u_int8_t *buf = new u_int8_t[len];
env->GetByteArrayRegion(imageData, 0, len, reinterpret_cast<jbyte *>(buf));
MyGLRenderContext::GetInstance()->SetImageDataWithIndex(index, format, width, height, buf);
delete[]buf;
env->DeleteLocalRef(imageData);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_MyNativeRenderer_nativeUpdateTransformMatrix(
JNIEnv *env, jobject thiz, jfloat rotateX,jfloat rotateY,jfloat scaleX,jfloat scaleY) {
MyGLRenderContext::GetInstance()->UpdateTransformMatrix(rotateX, rotateY, scaleX, scaleY);
}
EGL 渲染相关
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_egl_NativeEglRender_nativeEglRenderInit(JNIEnv *env, jobject thiz, jobject asset_manager) {
EGLRender::GetInstance()->Init(env,asset_manager);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_egl_NativeEglRender_nativeEglRenderSetImageData(
JNIEnv *env, jobject thiz, jbyteArray data, jint width, jint height) {
int len = env->GetArrayLength (data);
uint8_t* buf = new uint8_t[len];
env->GetByteArrayRegion(data, 0, len, reinterpret_cast<jbyte*>(buf));
EGLRender::GetInstance()->SetImageData(buf, width, height);
delete[] buf;
env->DeleteLocalRef(data);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_egl_NativeEglRender_nativeEglRenderSetFragmentShaderType(
JNIEnv *env, jobject thiz, jint param_type, jint fShaderType) {
EGLRender::GetInstance()->SetFragmentShaderType(param_type, fShaderType);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_egl_NativeEglRender_nativeEglRenderDraw(JNIEnv *env, jobject thiz) {
EGLRender::GetInstance()->Draw();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_oyp_openglesdemo_render_egl_NativeEglRender_nativeEglRenderUnInit(JNIEnv *env, jobject thiz) {
EGLRender::GetInstance()->UnInit();
}
EGL 渲染相关
应用层的Java类别通过VM而调用到native函数。一般是通过VM去寻找*.so里的native函数。
如果需要连续呼叫很多次,每次都需要寻找一遍,会多花许多时间。
注:在Android 源码开发环境下,大多采用动态注册native方法。
3.1 实现原理
3.2 实现过程
利用结构体JNINativeMethod保存Java Native函数和JNI函数的对应关系; 在一个JNINativeMethod数组中保存所有native函数和JNI函数的对应关系; 在Java中通过System.loadLibrary加载完JNI动态库之后,调用JNI_OnLoad函数,开始动态注册; JNI_OnLoad中会调用AndroidRuntime::registerNativeMethods函数进行函数注册; AndroidRuntime::registerNativeMethods中最终调用jni RegisterNativeMethods完成注册。
3.3 优点
RegisterNatives方法能帮助你把C/C++中的方法隐射到Java中的native方法,而无需遵循特定的方法命名格式。 更有效率去找到函数。 在执行期间进行抽换。
3.4 示例
/**
*
* Created by 公众号:字节流动 on 2021/3/12.
* https://github.com/githubhaohao/NDK_OpenGLES_3_0
* 最新文章首发于公众号:字节流动,有疑问或者技术交流可以添加微信 Byte-Flow ,领取视频教程, 拉你进技术交流群
*
* */
package com.byteflow.app;
public class MyNativeRender {
其他代码
static {
System.loadLibrary("native-render");
}
public native void native_Init();
public native void native_UnInit();
public native void native_SetParamsInt(int paramType, int value0, int value1);
public native void native_SetParamsFloat(int paramType, float value0, float value1);
public native void native_UpdateTransformMatrix(float rotateX, float rotateY, float scaleX, float scaleY);
public native void native_SetImageData(int format, int width, int height, byte[] bytes);
public native void native_SetImageDataWithIndex(int index, int format, int width, int height, byte[] bytes);
public native void native_SetAudioData(short[] audioData);
public native void native_OnSurfaceCreated();
public native void native_OnSurfaceChanged(int width, int height);
public native void native_OnDrawFrame();
}
2. Native层代码
代码定义在 app/src/main/cpp/JniImpl.cpp 文件中。
定义JNI NativeMethod的映射关系。
static JNINativeMethod g_RenderMethods[] = {
{"native_Init", "()V", (void *)(native_Init)},
{"native_UnInit", "()V", (void *)(native_UnInit)},
{"native_SetImageData", "(III[B)V", (void *)(native_SetImageData)},
{"native_SetImageDataWithIndex", "(IIII[B)V", (void *)(native_SetImageDataWithIndex)},
{"native_SetParamsInt", "(III)V", (void *)(native_SetParamsInt)},
{"native_SetParamsFloat", "(IFF)V", (void *)(native_SetParamsFloat)},
{"native_SetAudioData", "([S)V", (void *)(native_SetAudioData)},
{"native_UpdateTransformMatrix", "(FFFF)V", (void *)(native_UpdateTransformMatrix)},
{"native_OnSurfaceCreated", "()V", (void *)(native_OnSurfaceCreated)},
{"native_OnSurfaceChanged", "(II)V", (void *)(native_OnSurfaceChanged)},
{"native_OnDrawFrame", "()V", (void *)(native_OnDrawFrame)},
};
static JNINativeMethod g_BgRenderMethods[] = {
{"native_EglRenderInit", "()V", (void *)(native_EglRenderInit)},
{"native_EglRenderSetImageData", "([BII)V", (void *)(native_EglRenderSetImageData)},
{"native_EglRenderSetIntParams", "(II)V", (void *)(native_EglRenderSetIntParams)},
{"native_EglRenderDraw", "()V", (void *)(native_EglRenderDraw)},
{"native_EglRenderUnInit", "()V", (void *)(natuve_BgRenderUnInit)},
};
定义要关联的对应Java类。
#define NATIVE_RENDER_CLASS_NAME "com/byteflow/app/MyNativeRender"
#define NATIVE_BG_RENDER_CLASS_NAME "com/byteflow/app/egl/NativeEglRender"
然后定义RegisterNativeMethods函数和UnregisterNativeMethods函数。
static int RegisterNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodNum)
{
LOGCATE("RegisterNativeMethods");
jclass clazz = env->FindClass(className);
if (clazz == NULL)
{
LOGCATE("RegisterNativeMethods fail. clazz == NULL");
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, methods, methodNum) < 0)
{
LOGCATE("RegisterNativeMethods fail");
return JNI_FALSE;
}
return JNI_TRUE;
}
static void UnregisterNativeMethods(JNIEnv *env, const char *className)
{
LOGCATE("UnregisterNativeMethods");
jclass clazz = env->FindClass(className);
if (clazz == NULL)
{
LOGCATE("UnregisterNativeMethods fail. clazz == NULL");
return;
}
if (env != NULL)
{
env->UnregisterNatives(clazz);
}
}
JNI_OnLoad 函数和 JNI_OnUnload函数。
指定JNI版本:告诉VM该组件使用那一个JNI版本(若未提供JNI_OnLoad()函数,VM会默认该使用最老的JNI 1.1版),如果要使用新版本的JNI,例如JNI 1.6版,则必须由JNI_OnLoad()函数返回常量JNI_VERSION_1_6(该常量定义在jni.h中) 来告知VM。 初始化设定,当VM执行到System.loadLibrary()函数时,会立即先呼叫JNI_OnLoad()方法,因此在该方法中进行各种资源的初始化操作最为恰当。
extern "C" jint JNI_OnLoad(JavaVM *jvm, void *p)
{
LOGCATE("===== JNI_OnLoad =====");
jint jniRet = JNI_ERR;
JNIEnv *env = NULL;
if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK)
{
return jniRet;
}
jint regRet = RegisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME, g_RenderMethods,
sizeof(g_RenderMethods) /
sizeof(g_RenderMethods[0]));
if (regRet != JNI_TRUE)
{
return JNI_ERR;
}
regRet = RegisterNativeMethods(env, NATIVE_BG_RENDER_CLASS_NAME, g_BgRenderMethods,
sizeof(g_BgRenderMethods) /
sizeof(g_BgRenderMethods[0]));
if (regRet != JNI_TRUE)
{
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
extern "C" void JNI_OnUnload(JavaVM *jvm, void *p)
{
JNIEnv *env = NULL;
if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK)
{
return;
}
UnregisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME);
UnregisterNativeMethods(env, NATIVE_BG_RENDER_CLASS_NAME);
}
完整代码
完整代码如下所示:
//
// Created by ByteFlow on 2019/7/9.
//
#include "util/LogUtil.h"
#include <MyGLRenderContext.h>
#include <EGLRender.h>
#include "jni.h"
#define NATIVE_RENDER_CLASS_NAME "com/byteflow/app/MyNativeRender"
#define NATIVE_BG_RENDER_CLASS_NAME "com/byteflow/app/egl/NativeEglRender"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_Init
* Signature: ()V
*/
JNIEXPORT void JNICALL native_Init(JNIEnv *env, jobject instance)
{
MyGLRenderContext::GetInstance();
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_UnInit
* Signature: ()V
*/
JNIEXPORT void JNICALL native_UnInit(JNIEnv *env, jobject instance)
{
MyGLRenderContext::DestroyInstance();
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_SetImageData
* Signature: (III[B)V
*/
JNIEXPORT void JNICALL native_SetImageData
(JNIEnv *env, jobject instance, jint format, jint width, jint height, jbyteArray imageData)
{
int len = env->GetArrayLength (imageData);
uint8_t* buf = new uint8_t[len];
env->GetByteArrayRegion(imageData, 0, len, reinterpret_cast<jbyte*>(buf));
MyGLRenderContext::GetInstance()->SetImageData(format, width, height, buf);
delete[] buf;
env->DeleteLocalRef(imageData);
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_SetImageDataWithIndex
* Signature: (IIII[B)V
*/
JNIEXPORT void JNICALL native_SetImageDataWithIndex
(JNIEnv *env, jobject instance, jint index, jint format, jint width, jint height, jbyteArray imageData)
{
int len = env->GetArrayLength (imageData);
uint8_t* buf = new uint8_t[len];
env->GetByteArrayRegion(imageData, 0, len, reinterpret_cast<jbyte*>(buf));
MyGLRenderContext::GetInstance()->SetImageDataWithIndex(index, format, width, height, buf);
delete[] buf;
env->DeleteLocalRef(imageData);
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_SetParamsInt
* Signature: (III)V
*/
JNIEXPORT void JNICALL native_SetParamsInt
(JNIEnv *env, jobject instance, jint paramType, jint value0, jint value1)
{
MyGLRenderContext::GetInstance()->SetParamsInt(paramType, value0, value1);
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_SetParamsFloat
* Signature: (IFF)V
*/
JNIEXPORT void JNICALL native_SetParamsFloat
(JNIEnv *env, jobject instance, jint paramType, jfloat value0, jfloat value1)
{
MyGLRenderContext::GetInstance()->SetParamsFloat(paramType, value0, value1);
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_SetAudioData
* Signature: ([B)V
*/
JNIEXPORT void JNICALL native_SetAudioData
(JNIEnv *env, jobject instance, jshortArray data)
{
int len = env->GetArrayLength(data);
short *pShortBuf = new short[len];
env->GetShortArrayRegion(data, 0, len, reinterpret_cast<jshort*>(pShortBuf));
MyGLRenderContext::GetInstance()->SetParamsShortArr(pShortBuf, len);
delete[] pShortBuf;
env->DeleteLocalRef(data);
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_UpdateTransformMatrix
* Signature: (FFFF)V
*/
JNIEXPORT void JNICALL native_UpdateTransformMatrix(JNIEnv *env, jobject instance, jfloat rotateX, jfloat rotateY, jfloat scaleX, jfloat scaleY)
{
MyGLRenderContext::GetInstance()->UpdateTransformMatrix(rotateX, rotateY, scaleX, scaleY);
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_OnSurfaceCreated
* Signature: ()V
*/
JNIEXPORT void JNICALL native_OnSurfaceCreated(JNIEnv *env, jobject instance)
{
MyGLRenderContext::GetInstance()->OnSurfaceCreated();
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_OnSurfaceChanged
* Signature: (II)V
*/
JNIEXPORT void JNICALL native_OnSurfaceChanged
(JNIEnv *env, jobject instance, jint width, jint height)
{
MyGLRenderContext::GetInstance()->OnSurfaceChanged(width, height);
}
/*
* Class: com_byteflow_app_MyNativeRender
* Method: native_OnDrawFrame
* Signature: ()V
*/
JNIEXPORT void JNICALL native_OnDrawFrame(JNIEnv *env, jobject instance)
{
MyGLRenderContext::GetInstance()->OnDrawFrame();
}
/*
* Class: com_byteflow_app_egl_NativeBgRender
* Method: native_EglRenderInit
* Signature: ()V
*/
JNIEXPORT void JNICALL native_EglRenderInit(JNIEnv *env, jobject instance)
{
EGLRender::GetInstance()->Init();
}
/*
* Class: com_byteflow_app_egl_NativeBgRender
* Method: native_EglRenderSetImageData
* Signature: ([BII)V
*/
JNIEXPORT void JNICALL native_EglRenderSetImageData(JNIEnv *env, jobject instance, jbyteArray data, jint width, jint height)
{
int len = env->GetArrayLength (data);
uint8_t* buf = new uint8_t[len];
env->GetByteArrayRegion(data, 0, len, reinterpret_cast<jbyte*>(buf));
EGLRender::GetInstance()->SetImageData(buf, width, height);
delete[] buf;
env->DeleteLocalRef(data);
}
/*
* Class: com_byteflow_app_egl_NativeBgRender
* Method: native_EglRenderSetIntParams
* Signature: (II)V
*/
JNIEXPORT void JNICALL native_EglRenderSetIntParams(JNIEnv *env, jobject instance, jint type, jint param)
{
EGLRender::GetInstance()->SetIntParams(type, param);
}
/*
* Class: com_byteflow_app_egl_NativeBgRender
* Method: native_EglRenderDraw
* Signature: ()V
*/
JNIEXPORT void JNICALL native_EglRenderDraw(JNIEnv *env, jobject instance)
{
EGLRender::GetInstance()->Draw();
}
/*
* Class: com_byteflow_app_egl_NativeBgRender
* Method: natuve_BgRenderUnInit
* Signature: ()V
*/
JNIEXPORT void JNICALL natuve_BgRenderUnInit(JNIEnv *env, jobject instance)
{
EGLRender::GetInstance()->UnInit();
}
#ifdef __cplusplus
}
#endif
static JNINativeMethod g_RenderMethods[] = {
{"native_Init", "()V", (void *)(native_Init)},
{"native_UnInit", "()V", (void *)(native_UnInit)},
{"native_SetImageData", "(III[B)V", (void *)(native_SetImageData)},
{"native_SetImageDataWithIndex", "(IIII[B)V", (void *)(native_SetImageDataWithIndex)},
{"native_SetParamsInt", "(III)V", (void *)(native_SetParamsInt)},
{"native_SetParamsFloat", "(IFF)V", (void *)(native_SetParamsFloat)},
{"native_SetAudioData", "([S)V", (void *)(native_SetAudioData)},
{"native_UpdateTransformMatrix", "(FFFF)V", (void *)(native_UpdateTransformMatrix)},
{"native_OnSurfaceCreated", "()V", (void *)(native_OnSurfaceCreated)},
{"native_OnSurfaceChanged", "(II)V", (void *)(native_OnSurfaceChanged)},
{"native_OnDrawFrame", "()V", (void *)(native_OnDrawFrame)},
};
static JNINativeMethod g_BgRenderMethods[] = {
{"native_EglRenderInit", "()V", (void *)(native_EglRenderInit)},
{"native_EglRenderSetImageData", "([BII)V", (void *)(native_EglRenderSetImageData)},
{"native_EglRenderSetIntParams", "(II)V", (void *)(native_EglRenderSetIntParams)},
{"native_EglRenderDraw", "()V", (void *)(native_EglRenderDraw)},
{"native_EglRenderUnInit", "()V", (void *)(natuve_BgRenderUnInit)},
};
static int RegisterNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodNum)
{
LOGCATE("RegisterNativeMethods");
jclass clazz = env->FindClass(className);
if (clazz == NULL)
{
LOGCATE("RegisterNativeMethods fail. clazz == NULL");
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, methods, methodNum) < 0)
{
LOGCATE("RegisterNativeMethods fail");
return JNI_FALSE;
}
return JNI_TRUE;
}
static void UnregisterNativeMethods(JNIEnv *env, const char *className)
{
LOGCATE("UnregisterNativeMethods");
jclass clazz = env->FindClass(className);
if (clazz == NULL)
{
LOGCATE("UnregisterNativeMethods fail. clazz == NULL");
return;
}
if (env != NULL)
{
env->UnregisterNatives(clazz);
}
}
// call this func when loading lib
extern "C" jint JNI_OnLoad(JavaVM *jvm, void *p)
{
LOGCATE("===== JNI_OnLoad =====");
jint jniRet = JNI_ERR;
JNIEnv *env = NULL;
if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK)
{
return jniRet;
}
jint regRet = RegisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME, g_RenderMethods,
sizeof(g_RenderMethods) /
sizeof(g_RenderMethods[0]));
if (regRet != JNI_TRUE)
{
return JNI_ERR;
}
regRet = RegisterNativeMethods(env, NATIVE_BG_RENDER_CLASS_NAME, g_BgRenderMethods,
sizeof(g_BgRenderMethods) /
sizeof(g_BgRenderMethods[0]));
if (regRet != JNI_TRUE)
{
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
extern "C" void JNI_OnUnload(JavaVM *jvm, void *p)
{
JNIEnv *env = NULL;
if (jvm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK)
{
return;
}
UnregisterNativeMethods(env, NATIVE_RENDER_CLASS_NAME);
UnregisterNativeMethods(env, NATIVE_BG_RENDER_CLASS_NAME);
}
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!