首先在此之前希望你已經(jīng)掌握了基本JNI常識(shí)的運(yùn)用倍宾,比如Java代碼如何調(diào)用本地native的方法流炕,native方法如何訪問本地變量辫愉,本地方法等以及其他相關(guān)的基礎(chǔ)知識(shí)顽决。在此我還是貼上Activity的部分代碼窍仰,如下:
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
public String name = "test";
private int source[] = { 1, 4, 0, 7, 33, 11 };
@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();
public native String updateNameFromC();//屬性訪問
public native String getMethod();//方法訪問
public native void getArray(int arrays[]);
//引用解決什么問題呢汉规,什么時(shí)候通知JVM回收J(rèn)NI的對(duì)象
public native void getLocalReference();
//緩存策略,對(duì)象生命周期的問題
public native void cachede();
//測(cè)試
public native String test(String str);
同理驹吮,本地cpp的代碼如下:
#include <jni.h>
#include <string>
#include <string.h>
#include "stdlib.h"
#include <android/log.h>
//首先將a強(qiáng)制聲明為指向整數(shù)的指針针史,然后讀取指針對(duì)應(yīng)的整數(shù)
int compare(const void *a,const void *b){
return (*(int *)a-*(int *)b);
}
#define TAG "myDemo-jni" // 這個(gè)是自定義的LOG的標(biāo)識(shí)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定義LOGD類型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定義LOGI類型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定義LOGW類型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定義LOGE類型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定義LOGF類型
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_example_ee_ndkdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
運(yùn)行程序,則會(huì)發(fā)現(xiàn)在下面的目錄中生成了不同的.so庫(kù)碟狞,如下:
好的啄枕,第一步已經(jīng)完成。
其次族沃,新建一個(gè)項(xiàng)目频祝,將其不同的.so庫(kù)拷貝到項(xiàng)目的目錄下,這里有兩種方法脆淹,第一種常空,將.so庫(kù)拷貝到項(xiàng)目src->main->jniLibs下,不同的架構(gòu)放在這個(gè)目錄的不同文件夾下面即可盖溺,這是最簡(jiǎn)單的漓糙;第二種,將.so庫(kù)拷貝到項(xiàng)目app->libs中咐柜,不同的架構(gòu)放在這個(gè)目錄的不同文件夾下面即可兼蜈,但是這時(shí)候要在build.gradle中配置
rceSets{
main{
jniLibs.srcDirs = ['libs']
}
}
這時(shí)候就會(huì)涉及到如何引用.so庫(kù)里面的方法了攘残,其實(shí)調(diào)用So庫(kù)里的方法也有兩種方式:
(1)So庫(kù)有對(duì)應(yīng)的jar包,把jar包放進(jìn)libs里就可以調(diào)用so庫(kù)里面的方法了为狸,當(dāng)然得先把so放進(jìn)jniLibs里歼郭;
(2)只有So庫(kù),沒有jar包辐棒,下面詳細(xì)討論這種情況…..
沒有jar包又想調(diào)用so里的方法病曾,其實(shí)也是很簡(jiǎn)單的,前提當(dāng)然是要把so庫(kù)放進(jìn)jniLibs里漾根,然后看下面的代碼
public class MainActivity {
static {
System.loadLibrary("native-lib");
}
public String hh(){
return stringFromJNI();
}
public static native String stringFromJNI();
public static native String getMethod();
}
實(shí)際上我這是希望在另外一個(gè)項(xiàng)目中調(diào)用之前打包成so庫(kù)的本地方法
stringFromJNI()泰涂,事實(shí)上中間有一個(gè)必須要注意的細(xì)節(jié),就是調(diào)用已經(jīng)打包so庫(kù)的那個(gè)類辐怕,必須要與已經(jīng)生成的so庫(kù)的類名逼蒙,包名都要一致,否則就會(huì)出現(xiàn)問題寄疏,這是一個(gè)細(xì)節(jié)是牢。所以筆者最后發(fā)現(xiàn)只有so庫(kù)的調(diào)用實(shí)際上還是相對(duì)麻煩一下,因?yàn)槟阋{(diào)用的一些第三方的so庫(kù)陕截,比人不會(huì)告訴你他們的報(bào)名驳棱,已經(jīng)加載這個(gè)so庫(kù)所在的類名。相反例如百度推送以及七牛云等相關(guān)的so庫(kù)农曲,別人會(huì)額外再提供你一個(gè)相關(guān)的jar包社搅,我們只需要操作jar包就Ok了,所以最終我認(rèn)為對(duì)第三方so庫(kù)里面方法的調(diào)用乳规,so庫(kù)配jar包的使用比單純的so庫(kù)的使用要簡(jiǎn)潔的多形葬。