思想:
c文件或者c++文件里的实现方法被ndk或是cmake编译为动态库,java代码中加载动态库且声明方法为native就可以链接到c/c++的实现。
方法一 **** cmake方式
思路
1)build.gradle配好CMakeLists.txt的路径
2)CMakeLists里写好库名称、c源文件路径
3)按JNI规范写好c源文件
4)调用:加载库 声明native
不勾选c++ support,自己新建CMakelists.txt
1、main路径下新建cpp文件夹,新建.c文件,按jni规则写函数
2、app路径下新建CMakelists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
tryCMakeLists
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/test.c )
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 )
target_link_libraries( # Specifies the target library.
tryCMakeLists
# Links the target library to the log library
# included in the NDK.
${log-lib} )
写明库的名称、source file路径
3、app下的build.gradle加入两处externalNativeBuild
android {
compileSdkVersion 26
defaultConfig {
applicationId "grl.com.jnicmakelists"
minSdkVersion 26
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
4、以上完成了实现部分,之后java代码中可以 加载库+native声明 调用c代码。
demo项目路径AS-study/JNIcmakelists
ps:
1、新建工程时,勾选include c++ support
2、Java调用c++代码三个步骤:加载static代码块的库、声明native方法、调用JNI方法
3、由于勾选c++ support,自动生成CMakeLists.txt,将生成的native-lib.cpp,生成native-lib动态库。
4、在app的build.gradle里有两处externalNativeBuild
学习链接:
https://blog.youkuaiyun.com/quwei3930921/article/details/78820991
pps.
可以在app/src/main/cpp路径下新建自己的cpp文件或是c文件,在CMakeLists.txt中修改source file路径即可。当然要按照jni的命名规则。
demo项目路径AS-study/ndkTest
方法二 **** ndk方式
思路
1)app的build.gradle里配好ndk的moduleName
2)src/main/jni目录新建源文件(ndk应该是固定加载jni路径下的文件)
3)调用
1、SDK Manag安装NDK
2、Project Structure里配置NDK路径
3、新建java类,加载包+定义native方法
package grl.com.myjnistudy;
public class JniStudy {
static {
System.loadLibrary("StudyJNI");
}
public static native String getStr();
}
4、app的build.gradle里的defaultConfig添加(库名与上一步一致)
ndk {
moduleName "StudyJNI"
}
5、打开as的terminal,进入app/src/main/java/grl.com.myjnistudy(可以直接拖动文件夹到terminal)
用javac命令编译定义了native方法的java文件
:myjnistudy geng_rl$ javac JniStudy.java
出现JniStudy.class文件
6、terminal路径退到包外,即app/src/main/java
javah命令生成.h文件
grl_com_myjnistudy_JniStudy.h
java geng_rl$ javah -jni grl.com.myjnistudy.JniStudy
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class grl_com_myjnistudy_JniStudy */
#ifndef _Included_grl_com_myjnistudy_JniStudy
#define _Included_grl_com_myjnistudy_JniStudy
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: grl_com_myjnistudy_JniStudy
* Method: getStr
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_grl_com_myjnistudy_JniStudy_getStr
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
7、main下new->folder->jni folder新建文件夹,名为jni
Change 。。。Location勾选上
把grl_com_myjnistudy_JniStudy.h拖入jni文件夹
8、在jni文件夹新建c++源文件,文件名任意
例:study.cpp
1)include .h文件
2)实现.h文件里的方法
#include "grl_com_myjnistudy_JniStudy.h"
JNIEXPORT jstring JNICALL Java_grl_com_myjnistudy_JniStudy_getStr
(JNIEnv * env, jclass){
return (*env).NewStringUTF("hello study");
}
9、由于ndk报错在gradle.properties加入
android.deprecatedNdkCompileLease=1584204476879
(加入android.useDeprecatedNdk=true没有用)
10、编译so库成功的话
app/build/intermediates会生成ndk目录,debug/lib下有各个架构的so库
demo项目路径AS-study/MyJniStudy
方法三 **** ndk-build命令
思路
1)jni文件夹写好源文件、Android.mk、Application.mk
2)ndk-build生成so库
3)app的build.gradle将so库的路径配到sourceSets
4)调用
1、 jni文件夹,按jni命名规则写.c文件
2、 在jni文件夹写Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := StudyJNI
LOCAL_SRC_FILES := ndkdemotest.c
include $(BUILD_SHARED_LIBRARY)
3、 在src文件夹下新建Application.mk
APP_ABI := all
4、 在terminal进入jni文件夹,执行ndk-build
ruolindeMacBook-Pro:jni geng_rl$ ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in /Users/geng_rl/09-VideoChatGroup/AS-study/MyJniStudy/app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.
[arm64-v8a] Compile : StudyJNI <= ndkdemotest.c
[arm64-v8a] SharedLibrary : libStudyJNI.so
[arm64-v8a] Install : libStudyJNI.so => libs/arm64-v8a/libStudyJNI.so
[armeabi-v7a] Compile thumb : StudyJNI <= ndkdemotest.c
[armeabi-v7a] SharedLibrary : libStudyJNI.so
[armeabi-v7a] Install : libStudyJNI.so => libs/armeabi-v7a/libStudyJNI.so
[x86] Compile : StudyJNI <= ndkdemotest.c
[x86] SharedLibrary : libStudyJNI.so
[x86] Install : libStudyJNI.so => libs/x86/libStudyJNI.so
[x86_64] Compile : StudyJNI <= ndkdemotest.c
[x86_64] SharedLibrary : libStudyJNI.so
[x86_64] Install : libStudyJNI.so => libs/x86_64/libStudyJNI.so
效果在main文件夹生成libs文件夹,放着各个架构的so库
5、 App的build.gradle的android{}里加入
sourceSets{
main{
jniLibs.srcDirs=["src/main/libs"]
}
}
6、clean project,make project