Android_NEW

flutter_boost以aar形式运行到安卓项目

2020-04-02  本文已影响0人  gogoingmonkey

前言

flutte_boost框架,是咸鱼开源开源的:https://github.com/alibaba/flutter_boost
随意搜索一大堆接入使用教程,也存在很多非原创文章,一次又一次的让很多开发者从入门到放弃,市面上大部分文章都是按在安卓项目创建一个moudle形式接入到安卓项目中,单对于很多项目规模较大的团队,毫无卵用,比如我们就是以aar形式接入,好处都耳熟能详了。网上搜索了很多以aar形式的接入方式,以为能找到一篇文章指引光明。一次又一次迷失,短暂放弃了几天,还是要硬着头皮搞啊。

当前flutter版本: 1.9.1_hotfix.6
使用flutter_boost版本: 0.1.63

由于现在1.12版本flutter 稳定性及对Androidx的支持,当前项目未支持AndroidX,虽然我在单独分支已经搞成AndroidX了,不过并没得到充分验证,我们决定使用flutter1.9.1版本。

规划(后续文章)

1.flutter_boost运行起来的爬坑——也就是本文
2.flutter_boost原理分析——后续时间充裕了整理
3.flutter_boost高级用法、借助思路我们可以做些什么——后续时间充裕整理
4.官方路由、几种路由框架横向对比

当前问题 &接入步骤

1.首先第一个比较坑的问题:


image.png

这个是官方文档中的版本号,以及下图的添加依赖方式:


image.png
我按上图的方式引入,因为我需要supprot库,:
flutter_boost:
    git:
        url: 'https://github.com/alibaba/flutter_boost.git'
        ref: 'task/task_v1.12.13_support_hotfixes'

这个接入方式是已当前分支的代码拉取最新的,计入存在很大的风险,我当时第一次就使用这种方式遇到报错,直接GG,

1. 处理flutter 部分

后面采用以下方式,正常接入,推荐使用下面的方式接入稳定版本

flutter_boost: 0.1.63

然后命令或者点击IDE工具同步,处理flutter部分的初始化

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();

    FlutterBoost.singleton.registerPageBuilders({
      'embeded': (pageName, params, _)=>EmbededFirstRouteWidget(),
      'first': (pageName, params, _) => FirstRouteWidget(),
      'second': (pageName, params, _) => SecondRouteWidget(),
      'tab': (pageName, params, _) => TabRouteWidget(),
      'platformView': (pageName, params, _) => PlatformRouteWidget(),
      'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params),
      ///可以在native层通过 getContainerParams 来传递参数
      'flutterPage': (pageName, params, _) {
        print("flutterPage params:$params");

        return FlutterRouteWidget(params:params);
      },
    });
    FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver());
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Boost example',
        builder: FlutterBoost.init(postPush: _onRoutePushed),
        home: Container(
            color:Colors.white
        ));
  }
  //原生调用时候会回调
  void _onRoutePushed(
      String pageName, String uniqueId, Map params, Route route, Future _) {
  }
}

flutter部分就完成了!!!!!!

2.打成aar

修改清单文件、修改applicationID 、修改依赖未library 执行命令打成aar,你会发现flutter_boost会并没有被打入到aar中,
使用fat-aar,自行百度下,田间两处依赖及dependence依赖的脚本代码,再次执行,我使用fat-aar 1.1.7版本,目前正常

3.拿到aar,新建一个安卓工程

因为flutter工程使用的是support的版本,这里就不要搞androidx,否则清单文件合并失败。丢到libs下,这里要添加依赖:
implemention(name:"app-release",ext:"aar")
名字自己跟你的一样,默认不处理就是app-release, 这个时候如果报错app 模块问题,则添加下面的

repositories {
        //添加一个本地仓库,并把libs目录作为仓库的地址
        flatDir {
            dirs 'libs'
        }
    }

再次同步,然后就是初始化flutter_boost安卓部分代码,这里提下,如果想在flutter工程直接运行刚才的添加依赖的flutter项目,只有单独开启Android目录下工程,然后同步,在关闭再启动原flutter 工程才行,

4. flutter_boost官方坑

官方文档未更新,按照网上一堆教程,会发现根本没有这个方法,这个时候可以去参看下别的类,有没有什么单例等类可用, 直接用下面的代码初始化:

public class Application extends android.app.Application {

    @Override
    public void onCreate() {
        super.onCreate();

        INativeRouter router =new INativeRouter() {
            @Override
            public void openContainer(Context context, String url, Map<String, Object> urlParams, int requestCode, Map<String, Object> exts) {
                String  assembleUrl= Utils.assembleUrl(url,urlParams);
                PageRouter.openPageByUrl(context,assembleUrl, urlParams);
            }

        };


        FlutterBoost.BoostPluginsRegister pluginsRegister= new FlutterBoost.BoostPluginsRegister(){

            @Override
            public void registerPlugins(PluginRegistry mRegistry) {
                GeneratedPluginRegistrant.registerWith(mRegistry);
                TextPlatformViewPlugin.register(mRegistry.registrarFor("TextPlatformViewPlugin"));
            }
        };

        Platform platform= new FlutterBoost
                .ConfigBuilder(this,router)
                .isDebug(true)
                .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
                .renderMode(FlutterView.RenderMode.texture)
                .pluginsRegister(pluginsRegister)
                .build();

        FlutterBoost.instance().init(platform);
    }
}

里面涉及到的类:

package com.example.myflutterboostaddaardemo;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.idlefish.flutterboost.containers.BoostFlutterActivity;

import java.util.HashMap;
import java.util.Map;

public class PageRouter {

    public final static Map<String, String> pageName = new HashMap<String, String>() {{

        put("first", "first");
        put("second", "second");
        put("tab", "tab");
        put("sample://flutterPage", "flutterPage");
    }};

//    public static final String NATIVE_PAGE_USER_CENTER_URL = "sample://userCenterPage";
    public static final String NATIVE_PAGE_USER_CENTER_URL = "sample://nativePage";
    public static final String FLUTTER_PAGE_URL = "first";
    public static final String FLUTTER_PAGE_CONTACT_URL = "sample://flutterFragmentPage";

    public static boolean openPageByUrl(Context context, String url, Map params) {
        return openPageByUrl(context, url, params, 0);
    }

    public static boolean openPageByUrl(Context context, String url, Map params, int requestCode) {

        String path = url.split("\\?")[0];

        Log.i("openPageByUrl",path);

        try {
            if (pageName.containsKey(path)) {
                Intent intent = BoostFlutterActivity.withNewEngine().url(pageName.get(path)).params(params)
                        .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque).build(context);
                if(context instanceof Activity){
                    Activity activity=(Activity)context;
                    activity.startActivityForResult(intent,requestCode);
                }else{
                    context.startActivity(intent);
                }
                return true;
            } else if (url.startsWith(FLUTTER_PAGE_CONTACT_URL)) {
                context.startActivity(new Intent(context, ContactActivity.class));
                return true;
            } else if (url.startsWith(NATIVE_PAGE_USER_CENTER_URL)) {
                context.startActivity(new Intent(context, UserCenterActivity.class));
                return true;
            }

            return false;

        } catch (Throwable t) {
            return false;
        }
    }
}

package com.example.myflutterboostaddaardemo;

import android.content.Context;
import android.view.View;
import android.widget.TextView;

import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;

public class TextPlatformViewFactory extends PlatformViewFactory {

    public TextPlatformViewFactory(MessageCodec<Object> createArgsCodec) {
        super(createArgsCodec);
    }

    @Override
    public PlatformView create(Context context, int i, Object o) {
        return new TextPlatformView(context);
    }

    private static class TextPlatformView implements PlatformView {

        private TextView platformTv;

        public TextPlatformView(Context context) {
            platformTv = new TextView(context);
            platformTv.setText("PlatformView Demo");
        }

        @Override
        public View getView() {
            return platformTv;
        }

        @Override
        public void dispose() {

        }
    }
}

package com.example.myflutterboostaddaardemo;

import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.StandardMessageCodec;

public class TextPlatformViewPlugin {
    public static void register(PluginRegistry.Registrar registrar) {
        registrar.platformViewRegistry().registerViewFactory("plugins.test/view",
                new TextPlatformViewFactory(StandardMessageCodec.INSTANCE));
    }
}

其他就是两个activity,如果不清楚,下载我demo看下

中间你可能会遇到的问题

1.想直接运行flutter_boost ,会报错空指针:


image.png

因为原生未处理,处理后就好了,卡了我半天。。。

  1. 运行原生工程,会报错,:


    image.png

这个比较坑,网上一大堆说是因为混淆了,然而我测试环境根本就没混淆,去查看官方demo,发现他添加了依赖,加上就可以了,这个是一个方法,查看官方demo

 implementation 'android.arch.lifecycle:common-java8:1.1.1'

又费了我不少时间
3.设置多个跳转到flutter,居然只有第一个成功,断点看到:


image.png

原来还要在原生项目的清单文件中指定

 <activity
            android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"
            android:theme="@style/Theme.AppCompat"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize" >
            <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/page_loading"/>

        </activity>

总结

坑很多,运行起demo,你就成功40% ,剩下的就是看下源码实现,断点调试验证下,猜测下,总结下,不逼逼了,还有一堆事没做,

上一篇下一篇

猜你喜欢

热点阅读