# 动态注册JNI的方法(4)

动态注册JNI的方法

之前提供了一篇使用 java -jni来自动生成.h的文件,这种叫做静态注册的方法,现在提供一种动态注册的方法实现调用

前期的准备工作也是基本上一样的

不会的可以查看这里

JNI开发实现helloworld,调用自己的C代码实现

提供了静态注册的一些准备工作

如下是基本的准备工作

在build.gradle里

ndk{
   moduleName "JNI_DYNAMIC_ANDROID_TEST" //生成的so名字
   abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定的三种abi体系下的so库
}

在gradle.properties 里

  android.useDeprecatedNdk=true

基本的准备工作做完了,写一个工具类

  package com.cxria.ndkapplication;
  
  /**
   * Created by yukun on 17-9-21.
   */
  
  public class JNIDynamicUtils {
      /**
       * 调用C++代码的方法,计算两数相加的结果返回对应的字符串
       * @return
       */
      public static native String getSumFromJNI(int i1, int i2);
  
      /**
       * 加载so库或jni库
       */
      static {
          System.loadLibrary("JNI_DYNAMIC_ANDROID_TEST");
      }
  }

这里是工具类的代码

在项目里新建jni包,不知道在那个目录下建立的请看

JNI开发实现helloworld,调用自己的C代码实现

这一次新建的不是 .c后缀的文件了 ,是.cpp,因为是C++实现的动态注册

如下所示

 #include <stdio.h>
 #include <jni.h>
 #include <stdlib.h>
 
 jstring calcSum(JNIEnv *env, jclass clazz, jint i1, jint i2) {
     char result[50];
     sprintf(result, " this is string from jni. result is %d", (i1 + i2));
 //    jstring jstr=(*env)->NewStringUTF(env,result);
 //    return jstr;
     return env->NewStringUTF(result);
 }
 
 /**
  * JNINativeMethod由三部分组成:
  * (1)Java中的函数名;
  * (2)函数签名,格式为(输入参数类型)返回值类型;
  *  ()Ljava/lang/String; (II)表示需要传两个int型参数,Ljava/lang/String;表示返回String,在对象类名(包括包名,‘/’间隔)前面加L,分号结尾
  * (3)native函数名
  */
 static JNINativeMethod gMethods[] = { {"getSumFromJNI", "(II)Ljava/lang/String;", (void *)calcSum }};
 
 //System.loadLibrary过程中会自动调用JNI_OnLoad,在此进行动态注册
 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
     JNIEnv *env = NULL;
     jint result = JNI_FALSE;
 
     //获取env指针
     if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
         return result;
     }
     if (env == NULL) {
         return result;
     }
     //获取类引用
     jclass clazz = env->FindClass("com/cxria/ndkapplication/JNIDynamicUtils");
     if (clazz == NULL) {
         return result;
     }
     //注册方法
     if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
         return result;
     }
     //成功
     result = JNI_VERSION_1_6;
     return result;
 }

这里就是C++的代码实现,里面写了动态注册的一些参数和说明.可以作为参照

所谓的静态注册,可以让提前写了的C++代码来直接使用,在使用方法,命名上也显得更加的灵活.

最后调用以上方法实现

 package com.cxria.loadso;
 import android.support.v7.app.AppCompatActivity;
 import android.os.Bundle;
 import android.widget.TextView;
 
 import com.cxria.ndkapplication.JNIDynamicUtils;
 
 public class MainActivity extends AppCompatActivity {
 
     private TextView mTextView;
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
             mTextView = (TextView) findViewById(R.id.textview);
             mTextView.setText(JNIDynamicUtils.getSumFromJNI(10,10));

         }
 }

结果显示为 ‘this is the add string from jni. result is 20’

    原文作者:不识水的鱼
    原文地址: https://www.jianshu.com/p/833322db626d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞