Flutter-Android填坑之旅

为了不走寻常路,文章是我集成Flutter过程遇到的问题,如果不想看我啰嗦,可以直接看文章Flutter-Android快速集成

Flutter项目,同事已经开发完成,现需要将Flutter项目集成到自有Android项目中。

我的目的是赶紧将项目跑起来…

我的目的是赶紧将项目跑起来…

我的目的是赶紧将项目跑起来...

自有项目采用多module形式。基本一个大功能一个module。项目结构如下:

-app
-coreLib
-shareLib
-mineLib
-flutterLib//这个是新建的,flutter将放在这里
复制代码

之前没接触过Flutter,所以补充下。看了官方文档以及一些博客和WIKI。有了大概了解之后,开始集成。

官方有个WIKI说如何集成:github.com/flutter/flu…

呃,说实话,“麻(wo)烦(hai)的(mei)一(xi)逼(kan)”,先不按这个来。

目标:最好是flutter项目以aar形式放到library中,这样开发起来,独立,效率。自有项目的代码管理和flutter代码管理区分。毕竟不是一拨人开发。(呃,其实我们团队就这么多人,这俩人开发安卓项目,这俩人开发flutter项目,一个团队的)

走你---项目结构如下:

第一坑来了,aar怎么来?

回到flutter项目中,flutter run --release直接生成了apk..我要aar,你给我apk有个毛用 先看下flutter项目目录

熟悉安卓的都知道,build目录里面东西多多啊

哈哈,果然,在Flutter/build/outputs/aar找到了,看下文件大小,5.9M,嗯,差不多。就你了… 放到项目中

至此,不算填坑,且往后看

第二坑:arm架构调整

我们自有项目只支持arm架构,和美团类似。而Flutter项目默认是arm-v8的,好么,第二坑来了。 那按照美团的技术博客中所说,解压、复制吧啦吧啦…

呃,有这么麻烦么,直接把libflutter.so放到工程里面不就行了?

这样不是很简单?按照美团的提示,找到相应目录$FLUTTER_ROOT/bin/cache/artifacts/engine

先看下目录里面有啥?

呃,这么多,看美团处理了3个arm目录的。我只需要一个就行呀,用哪个?就3个,一个一个的试吧 release?这个显而易见,你先来。进入目录,unzip flutter.jar

好,直接拿走,扔到flutterLib/libs/armeabi/下面。好,走起,跑起来。

项目跑起来了,跳到Flutter页面..

啪啪啪,打脸…

Abort message: '[FATAL:flutter/runtime/dart_vm.cc(415)] Error while initializing the Dart VM: Snapshot not compatible with the current VM configuration: the snapshot requires 'product no-type_checks no-asserts no-error_on_bad_type no-error_on_bad_override sync_async reify_generic_functions arm64' but the VM has 'product no-type_checks no-asserts no-error_on_bad_type no-error_on_bad_override sync_async reify_generic_functions arm-eabi softfp’
复制代码

这是特喵的啥啊,google一波

github.com/flutter/flu…

这个里面,也没说咋解决。 看意思是要arm64的? 难道不能用android-arm-release里面的so?要用android-arm64-release的?那试试

跑起来,跳到Flutter页面

啪啪啪,又打脸…

java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/com.letv.android.client-RzaguRHTMAAeoInec8Xl8g==/lib/arm/libflutter.so" is 64-bit instead of 32-bit
复制代码

这特喵又是啥?google又走一波 blog.csdn.net/u014316462/…

看到这一句:“网上分析了出现这种情况的原因,可能是混合使用了32bit和64bit的库文件”。

后面的我就没看... 呃,那就是还是要用android-arm-*的so,不是用android-arm64-*里面的。

等等,前面只试了android-arm-release下面so,还有其他两个arm的目录呢:android-arm android-arm-profile 那试下android-arm这个下面so

跑起来,跳到Flutter页面

啪啪啪,脸肿了,艹

Error while initializing the Dart VM: JIT runtime cannot run a precompiled snapshot
复制代码

擦...这又是啥…

不过看样子,so的问题解决了。这应该是个新坑。

好,总结一下二坑。

二坑填坑:so可以直接用android-arm下面的so。

第三坑

顺着二坑继续分析

JIT runtime cannot run a precompiled snapshot
复制代码

JIT:在debug包的时候才会用JIT

precompiled snapshot:这个是release模式生成的。

这么一想,自有项目应该也用release才对

试试

打release包,安装

[FATAL:flutter/shell/platform/android/library_loader.cc(24)] Check failed: result. 
复制代码

额,这个啥也看不出来啊

后来分析:应该是so库的问题,release模式应该用android-arm-release下面的so文件。另外如果项目需要混淆,需要把flutter相关的混淆加上。

#Flutter Wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.**  { *; }
-keep class io.flutter.util.**  { *; }
-keep class io.flutter.view.**  { *; }
-keep class io.flutter.**  { *; }
-keep class io.flutter.plugins.**  { *; }
复制代码

第三坑填坑

当遇到Check failed: result时,应该检查so文件是否正常,另外混淆的话,把flutter的混淆加上。

其实到了这一步,我就停下来思考了

不按照官网指导来,是否真的可行?

平常开发过程中自有项目都是用debug模式,flutter项目用release还是用debug?用release模式有上面的问题,用debug模式?测试阶段换成release模式?这有点不灵活啊

第四坑

另外一个问题:我在集成过程中,遇到一个问题,现在复现不出来了(?)

大概意思是:

NoClassFound :PathProviderPlugin
复制代码

GeneratedPluginRegistrant类中调用导致的

对比flutter-release.aar和flutter通过release跑起来的apk

aar确实少了好多东西

这时候需要看下flutter 的gradle文件了,看看都干了啥

填坑

从app下的build.gradle发现依赖一个flutter的library。

dependencies {
    implementation project(':flutter')
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    ...
}
复制代码

这个flutter的module哪里来的?

看下settings.gradle文件

include ':app'

rootProject.name = 'android_generated'
setBinding(new Binding([gradle: this]))
evaluate(new File('include_flutter.groovy'))
复制代码

include_flutter.groovy是什么鬼?

目录下面找到这个文件

def scriptFile = getClass().protectionDomain.codeSource.location.path
def flutterProjectRoot = new File(scriptFile).parentFile.parentFile

gradle.include ':flutter'
gradle.project(':flutter').projectDir = new File(flutterProjectRoot, '.android/Flutter')

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile()
    gradle.include ":$name"
    gradle.project(":$name").projectDir = pluginDirectory
}

gradle.getGradle().projectsLoaded { g ->
    g.rootProject.afterEvaluate { p ->
        p.subprojects { sp ->
            if (sp.name != 'flutter') {
                sp.evaluationDependsOn(':flutter')
            }
        }
    }
}
复制代码

下面分析一下include_flutter.groovy这个文件

def scriptFile = getClass().protectionDomain.codeSource.location.path
def flutterProjectRoot = new File(scriptFile).parentFile.parentFile
//这两行是确定文件路径

gradle.include ':flutter'
gradle.project(':flutter').projectDir = new File(flutterProjectRoot, '.android/Flutter')
// OK,声明flutter的module,并设置module路径,前面提到的flutter的module的问题解决了

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
// 读取.flutter-plugins文件,这里看下文件有啥
// path_provider=/Users/PanJiafang/.pub-cache/hosted/pub.flutter-io.cn/path_provider-0.4.1/
// sqflite=/Users/PanJiafang/.pub-cache/hosted/pub.flutter-io.cn/sqflite-0.13.0/

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile()
    gradle.include ":$name"
    gradle.project(":$name").projectDir = pluginDirectory
}
// 意思是根据前面读入的内容引入path_provider和sqflite两个库,库路径为xxxx/android/

gradle.getGradle().projectsLoaded { g ->
    g.rootProject.afterEvaluate { p ->
        p.subprojects { sp ->
            if (sp.name != 'flutter') {
                sp.evaluationDependsOn(':flutter')
            }
        }
    }
}
复制代码

看下目录里有啥

OK,到这里,应该能明白Flutter集成是咋回事了。 flutter相关的东西都通过include_flutter.groovy处理。

那么填坑之旅也算完成了,集成Flutter可以这么做,请看文章:Flutter-Android快速集成

参考文献:

美团的 Flutter的原理及美团的实践

Flutter 官方WIKI

转载于:https://juejin.im/post/5c0dfffb6fb9a049b221b5eb

你可能感兴趣的:(Flutter-Android填坑之旅)