在實(shí)際的Android開發(fā)中孵运,我們經(jīng)常要用到外部的動態(tài)鏈接庫.so文件,有時我們是使用別人編譯好的.so 文件,有時需要我們自己用NDK編譯出.so文件怕品,并且在另外的工程里使用。所以本文旨在編寫自己的Jni并且編譯生成特定的共享庫.so文件巾遭,然后在另外的工程里使用該共享鏈接庫肉康。
首先我們先創(chuàng)建一個Naive C++工程,具體創(chuàng)建方法見我上一篇博客灼舍。創(chuàng)建完成的目錄結(jié)構(gòu)大致如下:
?
這里為了在調(diào)用.so文件時方便區(qū)分開來吼和,我的工程名、包名以及共享庫名和庫源文件名都做了修改骑素。所以對應(yīng)的CMakeLists也做了修改:
# 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.
testso-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
testso-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.
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.
testso-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
在上篇博文里炫乓,我們知道初始創(chuàng)建的Native C++工程是在MainActivity調(diào)用Jni方法的,這里我們新建了一個接口類TestSoHelper献丑,并通過這個類調(diào)用Jni方法末捣。TestSoHelper的代碼如下:
package com.test.mytestsoproject;
public class TestSoHelper {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("testso-lib");
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public static native int intFromJNI(int a, int b);
}
對應(yīng)的Jni方法是:
extern "C"
JNIEXPORT jint JNICALL
Java_com_test_mytestsoproject_TestSoHelper_intFromJNI(JNIEnv *env, jclass instance, jint a,
jint b) {
// TODO
int returnValue = a + b;
return returnValue;
}
這個Jni的方法十分簡單,方法傳入兩個整數(shù)创橄,然后返回這兩個數(shù)的和箩做。關(guān)于Jni的編寫,學(xué)過C語言的同學(xué)應(yīng)該一看就會了妥畏,基本是跟C/C++編寫一模一樣邦邦,在此不再贅述。
下面就是對應(yīng)的native方法的調(diào)用了醉蚁,我這里在MainActivity里簡單調(diào)用了一下燃辖,由于我們是為了編譯成.so文件,給其他工程用的网棍,所以在此不寫native方法的調(diào)用也是可以的黔龟。下面是我的調(diào)用:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(TestSoHelper.intFromJNI(1,2) + "");
}
}
基本是默認(rèn)的工程,只是把要顯示的文本改成了我Jni方法返回的數(shù)據(jù)。打包運(yùn)行的結(jié)果就是在手機(jī)上輸出數(shù)字1+2的和3捌锭。
然后我們把編寫好的Jni封裝成共享庫.so俘陷。只需要點(diǎn)擊Build [圖片上傳失敗...(image-883908-1583744056196)]
Make Project即可生成.so文件。生成的.so文件可以在下面的路徑下找到:app\build\intermediates\cmake\debug\obj观谦±埽可以看到工程生成了對應(yīng)不同android CPU架構(gòu)的.so文件:
?
?這樣我們就可以在別的工程里使用該.so 文件了。
這里我是直接用上篇博客創(chuàng)建的工程(MyTestProject)來引用這個共享庫.so文件的豁状,當(dāng)然捉偏,理論上這個共享庫可以被任意android工程引用。首先泻红,我們要把剛才生成的共享庫.so文件拷貝到我們要使用它的工程的libs文件夾下夭禽,最好是把不同CPU架構(gòu)的.so文件都拷貝進(jìn)去,這樣我們的應(yīng)用就能支持各種android系統(tǒng):
?
然后谊路,在build.gradle里添加以下代碼:
?
sourceSets.main {
jniLibs.srcDirs = ['libs']
jni.srcDirs = []
}
?
這是告訴工程要引用的共享庫所在的位置讹躯。接下來把剛才生成.so文件的工程里的Jni接口類TestSoHelper拷貝到我們當(dāng)前的工程里,注意缠劝,路徑也必須與原工程相同潮梯!另外,該類里的native方法可能會顯示為紅色惨恭,無法解析秉馏,這個不用去管,程序可以正常編譯運(yùn)行脱羡。
?
?到這里我們就可以直接在當(dāng)前工程(MyTestProject)里調(diào)用共享庫里的方法了萝究,簡單的調(diào)用如下:
?
?打包執(zhí)行下,結(jié)果果然與之前一樣锉罐!
以上方法是我個人使用Android Jni 的經(jīng)驗(yàn)帆竹,應(yīng)該是比網(wǎng)上其他引用自編寫共享庫的方法簡單很多,希望能幫助大家氓鄙。如有錯誤和不足馆揉,希望大家指正!
?您的贊賞是我堅持分享的最大動力 :)
?
?
?
?