flutter_boost以aar形式运行到安卓项目
前言
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
因为原生未处理,处理后就好了,卡了我半天。。。
-
运行原生工程,会报错,:
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% ,剩下的就是看下源码实现,断点调试验证下,猜测下,总结下,不逼逼了,还有一堆事没做,