序:
1.本文是安卓插件化课程的第六篇,完整课程链接参见下面链接:
2.主要内容
本文主要介绍如何在宿主中使用SO文件。
一:原理简述
1.安卓中加载so库的方式
我们安卓中最经常使用SO文件的方式是System.loadLibrary(),但是其实还有一个System.load()方法。
这两个方法我们深入进入看,发现其实最终调用的都是方法。
private static String nativeLoad(String filename, ClassLoader loader) {
return nativeLoad(filename, loader, null);
}
所以路径并不是问题,外部的路径也是可以的,主要传入合适的classLoader就可以了。
二:代码编写
1.首先我们要创建SO文件
具体创建的流程和原理可以参见我另外一个系列的文章:JNI入门课程-序章_分享+记录-CSDN博客
这里,我们只要知道我们创建了一个SO库,并且这个SO库的包名+类名是:com.xt.client.jni.PluginJni
方法名和入参如下:
public native String pluginSpliceString(String str, String str2);
功能是拼接两个字符串。
这一块的JNI代码我写在了项目中(项目地址在最尾端),对应的文件名叫PluginJni.cpp,感兴趣的可以去看下。
2.插件项目中使用SO文件做验证
1.插件项目中导入so文件
2.build文件中进行配置
defaultConfig中添加编译类型:
defaultConfig {
applicationId "com.xt.appplugin"
minSdkVersion 26
targetSdkVersion 31
versionCode 1
versionName "1.0"
ndk { abiFilters "armeabi-v7a" }
}
android{}中添加配置:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
3.JNI调用类
因为SO的类名是com.xt.client.jni.PluginJni,并且没有创建入口类。所以这里需要在插件中进行创建对应的类
package com.xt.client.jni;
public class PluginJni {
//加载so库
static {
System.loadLibrary("PluginJni");
}
public native String pluginSpliceString(String str, String str2);
}
4.测试入口代码:
PluginJni pluginJni = new PluginJni();
String s = pluginJni.pluginSpliceString("hello", "world");
((TextView) findViewById(R.id.result)).setText(s);
插件中,我们发现是可以正常拼接字符串现实的。
3.打包apk,拷贝到宿主中
4.宿主项目使用SO文件
1.在宿主中,是也要进行JNI的配置,这个就不多说了,和上面流程类似。
2.同样的因为只引入了SO,所以我们要写调用入口类:
package com.xt.client.jni;
public class PluginJni {
//加载so库
public PluginJni(String path) {
System.load(path);
}
public native String pluginSpliceString(String str, String str2);
}
3.so文件是在插件apk中的,所以我们首先要解压so文件到data目录中。然后把路径传入到PluginJni中,就可以正常使用了。
val apkPath = context.filesDir.absolutePath + File.separator + APK_NAME
val toPath = context.filesDir.absolutePath + File.separator + "plugin"
FileUtil.unzipPack(apkPath, toPath, ".so")
val soFile = File(toPath + File.separator + "lib/armeabi-v7a/libPluginJni.so")
if (!soFile.exists()) {
return
}
val pluginJni = PluginJni(soFile.absolutePath)
val result = pluginJni.pluginSpliceString("aaa", "bbb")
showResult(result)
三:要点总结
无
四。代码地址:
项目地址:
GitHub - aa5279aa/android_all_demo: 一直觉得研究各种技术,一个个demo的下载运行太费劲了,为什么不能有一个所有新技术的融合体demo呢?项目为此而生
插件项目位置:android_all_demo/DemoClient/appplugin at master · aa5279aa/android_all_demo · GitHub
调用类位置:android_all_demo/DynamicFragment.kt at master · aa5279aa/android_all_demo · GitHub