创建一个模块(JNITest01)
略
MainActivity使用native方法
MainActivity.java:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("jni_test01"); // 启动加载的库
}
public native String GetString(); // 声明native方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
具体步骤
加载自定义jni库
static {
System.loadLibrary("jni_test01");
}
声明native方法
public native String GetString();
打开Android studio的Terminal控制面板(IDE左下方)
进入java代码目录
cd JNITest01\src\main\java
使用javah命令把MainActivity类转为.h
javah -jni com.example.jnitest01.MainActivity
执行完该命令后将生成com_example_jnitest01_MainActivity.h
注:
如果没设置jdk环境变量会提示javah不是内部命令错误
出现该错误需要设置一下环境变量,Android studio一般会把java安装在C:\ProgramFiles\Android\Android Studio\jre
在path中增加:C:\Program Files\Android\Android Studio\jre\bin
新建一个cpp文件夹
右键cpp->New->C/C++Source File
假设新建文件名为:jni_test01.cpp
把com_example_jnitest01_MainActivity.h中部分内容复制到jni_test01.cpp中#include <jni.h>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnitest01_MainActivity_GetString(JNIEnv *env, jobject jobj) {
return env->NewStringUTF("string from C++");
}
从其他工程中复制一份CMakeLists.txt到当前模块下
修改CMakeLists.txt
add_library(
jni_test01 ---------------> 改名为自己想要的
src/main/cpp/jni_test01.cpp ---------------> 改名为自己想要的
)
...
target_link_libraries(
jni_test01
...
)
修改当前模块中的build.gradle
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
-----------> 默认的到这里,以下手动添加
externalNativeBuild {
cmake {
cppFlags ""
}
}
ndk {
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
}
buildTypes {
...
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
Android studio应该会提示你同步工程
同步没出错就可以编译了编译JNITest01模块编译生成的.so
文件所在路径为:build->intermediates->cmake->debug/release/arm64-v7a/8a/x86/x86_64
增加JNI接口
只要编译通过了,后续增加接口只要在.java中声明,然后选中方法名或双击方法名,按ALT + ENTER键即可在.cpp张自动生成相应的方法
查看JAVA对应JNI类型
使用javap命令查看在.java中声明的参数在JNI(C/C++)下对应的参数
javap操作的对象是.class,因此需要进入到.java被编译后的路径,然后执行javap命令
在Androidstudio终端中执行:
cd build\intermediates\classes\debug\com\example\jnitest01
javap -s MainActivity
注:本例是使用MainActivity对native接口声明的,因此使用的是MainActivity
javap执行结果:
CMakefileLists.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.
jni_test01
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/jni_test01.cpp )
# 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.
jni_test01
# Links the target library to the log library
# included in the NDK.
${log-lib} )
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.jnitest01"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
ndk {
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
jni_test01.cpp
#include <jni.h>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_jnitest01_MainActivity_GetString(JNIEnv *env, jobject jobj)
{
return env->NewStringUTF("Native");
}