簡(jiǎn)介:
涉及到一些算法或者底層驅(qū)動(dòng)的時(shí)候,,往往需要使用jni來開發(fā)?,F(xiàn)在官方推薦使用CMake工具來開發(fā)jni。
使用CMake開發(fā)Jni其實(shí)挺簡(jiǎn)單的,,要求不高的話只需要簡(jiǎn)單配置一下就可以使用了,。
配置環(huán)境
使用CMake進(jìn)行Jni開發(fā)需要使用CMake插件、LLDB插件,、NDK插件,,這些都可以通過Android Studio很快地安裝,。
打開SDK Manager,找到Android SDK->SDK Tool選項(xiàng),,安裝CMake,、LLDB、NDK插件,。
創(chuàng)建支持C++代碼的工程
勾選Include C++ support選項(xiàng),,勾選后Android Studio可以更好地支持及幫助我們檢查jni代碼,之后一路next即可,。
創(chuàng)建完成后會(huì)發(fā)現(xiàn)Android Studio會(huì)自動(dòng)為我們生成一個(gè)Jni調(diào)用示例,。我們把工各切換至project視圖,來看一看目錄結(jié)構(gòu),。
看目錄可以知道,,相比普通工程,AndroidStudio主動(dòng)為我們生成了一個(gè)cpp的目錄,,該目錄主要存放調(diào)用的c++頭文件,,源代碼及jni代碼,還有一個(gè)CMakeLists.txt的文件,,cpp目錄下面包含一個(gè)native-lib.cpp文件(稍后會(huì)講解),,這里需要關(guān)注的主要文件有3個(gè),native-llib.cpp,、MainActivity和CMakeList.txt,。下面重點(diǎn)講解一下這幾個(gè)文件的作用。
native-lib.cpp文件
該文件是之前勾選支持c++后Android Studio主動(dòng)為我們生成的一個(gè)示例調(diào)用文件,,里面包含了jni代碼,。
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring
JNICALL
Java_mhwang_com_jnidemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
MainActivity.java文件
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
這里的代碼主要注意2點(diǎn),一是
static {
System.loadLibrary("native-lib");
}
這里主要加載native-lib庫,,這里加載庫的名稱需要跟CMakeLists.txt里面配置的一樣,。
二是public native String stringFromJNI(), 方法,,主要提供java本地jni接口,,java層代碼就是調(diào)用這個(gè)接口來通過jni調(diào)用C++函數(shù)的。
CMakeLists.txt文件
這個(gè)文件的作用是通過配置將C++代碼編譯到共享對(duì)象庫中,,具體功能項(xiàng)直接通過注釋來說明吧,。
# For more information about using CMake with Android Studio, read the
# documentation: https://d./studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
# 設(shè)置CMake構(gòu)造本地庫所需要的最低版本
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.
# 創(chuàng)建并命名庫,可以將庫的類型設(shè)置為靜態(tài)
# 或共享,,并提供該庫源代碼的相對(duì)路徑,。
# 你可以定義多個(gè)library庫,并使用CMake來構(gòu)建,。
# Gradle會(huì)自動(dòng)打包庫集成到apk中,。
add_library( # Sets the name of the library.
#庫的名稱
native-lib
#庫的分享類型
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# 庫所在位置的相對(duì)路徑
src/main/cpp/native-lib.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提供了一套實(shí)用的原生API和庫,,可以使用find_library搜索NDK中存在的庫,只需要加入所需要使用庫的名稱即可,,如下面的日志庫log-lib,。
# 更多的庫可參考https://developer./ndk/guides/stable_apis
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.
# 指定CMake連接到目標(biāo)庫中,可以鏈接多個(gè)庫,,如上面的native-lib庫以及NDK中自帶的log-lib庫
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
#
${log-lib} )
截至目前為止,,我們什么也沒有添加,但是這已經(jīng)是一個(gè)完整的jni開發(fā)的Android 應(yīng)用了,,我們來運(yùn)行看一下效果,。
可以看到,app已經(jīng)能調(diào)用jni代碼中的Hello from C++了,。
雖然看著簡(jiǎn)單,,但是在編譯運(yùn)行時(shí),Android Studio為我們做了大量的工作,。
1,、首先Gradle調(diào)用了工程中的CMakeLists.txt文件
2、CMake按照期里面的命令將C++源文件native-lib.cpp編譯到共享對(duì)象庫中,,并命名為libnative-lib.so,之后由Gradle將其打包到APK中,。
3,、運(yùn)行時(shí),由于System.loadLibrary()是靜態(tài)方法,,會(huì)在應(yīng)用MainActivity中的onCreate()調(diào)用之前加載原生庫,。實(shí)際運(yùn)行結(jié)果也是先執(zhí)行l(wèi)oadLibrary()
4、之后再由onCreate()中調(diào)用stringFromJNI(),,并將返回的“Hello from C++”更新視圖,。
更多詳細(xì)的說明可以參考官方文檔
|