Android NDK、JNI之--(四)so打包發佈aar
一、前言
突然好久發現沒寫JNI相關的代碼了,也不清除現在的一個流程了,所以今天特地重新嘗試了下so文件的開發以及打包發佈aar等流程。
二、 真香的Android Studio
現在AS已經發展到了3.6.3的版本了,我們可以直接新建一個使用JNI的Native C++示例工程,如下圖最後一個Native C++的工程模板,一路Next,Finish下去即可創建好該工程了。
新建的工程跟之前的區別不是很大,在main下多了一個 cpp 的文件夾,專門用來存放 .cpp代碼 以及 CMakeLists.txt文件 。
直接運行就能看到效果了,但是由於我們要打aar的包,所以我們新建module來做。
三、新建hello Module
直接新建Android Library Module,新建完後我們仿照工程中app module的示例代碼來完善。
3.1、新建cpp文件夾
在hello module的main文件夾下創建cpp文件夾,這個文件夾中需要包含CMakeLists.txt和.cpp的源碼文件,然後我們來完善這個文件夾。
3.1.1、新建CMakeLists.txt文件
我們仿照app module中編寫CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
#注意這裏的library name,下文在java(kotlin)類中需要用到
hello-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
hello.cpp) #注意是路徑,而不是包,不可用.區分,需要使用/
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.
hello-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
可以看到我們在該文件中配置了生成的library名稱爲:hello-lib,而使用的代碼文件是hello.cpp文件。
3.1.2、新建hello.cpp文件
好了接下來新建.cpp文件,裏面是一個示例的hi()方法【爲啥要加這個方法進去?因爲我在新的module中創建java或者kotlin類後,在類中新建本地方法,結果發現快捷鍵無法直接生成對應的c++方法。但是隻要這個cpp文件有任意一個方法後,在本地方法上使用快捷鍵就可以直接生成了】:
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT void JNICALL
Java_xxx_hi(JNIEnv *env, jobject thiz) {
// TODO: implement hi()
}
3.2、配置build.gradle
打開hello Module下的build.gradle文件,我們仿照app中的進行修改,其實就兩處:
- android 節點下添加externalNativeBuild 配置path及version等信息
- android defaultConfig 節點下添加externalNativeBuild 配置cppFlags等信息
修改完畢後重新構建下項目:
android {
......
defaultConfig{
......
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt" //這裏就是上文我們在module中編寫的hello CMakeLists.txt文件
version "3.10.2"
}
}
}
3.3、新建本地方法
在hello Module中java文件夾下的包中新建showHello類(kotlin示例)如下:
class ShowHello {
companion object {
init {
System.loadLibrary("hello-lib")
}
}
external fun getHello(): String
}
伴生對象init{}代碼塊中的就是我們需要加載的library名稱,需要和你在CMakeLists.txt中定義Library 名稱的一致。
然後我們寫本地方法getHello(),此時在getHello()方法上使用快捷鍵 Alt+Enter ,彈出如下所示:
回車後即可在上文的hello.cpp文件中看到生成的代碼了,但是如果在上文.cpp文件中沒有配置默認方法的話,這一步就廢了無法幫助我們自動生成:
然後記得將生成的代碼中的TODO完善,下文中我們就讓其返回了一個默認的字符串:
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT void JNICALL
Java_xxx_hi(JNIEnv *env, jobject thiz) {
// TODO: implement hi()
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_cooloongwu_hello_ShowHello_getHello(JNIEnv *env, jobject thiz) {
// TODO: implement getHello()
return env->NewStringUTF("This is a String from hello module, hello.cpp");
}
3.4、測試本地方法
讓app module直接依賴hello module,然後在MainActivity中直接打印該方法即可,例如最簡單的:
Log.e("本地方法測試", ShowHello().getHello())
不出意外的話,可以直接在控制檯打印出來信息了,好的,快進。
四、將hello module打包aar
打包的話其實很簡單了,打開AS右側的Gradle,在hello module下點擊Tasks->other->assembleRelease,等待AS構建完即可在 hello模塊下的build/outputs/aar文件夾下看到生成的hello-release.aar文件了。
將該文件拷貝出來,我們解壓看看裏面內容如下,生成的so文件其實在jni目錄下:
五、其他工程使用aar
新建其他Android工程,然後我們直接將上文生成的 hello-release.aar包拷貝到新工程app module的libs目錄下,然後更改app module下的build.gradle文件,添加對該aar包的依賴:
dependencies {
...
implementation files('libs/hello-release.aar')
}
然後構建項目。
構建完畢後直接在MainActivity中日誌打印調用aar中的ShowHello類的getHello()方法即可測試。
六、總結
好了,整個打包及使用的過程到這裏就結束了。但是每次這樣打包下發給其他人去更新去使用的話是不是很麻煩呢,而且也沒有個版本號信息什麼的,不方便查閱。所以我們可不可以發佈這個aar包到公司構件倉庫中,然後配置依賴去使用呢,當然可以哈哈。如果對構件倉庫還不熟悉的請參考 AndroidStudio加速之–構件倉庫Artifactory 這篇文章,下文我們就將aar發佈到Artifactory中。