Android NDK-动态注册jni方法

概要

作者上一文通过Cmake的编译方式对Android开发NDK调用三方so库进行了演示,这里主要讲一下在NDK开发中,怎么样去动态的注册C++里面的native方法,主要步骤如下:

  • java中定义Native方法
  • 编写C++文件,实现jni接口方法,以及JNI_OnLoad方法
  • 编译生成so
  • java加载so库,调用native方法

1.创建加载native方法的java类

package com.example.testndk2;

public class NativeApi {
    static {
        System.loadLibrary("nativelib");
    }
    public static native String getHello();
}

2.编写C++代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <jni.h>

extern "C" {  //因为是jni默认是调用C的代码,这里由于开发语言是C++,为了兼容C,一定要用到 extern “C”

JNIEXPORT jstring JNICALL get_hello(JNIEnv *env, jclass clazz) {
    return env->NewStringUTF("hello jni");
}

static JNINativeMethod g_methods[] = {
    { "getHello", "()Ljava/lang/String;", (void*)get_hello}
};

JNIEXPORT int JNICALL JNI_OnLoad(JavaVM *vm,void *reserved) {
  JNIEnv *env;
  if (vm->GetEnv((void **) &env,JNI_VERSION_1_6) != JNI_OK) {
    return JNI_ERR;
  }
  const char* class_path = "com/example/testndk2/NativeApi";//这里对应native的java类
  jclass javaClass = env->FindClass(class_path);
  if (javaClass == NULL){
    return JNI_ERR;
  }

  int method_count = sizeof(g_methods) / sizeof(g_methods[0]);
  if (env->RegisterNatives(javaClass, g_methods, method_count) < 0) {
    return JNI_ERR;
  }

  return JNI_VERSION_1_6;
}

}

3.编译生成so库

这里采用上一篇文章的方式,分别创建Android.mk、Application.mk,这里还是贴一下相应的代码:

  • Android.mk
#Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := nativelib

LOCAL_SRC_FILES := NativeApi.cpp
NDK_APP_DST_DIR := ../../libs/$(TARGET_ARCH_ABI)
include $(BUILD_SHARED_LIBRARY)
  • Application.mk
#Application.mk
APP_STL:=c++_shared
APP_PLATFORM := android-16
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI := all

4.加载so库,并调用方法

在模块级的build.gradle文件中配置lib库目录

sourceSets{
        main{
            jniLibs.srcDirs = ['libs']
        }
    }

在MainActivity里面调用native方法,拿到数据,显示到TextView上

package com.example.testndk2;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = findViewById(R.id.tv);
        tv.setText(NativeApi.getHello());
    }
}

注意

  • 如果是用C++代码编写so库,一定要记得加extern 'C'
  • C++代码中,env->FindClass(class_path)方法,class_path一定要和java类的包名和类名对应上

这里附上源码:https://github.com/cyy854325486/TestNDK

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容