.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的生成过程以及使用有了一个初步的认识呢?