环境配置:
NDK、CMake
打开as后新建C++工程
进来后AS会帮我们在MainActivity中写一个小demo
我们只需要在其增删改就行了
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(dynamicFromJNI2(1.1f,2.2f)+""); //show哪个函数就调哪个
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(); //静态注册
public native int addFromJNI(int x, int y);
public native String dynamicFromJNI(); //动态注册
public native float dynamicFromJNI2(float x,float y); //动态注册 并参数
}
这里so层我是使用C语言编写的
C++的可以看这个博客:https://www.jianshu.com/p/20cfebfc1f20
因为是c语言所以我将AS生成的cpp文件改成了c文件
改为文件后我们也要修改CMakeLists.txt文件这个文件是之前版本Application.mak Android.mak的文件整合,所以我们只需要在哪里修改即可
CMakeLists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.c ) //这里修改成自己的c文件
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
native-lib.c
#include <jni.h>
jstring Java_com_example_jni_1demo_MainActivity_stringFromJNI(JNIEnv *env, jclass jcs){
return (*env)-> NewStringUTF(env,"Hello form C");
}
jint Java_com_example_jni_1demo_MainActivity_addFromJNI(JNIEnv *env,jclass jcs, jint x, jint y){
return x+y;
}
//动态注册的方法
jstring getDynamic(JNIEnv *env, jobject this){
return (*env)-> NewStringUTF(env,"Hello Dynamic Native");
}
//动态注册的方法2
jfloat getDynamic2(JNIEnv *env, jobject this,jfloat jx,jfloat jy){
return jx+jy;
}
//需要动态注册的方法组
JNINativeMethod gMethods[] ={
{"dynamicFromJNI2", "(FF)F",(void*)getDynamic2}, //传参的函数声明
{"dynamicFromJNI","()Ljava/lang/String;",(void*)getDynamic}
};
//调用RegisterNatives方法注册函数
int registerNativeMethods(JNIEnv *env) { //JNIEnv : JavaVM 在线程中的代表, 每一个线程都有一个, JNI 中可能有非常多个 JNIEnv;
jclass cls = (*env) -> FindClass(env,"com/example/jni_demo/MainActivity");
if((*env) -> RegisterNatives(env,cls,gMethods, sizeof(gMethods) / sizeof(gMethods[0])))
return -1;
if((*env) -> RegisterNatives(env,cls,gMethods, sizeof(gMethods) / sizeof(gMethods[1]))) //这里返回方法组的第二个
return -1;
return 0;
}
//动态注册时都会执行到这个方法中
jint JNI_OnLoad(JavaVM *vm, void *unused) { //JavaVM : JavaVM 是 Java虚拟机在 JNI 层的代表, JNI 全局仅仅有一个;
JNIEnv* env;
if ((*vm) -> GetEnv(vm,(void**)&env,JNI_VERSION_1_4) != JNI_OK || registerNativeMethods(env) != JNI_OK)
return JNI_ERR;
return JNI_VERSION_1_4;
}
关于方法的解释都写在代码里面了,这样好对应位置解释看起来容易懂。