.so的創建和調用有一個特點,我們要知道.so的調用並不一定必須在Activity中進行,那麼製作時也並不一定要在Activity中,但是,一旦.so製作成功,那麼再調用時,調用的java類就必須跟製作.so時的java類(包括路徑和類名)必須一致!
舉個例子:拿上篇文章來說,我在創建.so時是在MainActivity中調用的,路徑名是com.byl.jnitest,那麼最終生成的.so想要在其他項目中使用,調用其的類就必須是com.byl.jnitest.MainActivity,不能是其它任何類,否則報錯。這樣一來豈不是侷限性非常大,而且特別不人性化?是的,但是我前面說過,.so的調用並不一定必須在Activity中進行,製作時也並不一定要在Activity中,所以我們可以另外創建一個util類來調用.so,並最終將該類封裝爲一個jar和.so配套使用,由此我們也可以窺探出其他第三方sdk總是x個jar和x個so配對使用的原因!
好了,接下來我們重新建立一個AS項目jnitest2,隨後創建一個專門調用so的java類JniUtil:
JniUtil.java:
package com.byl.jnitest2;
/**
* Created by baiyuliang on 2016-4-5.
*/
public class JniUtil {
public static native String getSec();//.so中的方法名
static{
System.loadLibrary("jnitest2");//加載.so
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("jj", JniUtil.getSec());
}
}
jni文件夾下的.h和.c文件:
注意.h的命名要和調用so的類名一致!
com_byl_jnitest2_JniUtil.h:(注意路徑名)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_byl_jnitest2_JniUtil */
#ifndef _Included_com_byl_jnitest2_JniUtil
#define _Included_com_byl_jnitest2_JniUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_byl_jnitest2_JniUtil
* Method: getSec
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_byl_jnitest2_JniUtil_getSec
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
jnitest.c:
#include <string.h>
#include <jni.h>
jstring
Java_com_byl_jnitest2_JniUtil_getSec
(JNIEnv* env,jobject thiz){
return (*env)->NewStringUTF(env,"調用jni成功");
}
其它步驟不在書寫,按照上篇文章的步驟,最終生成我們所要的so文件libjnitest2.so:
運行結果:
成功,好了,接下來我們看如何將這個so應用到其它項目中:
首先我們要將JniUtil這個類打包成一個jar>>jniutil.jar:
接着我們再次創建一個新的AS項目jnitest3來測試生成的so和封裝的jar,並將so和jar依次添加進項目中:
在MainActivity中調用so方法:
運行結果:
這樣封裝過後,對於so的調用就變得異常簡單,那麼對於一些項目中使用的密文則可以直接使用這種方法處理了!
經過這幾篇文章,你是否對jni、so的生成過程以及使用有了一個初步的認識呢?