在现有Android Studio项目添加JNI开发
前提 需要配置NDK
1. 在app/src/main 下创建cpp 目录 这边目录主要放一些C/C++源码
2. 在app目录创建 app/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 的最小版本 一般系统自动生成
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.
# 设置生成.so 的文件名
my_lib
# Sets the library as a shared library.
#设置库的类型 一种静态文件 STATIC .a 一种动态文件 SHARED .so
SHARED
# Provides a relative path to your source file(s).
# 需要编译的c/c++ 文件
src/main/cpp/main.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.
# 指定链接的目标库
my_lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
3. 在 app/build.gradle 中指定cmake 编译文件路径
android {
.......
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
4. 在cpp 中创建c/c++ 源文件
在Java代码中添加 nation 方法
static {
System.loadLibrary("my_lib"); // 加载。名字和。CMakeLists.txt 的名字一样
}
public native String getStringToC();
#include "jni.h" // jni 开发必须的 头文件
extern "C" JNIEXPORT // 不加好像会报错
jstring // nation 方法的返回值
// c/c++ nation 方法命名规则。 Java_包名_nation方法所在的类名_nation的方法名
// 后面那两个参数是必须要有的。 *env。 是java 和 c/c++ 互调常用的方法 thiz。 是nation 方法所在类的对象
Java_com_example_abc_jnidemo_MainActivity_getStringToC
(JNIEnv *env, jobject thiz) {
char * str = "from c++";
return env->NewStringUTF(str);
}
简单的实现了。java 调c/c++的代码
传int 类型的实现方法
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_abc_jnidemo_MainActivity_getIntToC
(JNIEnv *env, jobject thiz, jint a, jint b) {
// TODO
return a + b;
}
传数组类型的实现方法
extern "C"
JNIEXPORT jintArray JNICALL
Java_com_example_abc_jnidemo_MainActivity_sort(JNIEnv *env, jobject thiz, jintArray array_) {
// TODO
int size = env->GetArrayLength(array_); // 获取数组的长度adb
int *array = env->GetIntArrayElements(array_, NULL); // 获取数组第一个元素的地址
int flay = 0;
int i ;
for (i = 0; i < size; ++i) {
if (*(array + i) > *(array + i + 1)) {
flay = *(array + i);
*(array + i) = *(array + i + 1);
*(array + i + 1) = flay;
}
LOGE("---%d", *(array + i));
}
env->ReleaseIntArrayElements(array_, array, 0);
return array_;
}
5. c/c++ 查错
我在这先写一个错误
运行报错
但是logcat 的我们看不懂 如图
我们先在Android Studio Terminal 先运行 adb logcat ->log.txt.
先把日志保存到log.txt文件中
然后再 运行
// 这个命令需要先配置环境变量。 命令的路径在 Android Studio NDK路径里自行查找
// 该命令中间那个目录是 根据自己手机的类型来选择 有x86 arm 。。。等 很多自己尝试
// 最后一个参数就是上面保存的日志文件
ndk-stack -sym app/build/intermediates/cmake/debug/obj/x86 -dump ./log.txt
运行成功会变成
就可以看到错误在哪里一行了
上面的实例代码