一、说明
笔记主要是记录一些本人在开发当中的学习和使用笔记。笔记内容包含一些本人觉得重要的知识点、本人易犯的错误等。
由于本人水平有限,其中出现的错误或者不合理的地方望各位读者多多包含,并指出其中不合理和错误的地方,以便我来修正。谢谢!
二、笔记时间
2018年10月17日
三、简述
本文主要讲述Android APP JNI的简单使用方式。
四、详情
1、简介
JNI的全称是Java Native Interface,它用来实现Java与其他语言的通信(主要是C和C++)。
本文是使用Android studio + CMake来进行JNI开发的,因此需要安装Android Studio、NDK、CMake。
2、详情
Java里调用C语言函数需要先调用“System.loadLibrary("XXX")”,其中XXX是C语言编译的库文件名;以下代码中定义native的方法在C文件中实现的同时也供Java进行调用。以通俗的话说这个native方法是Java和C语言沟通的桥梁。
Java方法名和C函数名关系:C函数名=Java_文件路径_文件名_Java方法名,文件路径用"_"隔开。这样我们就可以在Java里调用C语言中的函数,同时我们也可以通过反射的方式在C语言函数中调用Java方法调用。
//Java方法
package com.lipy.demo.uart;
public class UartJNI {
static {
System.loadLibrary("uart");
}
/**
* 串口初始化
*
* @param namePath 串口路径
* @return 串口文件描述符
*/
public static native int initUart(String namePath);
}
//C函数
PORT jint JNICALL
Java_com_lipy_demo_uart_UartJNI_initUart(JNIEnv *env, jobject obj, jstring namePath) {
return init_uart_port((*env)->GetStringUTFChars(env, namePath, 0));
}
注:
2)采用CMake编译C文件,需要我们在“CMakeLists.txt”中配置编译生成lib名和编译C文件等。如下代码所示。
# 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.
uart
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/uart.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.
uart
# Links the target library to the log library
# included in the NDK.
${log-lib} )
3)当在C中使用Java对象(例如:String等)后,一定需要释放转换资源,不然容易造成内存溢出;以下代码中就需要释放Java传入的参数jbyteArray和转换数据jbyte指针。
//C函数
JNIEXPORT jint JNICALL
Java_com_lipy_demo_uart_UartJNI_sendUartData(JNIEnv *env, jobject obj, jstring namePath, jint fd, jbyteArray datas,
jint length, jlong timeout_ms) {
unsigned char *sendBuff = NULL;
jbyte *ba = (*env)->GetByteArrayElements(env, datas, JNI_FALSE); //jbyteArray转为jbyte*
if (length > 0) {
sendBuff = (char *) malloc(length + 1); //预留"\0"
memcpy(sendBuff, ba, length);
sendBuff[length] = '\0';
}
(*env)->ReleaseByteArrayElements(env, datas, ba, 0); //释放掉资源
return uart_send_data((*env)->GetStringUTFChars(env, namePath, 0), fd, sendBuff, length, timeout_ms);
}
3、示例源码
示例源码:https://github.com/lipyhui/android_app_demo/tree/master/UART
网友评论