Java层入口
对要在C层实现的方法加native修饰符
public class NDKTools { static { System.loadLibrary("ndktest-jni"); } public static native String getStringFromNDK(); }
Activity中使用该方法,该方法会从Native层返回一个字符串显示在屏幕上。我这里用了MVP设计模式,无视他就可以了。
public class NDKActivity extends BaseMvpActivity { TextView ndkTv; @Override public void initView() { ndkTv = findViewById(R.id.ndk_tv); } @Override public void initData() { ndkTv.setText(NDKTools.getStringFromNDK()); } @Override public int getLayoutId() { return R.layout.activity_ndk; } @Override public void showLoading() { } @Override public void hideLoading() { } @Override public void refreshView() { } @Override public void onError(String errMessage) { } }
自动生成.h文件
编译java文件,生成.class文件
javac NDKTools.java
生成的字节码文件
输入javah -jni com.billshen.offerlearn.util.NDKTools,根据class生成h头文件。注意这里要cd到java根目录。
会在java根目录下生成一个h头文件
在main目录下新建一个jni目录,同时新建一个c文件和一个Android.mk,并把刚才那个h文件拷过来。当然h文件你自己写也是可以的,这样自动生成快一点,而且规范。
ndk_test.c文件实现h文件中的方法,需要导入刚才的头文件。
#include "com_billshen_offerlearn_util_NDKTools.h" JNIEXPORT jstring JNICALL Java_com_billshen_offerlearn_util_NDKTools_getStringFromNDK (JNIEnv *env, jobject obj){ return (*env)->NewStringUTF(env,"Hello World,这是夜空中最亮的盖子第一行代码"); }
Android.mk类似于CMakeLists.txt,用于指明编译方式,源文件名称,模块名称等信息
# Android的路径
LOCAL_PATH := $(call my-dir)
# 清理变量
include $(CLEAR_VARS)
# 模块名称
LOCAL_MODULE := ndktest-jni
# 源文件,不需要指明头文件,他会自己去找的
LOCAL_SRC_FILES := ndk_test.c
# 编译方式,静态编译还是动态编译
include $(BUILD_SHARED_LIBRARY)
最后在Gradle文件中指明需要编译的Android.mk
android { compileSdkVersion 29 buildToolsVersion "30.0.0" defaultConfig { applicationId "com.billshen.offerlearn" minSdkVersion 15 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(‘proguard-android-optimize.txt‘), ‘proguard-rules.pro‘ } externalNativeBuild { ndkBuild { path ‘src/main/jni/Android.mk‘ } } } }
运行结果