flutter填坑——现有Android项目和现有iOS项目引入同一个Flutter项目
项目目录
flutter_module是AndLangBase(Android现有项目)和iOSLangBase(iOS现有项目)引用的同一个flutter module
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
classpath 'com.android.tools.build:gradle:3.5.3'
//butterknife版本升级
classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0-rc2'
使用自动升级AndroidX功能 Refactor->Migrate to AndroidX
参考链接[https://flutter.cn/docs/development/add-to-app](https://flutter.cn/docs/development/add-to-app)
Add-to-app mode got NullPointerException when use BackgroundMode.transparent
解决:
不使用backgroundMode,注视掉下面代码,跳转flutter页面成功
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)
在flutter module项目的目录下执行命令flutter attach,之后运行app项目,成功之后如下图所示,更新flutter代码时,只有在命令行输入R,就可以实现热更新
两种方式:
1.FlutterEngineCache 在application里提前注册
public static final String FLUTTER_ENGINE_ID="AndLangFlutter";
public static void initFlutter(Context context){
// Instantiate a FlutterEngine.
FlutterEngine flutterEngine = new FlutterEngine(context);
// Configure an initial route.
flutterEngine.getNavigationChannel().setInitialRoute("/");
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
// Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
FlutterEngineCache
.getInstance()
.put(FLUTTER_ENGINE_ID, flutterEngine);
}
之后调用方法(注:只能跳转至setInitialRoute的路由地址,无法修改路由)
activity.startActivity(
FlutterActivity
.withCachedEngine(FLUTTER_ENGINE_ID)
.build(activity)
);
2.withNewEngine 跳转
activity.startActivity(
FlutterActivity
.withNewEngine()
.initialRoute(route)
.build(activity)
);
工具类FlutterUtil
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterActivityLaunchConfigs;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
public class FlutterUtil {
public static final String FLUTTER_ENGINE_ID="AndLangFlutter";
public static void initFlutter(Context context){
// Instantiate a FlutterEngine.
FlutterEngine flutterEngine = new FlutterEngine(context);
// Configure an initial route.
flutterEngine.getNavigationChannel().setInitialRoute("/");
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);
// Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
FlutterEngineCache
.getInstance()
.put(FLUTTER_ENGINE_ID, flutterEngine);
}
public static void startFlutterActivity(Activity activity,String route){
if(!BaseLangUtil.isEmpty(route)){
activity.startActivity(
FlutterActivity
.withNewEngine()
.initialRoute(route)
.build(activity)
);
}else {
activity.startActivity(
FlutterActivity
.withCachedEngine(FLUTTER_ENGINE_ID)
.build(activity)
);
}
}
}
在 Podfile
中添加下面代码:
flutter_application_path = '../my_flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
每个需要集成 Flutter 的 [Podfile target][],执行 install_all_flutter_pods(flutter_application_path)
:
target 'MyApp' do
install_all_flutter_pods(flutter_application_path)
end
运行 pod install
这时候可能会报错
[!] No podspec found for `Flutter` in `../flutter_module/.ios/Flutter/engine`
解决办法:
在AndroidStdio中把Flutter Module选择iOS设备运行一次,再pod install 即可解决。
运行报错: Could not parse callback cache, aborting restore
AppDelegate : FlutterAppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
return true;
改为:
return [super application:application didFinishLaunchingWithOptions:launchOptions];
工具类FlutterUtil
#import "AppDelegate.h"
#import "FlutterUtil.h"
#import
#import
static NSString *FLUTTER_ENGINE_ID=@"iOSLangFlutter";
@implementation FlutterUtil
//获取url中的key的值
+(void)initFlutter{
((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine= [[FlutterEngine alloc] initWithName:FLUTTER_ENGINE_ID];
FlutterEngine *flutterEngine =
((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine;
// Runs the default Dart entrypoint with a default Flutter route.
[[flutterEngine navigationChannel] invokeMethod:@"setInitialRoute"arguments:@"/"];
[flutterEngine run];
// Used to connect plugins (only if you have plugins with iOS platform code).
[GeneratedPluginRegistrant registerWithRegistry:flutterEngine];
}
+(void)pushFlutterVC:(UIViewController *)vc withRoute:(NSString *)route{
FlutterViewController *flutterViewController =nil;
if(![LangUtil isEmpty:route]){
//设置flutter 路由
flutterViewController=[[FlutterViewController alloc]init];
[flutterViewController setInitialRoute:route];
[GeneratedPluginRegistrant registerWithRegistry:[flutterViewController pluginRegistry]];
}else{
FlutterEngine *flutterEngine =
((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine;
flutterViewController =
[[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
}
//导航控制器入栈的方式切换页面
[vc.navigationController pushViewController:flutterViewController animated:YES];
//模态切换的方式切换页面
//[vc presentViewController:flutterViewController animated:YES completion:nil];
}
@end
import 'package:flutter/material.dart';
import 'dart:ui';
import 'package:flutter_module/common/LogUtil.dart';
import 'package:flutter_module/common/RouteUtil.dart';
void main() {
LogUtil.showLog("原生传递的参数:"+window.defaultRouteName);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.blue,
),
initialRoute:"/",
routes:RouteUtil.initRouteMap(context),
home:initRoute(window.defaultRouteName),
);
}
}
方法initRoute中处理接收到Native的参数,返回对应的Widget
if(Platform.isAndroid) {
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
}else {
exit(0);
}