Android JNI使用

Android JNI使用相关记录
Views: 546
1 0
Read Time:2 Minute, 21 Second

经常做Android开发的朋友不可避免地会接触到一个词:JNI,其英文全称为Java-Native Interface,JNI的作用即在于通过JNI可以让我们从Java代码调用到C++代码。

一般我们在开发APP时,由于Framework层没有对应的框架实现,可能需要调用C/C++编写的代码,或者是出于安全需要将核心代码使用C/C++编写,进而通过JNI来调用。

使用JNI需要提前配置NDK,因为C++代码依赖于NDK环境。在AndroidStudio中配置NDK时首先需要通过File->Settings->System Settings->Android SDK->SDK Tools内选择NDK进行下载,并通过File->Project Structure->Android NDK location配置其路径。

AndroidStudio中配置使用JNI大致可遵循如下步骤:

1.在app/src/main目录下创建cpp目录,并添加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 的文件名,最终产物为libnative-lib.so
             native-lib
             # Sets the library as a shared library.
             #设置库的类型  一种静态文件  STATIC .a   一种动态文件  SHARED .so
             SHARED
             # Provides a relative path to your source file(s).
             # 需要编译的c/c++ 文件,以CMakeLists.txt所在目录为基准的相对目录
             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.
# 依赖的NDK第三方库--
find_library( # Sets the name of the path variable.
              dependencies-lib
              # Specifies the name of the NDK library that
              # you want CMake to locate.
              EGL, #依赖libEGL.so
              nativehelper #依赖libnativehelper.so
              log )#依赖liblog.so
 
# 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.
                       ${dependencies-lib } )

关于CMake的更多使用信息,可以参考我的这篇博客

2.在app/build.gradle中将gradle与cmake进行关联,如下所示:

android {
   defaultConfig {
	externalNativeBuild{
      cmake{
	  cflags “_D”
	  cppflags “-frtti”,”-fexceptions”
	  abiFilters ‘x86’,’x86_64’,’armabi’,’armeabi-v7a’,’arm64-v8a’
      }
   }
    .......
    externalNativeBuild {
        cmake {
	    //通过path关键字指定CMakeLists.txt路径
	    //该路径是是以build.gradle为基准的相对路径
            path "CMakeLists.txt"
        }
    }
}

3.添加关键代码,关键代码的添加分为两部分,一部分是C/C++代码,另外一部分是Java代码。

首先是Java代码,包括加载JNI库,同时声明native 函数。如下示例:

//here we will load jni library
static {
     System.loadLibrary("natiave-lib"); //该名称对应cmake中的add_library所添加的库名
}
// Native method declaration
private native boolean nUpdateTexture(HardwareBuffer buffer, int textureId);

然后我们需要编写C/C++代码:

//必须要引用jni.h头文件
#include <jni.h>

//此外有两个重要的函数JNI_OnLoad、JNI_OnUnload是需要去完成的
//当native library被加载时(如调用System.loadLibrary),JAVA VM将会调用JNI_Onload,返回JNI版本
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) {

}

//当JAVA类加载器发生GC时,该函数将会被JAVA VM进行调用。通常该函数将用于清理工作。
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* /*reserved*/) {

}

此外我们还需要了解一下JNI中的数据类型,以便将Java中的数据类型与native原生类型做匹配:

Java TypeNative TypeDescription
booleanjbooleanunsigned 8 bits
bytejbytesigned 8 bits
charjcharunsigned 16 bits
shortjshortsigned 16 bits
intjintsigned 32 bits
longjlongsigned 64 bits
floatjfloat32 bits
doublejdouble64 bits
voidvoidN/A

除了原生数据类型,JNI中也存在与Java中对应的复合类型,其对应关系如下:

Java Type Native Type
java.lang.Classjclass
java.lang.Stringjstring
arraysjarray
java.lang.Throwablejthrowable

在编写完相关代码后,在Androud Studio中你可以在Build窗口中查看编译相关的报错信息;如果你需要更准确地获取C/C++相关的诊断信息,可以在app/.cxx目录下找到更多的有效信息,如CMakeCache.txt等。

Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
FranzKafka95
FranzKafka95

极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。

Articles: 86

Leave a Reply

Your email address will not be published. Required fields are marked *

en_USEN