上次开发的相机插件厂家提供的是一个AAR库,导入就可以使用,可以直接用原生UI控件渲染界面,也可以用插件内方法回调的数据传递到Flutter层进行展示。
今天公司又提供了另一台相机的sdk,本来想着已经学会了aar插件开发,这次又提供了一套jar和so文件,又给我出难题。根据百度得知,jar文件封装了方法供开发者调用,而so文件是和底层打交道的函数库,所以和手机的CPU架构有关,一般分为armeabi,armeabi-v7a,arm64-v8a等其他类型的架构。最原始的版本就是32位的armeabi,而现在主流的手机一般都采用64位的arm64-v8a,。
所以一般来说要对不同架构的手机提供不同的sdk包,当然也可以只使用armeabi,因为后两种架构是可以向下兼容的。所以一部分第三方服务商虽然提供的SDK包含各种架构的,也会顺带一句:只引入armeabi也能正常运行,还能减小包的体积。
然而我们这个相机厂商只提供
armeabi架构的包
由于测试机是v8a的架构,而且flutter经过多个版本更新后,不能直接flutter run的时候指定平台架构为32位的,则无法调用到so文件,所以有不小的麻烦。这先按下不表。
一、导入jar包和so文件
导入jar包
首先还是在plugin/android的目录新建一个libs文件夹,然后将jar文件放进去就好

然后在依赖里一个一个导入就好。
dependencies {
implementation files('libs/hyfisheyepano.jar')
implementation files('libs/mid-core-sdk-4.0.7.jar')
implementation files('libs/org.apache.http.legacy.jar')
implementation files('libs/wup-1.0.0.E-SNAPSHOT.jar')
implementation files('libs/Xg_sdk_4.0.3_20180720_1441.jar')
implementation files('libs/nv_sdk_v1.0.0.jar')
}
复制代码
导入so文件
so文件包在编辑器中只需要放入指定位置,就可以被找到,在Android studio中需要放在src/main/jniLibs中,所以直接将文件包一下子复制进去。

如果有多种架构的so文件,同样也是把包整体复制进来。
运行一下
这个时候,程序是可以正常跑起来了,不涉及到插件功能的时候运行正常,一旦需要调用一下插件的方法的时候,程序会直接奔溃退出,查看控制台,提示出Can't link the lib。

这里的提示语句是sdk里使用try catch返回出来的,本意就是coundn't find "xxx.so",无法在程序里面找到所需要的文件,按照方法导入了,怎么又无法链接到,接着往下看。
二、加载so文件
上面我们运行了一下,发现是jar包里的方法需求调用so文件,但是怎么都调用不到,这又是什么问题?
验证安装包
首先想到的是验证一下文件是否引入成功,如果文件引入成功,可以直接查看apk里查看到引入的文件。所以首先找到安装包的位置
当flutter运行于debug模式的时候,程序会先生成一个app-debug.apk的文件,储存在项目目录中build/app/outputs/flutter-apk的这个位置,当然这里同时也保存了release版的安装包。
在Android studio的菜单栏中,找到build -> Analyze Apk这个功能,打开我们的app-debug.apk。

可以发现里面包含了多种架构的jniLibs,而我们的手机是arm64-v8a,程序非常符合逻辑的就去对应的架构中去寻找需要文件,而我们的文件只有armeabi的版本,找不到文件,插件方法无法调用,程序就报错崩溃

根据开头提到的:armeabi-v7a和arm64-v8a这两种架构是可以向下兼容的,聪明的你肯定想到可以把其他架构的文件包删掉就好,只有保留有内容的。
解决方法
解决方法就一句话,在build.gradle文件中加上以下这句话:
android{
defaultConfig{
ndk {
abiFilters 'armeabi'
}
}
}
复制代码
在这里是通过 abiFilters 来指定我们需要的 ABI,也就是指定需要的CPU架构,加上上面语句后,在通过Analyze Apk的功能,可以看到:

安装包里只剩armeabi了,这样的话,基本的3中架构调用文件的时候,都会调用到这个包里的文件,程序就不会崩溃了。
这里不得不插一句,因为我在开发插件,在得知这个解决方法的时候,我将这个语句放入了
android/build.gradle,没有任何效果,而是应该写在example/android/build.gradle的这个文件里,这里才是安装包生成时候所依赖的参数和配置。这个小问题卡了近我3个小时。
三、还是跑不起来?
在指定了ABI之后,程序不会崩溃了,因为程序直接跑不起来了。

话不多说,还是直接看控制台的报错,发现缺少了最核心的文件-libflutter.so。而在开始未指定ABI的时候,v8a的文件包里是有这个文件的,现在这个文件随它一起蒸发了。

依然先打开百度,输入这个关键词,有无数的答案。万语千言就一个原因,在flutter构建apk的时候,需要指定对应的平台,才会生成对应架构的libflutter.so文件。
在旧版本的flutter中,可以直接运行flutter run --target-platform android-arm命名来指定平台,新版又去掉了这个功能。只有发布release的时候才能指定平台,但不可能每修改一点,需要调试了就打包一份吧。
网上还有很多其他方法,试了都不太管用。其实有个最不优雅但很实用的方法,直接再别的包里拿一个libflutter.so文件,放进armeabi包里,运行成功。

- 1、复制一份未指定ABI前的
app-debug.apk。 - 2、修改文件后缀
apk到zip并解压 - 3、将文件夹里
libs\arm64-v8a里的libflutter.so拿出来 - 4、放进插件里
armeabi里 - 5、重新运行,没报错了。
四、总结
研究怎么导入aar的时候,3行代码花了3天,研究怎么导入jar&so的时候,Ctrl C + Ctrl V几个文件又花了3天,果然是万事开头难。
大部分时间都是对一个语句的反复尝试,多次怀疑自己哪的单词是不是拼错了,结果还是对解决方法的原理理解不到位。最开始只知道so放到指定位置就可以了,请求不到的时候报错也不知道什么意思,然后发现,不同的CPU架构会请求不同的包,就开始找指定ABI的方法。方法很简单啊,就一句话,但放错了位置,没任何效果,半天开不了窍。终于在最后把每一块理解到位了,才解决了问题。



















![[02/27][官改] Simplicity@MIX2 ROM更新-一一网](https://www.proyy.com/wp-content/uploads/2020/02/3168457341.jpg)



![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)