Flutter框架Android so库的一些实践

学而思网校1对1的android工程是用flutter框架实现的,而android工程不可避免的要和cpu架构和so库打交道,在实践中,针对flutter框架对cpu架构的支持,我们也有一些经验在此总结。

so库说明

so库在android中,是使用c/c++代码编译出来的库文件,可以使用ndk调用,就是你在android代码中见到的native方法,具体的实现就在so库中。

关于so库兼容性问题

andorid中或多或少都会引用到第三方库,而很多第三方库中都有so的存在,不论是复制到项目中(如百度地图),或是gradle依赖(如个推)
其中都涉及到了so库的相关问题,如果你选择的库是有所有cpu类型可选还好,如果不是,那么就需要自定义设置了。

举个栗子

你的app依赖两个库,分别是lib1,lib2

lib1: arm64-v8a,armeabi-v7a
lib2: armeabi-v7a

那么当你运行在v7的手机上时,因为你的项目含有v7的so库,所以没有问题,可以跑起来如果,你运行在v8手机上,那么你的项目就会Crash, 为啥呢? 这就涉及到so对齐了

so对齐

简单来说,就是要有就必须都有,如果一个没有,那就一个都不要
比如上面的例子,如果你是自己复制到项目下的,你需要删掉arm64-v8a的文件夹

flutter经典问题couldn't find "libflutter.so"

引发的原因

导致这个问题出现的原因是因为我们在项目种使用了so库,或者项目中引用的三方sdk使用了so库。在引用so库时需要针对不同的cpu架构使用不同的.so文件。armeabi,armeabi-v7a,x86,arm64-v8a,大家通常会对这几个cpu架构进行适配。然而问题就出在现在Flutter在打包Apk时不能同引入arm32和arm64的libflutter.so。我门将打好包的Apk安装到arm64架构(默认打包会引入arm32)的手机上就出现了couldn't find libflutter.so这个异常。

如何解决

  1. 针对arm32和arm64分别打包(flutter 提供了命令来之分别对arm32和arm64分别打包)

flutter build apk --target-platform=android-arm32
flutter build apk --target-platform=android-arm64

我们用flutter build apk --target-platform=android-arm64打包apk,并在arm64cpu架构的手机安装运行,很好完美运行。但是当我们吧apk安装到32位时问题再次出现,原因就不再重复了。很显然到这里这个方式并不能解决这个问题,为了适配arm32和arm64我们需要分别打包,而国内大部分应用市场不能针对不同cpu架构上传不同的apk。

  1. 不对arm64做适配,打包时排除其他非arm32架构的so文件
    这时候有些朋友可能会又疑问,问题不就是因为打包时没有引入arm64的libflutter的so文件导致在arm64架构手机上出现“兼容”问题的么。arm64cpu架构是可以像下兼容的,简单点就是arm64架构的cpu可以使用arm32的.so文件。出现问题真正原因是我们在引用so库时(引用的三方库中引用了so库),对arm64做了兼容。这样就会导致运行时系统误以为我们的应用对所有的so库做了arm64架构的兼容,但是在打包时libflutter并没有引入arm64的版本。这就导致系统去寻找arm64版本的libflutter发现找不到。系统误会了我们,我们只能通过gradle在打包时排除其他非arm32架构的so文件来解除这个误会。
    好那如何排除其他非arm32架构的so文件。在app下的gradle文件加入如下代码
buildTypes {
     release {
         ndk{
             //这里其实我觉可以直接是用"armeabi-v7a",但国内几个大哥之前使用的都是"armeabi"
             abiFilters "armeabi"
         }
     }
     debug {
         ndk {
             //这里要加上,否则debug包会出问题,后面三个为可选,x86建议加上不然部分模拟器回报错
             abiFilters "armeabi", ,"armeabi-v7a","arm64-v8a", "x86"
         }
     }
 }

3.flutter 1.7.8+hotfix.2 以上版本已经支持flutter 64位了 直接打包即可.

只支持64位:flutter build apk --target-platform android-arm64
支持32位:flutter build apk --target-platform=android-arm
同时支持64位和32位:flutter build apk

工程加入x5内核引起的新问题

经过上述文章方法的处理,我们的工程解决了在64位手机上,出现couldn't find "libflutter.so"引起的Crash问题,但是,当我们引入x5内核后,又出现了新的问题。
这是我们在没有引入x5内核前工程支持的cpu架构配置,这个地方需要说明,如果不加入 "arm64-v8a"配置的话,flutter build apk命令虽然会将so库打入工程,但是平时开发时使用的flutter run apk命令并不会把so库打入工程。

ndk {
                abiFilters "armeabi" ,"armeabi-v7a", "arm64-v8a"
            }

这种配置方式能保证flutter run和flutter build同时生效,不会引起程序因为找不到so库引起的Crash。
但是当引入x5内核后,会出现如下错误

X5 does not support the 64-bit mode to run

x5官方解释是x5内核暂时不提供64位的so文件,在64位手机上需要让AP以32位模式运行,所以我们如果加入了 "arm64-v8a"的话,x5内核在64位手机无法启动。
但是加入的话,又会引起flutter的so库找不见,解决办法如下:

  1. 修改flutter.gradle里面,关于flutter run的配置,使其支持把64位的so库打入工程
 String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
        flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile();

        if (useLocalEngine(project)) {
            String engineOutPath = project.property('localEngineOut')
            File engineOut = project.file(engineOutPath)
            if (!engineOut.isDirectory()) {
                throw new GradleException('localEngineOut must point to a local engine build')
            }
            Path baseEnginePath = Paths.get(engineOut.absolutePath)
            flutterJar = baseEnginePath.resolve("flutter.jar").toFile()
            if (!flutterJar.isFile()) {
                throw new GradleException("Local engine jar not found: $flutterJar")
            }
            localEngine = engineOut.name
            localEngineSrcPath = engineOut.parentFile.parent
            // The local engine is built for one of the build type.
            // However, we use the same engine for each of the build types.
            project.android.buildTypes.each {
                addApiDependencies(project, it.name, project.files {
                    flutterJar
                })
            }
        } 
  1. 修改构建脚本,在jenkens上构建工程时,动态修改cpu架构支持
 #andorid app build.gradle 工程配置文件地址
    # 删除 arm64-v8a,防止  hybrid 在某些手机上无法构建。
    androidAppGradlePath="$JENKINS_WORKSPACE/northstar_flutter/android/app/build.gradle"
    echo "App 中 app/build.gradle 配置文件地址是:${androidAppGradlePath}"
    sed -i 's/, "arm64-v8a"/ /' $androidAppGradlePath
    echo "已经将 arm64-v8a 从文件中剔除,文件路径是:$androidAppGradlePath"

我们最终采用了方案2,因为每次更新flutter的版本,flutter.gradle文件都会被官方修改,尽量不动此文件为好。

总结

以上就是我们在学而思网校1对1android工程中对flutter框架支持so库做的一些实践和总结,随着flutter版本的不断更新,相信官方会对cpu架构支持越来越好。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容