Android中店溢,我們經(jīng)常會(huì)用到.so文件晚胡,.so文件是一個(gè)C/C++的函數(shù)庫(kù),Android中調(diào)用.so文件都是通過(guò)jni的方式桌粉。Android系統(tǒng)中每一個(gè)CPU架構(gòu)對(duì)應(yīng)一個(gè)ABI芋膘,目前有以下幾種:armeabi鳞青,armeabi-v7a,x86为朋,mips臂拓,arm64-v8a,mips64习寸,x86_64胶惰,所以我們可以生成對(duì)應(yīng)ABI的.so文件。
接下來(lái)看如何生成我們的.so文件霞溪。
一童番、NDK環(huán)境搭建
1精钮、下載NDK
下載鏈接:https://developer.android.com/ndk/downloads/index.html
當(dāng)然沒(méi)有梯子的話可以baidu找一下。PS:建議下載r9+的版本
2剃斧、下載完后解壓,并將其根目錄配置到Android Studio中忽你,打開(kāi)Project Structure(win快捷鍵:ctrl+alt+shfit+s)幼东,如下圖:
在紅框中配置你的ndk根目錄,然后ok確認(rèn)科雳。
3根蟹、打開(kāi)項(xiàng)目根目錄的local.properties文件,如下:
可以看到ndk的目錄糟秘,說(shuō)明添加成功了简逮。
4、打開(kāi)項(xiàng)目根目錄的gradle.properties文件尿赚,添加android.useDeprecatedNdk=true
散庶,如下:
到此ndk環(huán)境搭建完畢。
二凌净、Java悲龟、C/C++代碼編寫(xiě)
1、創(chuàng)建一個(gè)JniUtil類冰寻,以實(shí)現(xiàn)jni調(diào)用
public class JniUtil {
static {
//jniutil這個(gè)參數(shù)须教,可根據(jù)需要任意修改
System.loadLibrary("jniutil");
}
//java調(diào)C/C++中的方法都需要用native聲明且方法名必須和C/C++的方法名一樣
public native String test();
}
然后Make Project:
完成后會(huì)生成對(duì)應(yīng)的class文件:
2、根據(jù)JniUtil.class生成.h文件
打開(kāi)Android Studio的Terminal斩芭,切換到項(xiàng)目的app/src/main目錄下轻腺,執(zhí)行命令:
javah -d jni -classpath 編譯后的class文件的絕對(duì)路徑
如下圖:
即可生成在app/src/main目錄下自動(dòng)創(chuàng)建一個(gè)包含.h文件的jni文件夾:
我們不需要對(duì)這個(gè).h文件做任何修改,其內(nèi)容如下:
#include <jni.h>
#ifndef _Included_com_othershe_jnitest_JniUtil
#define _Included_com_othershe_jnitest_JniUtil
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_com_othershe_jnitest_JniUtil_test
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
3划乖、編寫(xiě)jniutil.c
這里的jniutil文件名需要和JniUtil類中System.loadLibrary("jniutil");
的參數(shù)一致贬养。
jniutil.c具體的編寫(xiě)可根據(jù)自己的業(yè)務(wù)實(shí)現(xiàn),這里僅做測(cè)試:
#include "com_othershe_jnitest_JniUtil.h"
JNIEXPORT jstring JNICALL Java_com_othershe_jnitest_JniUtil_test
(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, "jni調(diào)用成功");
}
在jniutil.c中我們需要導(dǎo)入上邊的.h文件迁筛,然后實(shí)現(xiàn)具體的test方法煤蚌。
4、配置項(xiàng)目app目錄下的build.gradle文件
defaultConfig {
applicationId "com.othershe.jnitest"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
ndk {
moduleName "jniutil"
abiFilters 'armeabi', 'x86', 'armeabi-v7a'
}
}
其中ndk標(biāo)簽是新添加的细卧,moduleName 的值同樣為System.loadLibrary("jniutil");
的參數(shù)尉桩。由于配置了abiFilters,則只會(huì)得到armeabi贪庙、x86蜘犁、armeabi-v7a三種ABI對(duì)應(yīng)的.so文件。
最后還需要在生成的jni文件夾下創(chuàng)建一個(gè)空的util.c文件止邮,否則會(huì)有如下異常:
jni文件夾的結(jié)構(gòu)如下:
三这橙、生成.so文件
簡(jiǎn)單的做下調(diào)用操作奏窑,運(yùn)行項(xiàng)目看效果:
textView = (TextView) findViewById(R.id.test);
textView.setText(new JniUtil().test());
到這里就成功的實(shí)現(xiàn)了jni的調(diào)用。
說(shuō)好的.so文件呢屈扎?看下圖:
上邊運(yùn)行項(xiàng)目后就生成了對(duì)應(yīng)ABI的.so文件埃唯。
四、使用生成的.so文件
上邊的這些步驟只是幫助我們得到需要的.so文件鹰晨,供自己的項(xiàng)目或給其它項(xiàng)目使用墨叛。所以使用階段就簡(jiǎn)單多了:
首先在項(xiàng)目的app/src/main目錄創(chuàng)建一個(gè)jniLibs文件夾,將生成的.so文件連同對(duì)應(yīng)的所在的文件夾拷貝到創(chuàng)建的jniLibs中模蜡,如下圖:
之前的的jni文件夾和build.gradle文件配置就不需要了漠趁。調(diào)用方法還和上邊的一樣。
PS:關(guān)于.so文件使用應(yīng)該注意的問(wèn)題可參考這篇文章:關(guān)于Android的.so文件你所需要知道的