序、上半年准备在原有的项目中接入一些Flutter页面 。当时就是一个感受,一个字,真坑。
讲真的,我有一个大胆的猜测,大部分使用Flutter的项目,应该很少更新Flutter的版本。尽管Flutter已经更新到了***。怎么说呢?
接入时遇到的问题,搜索出来的博客几乎不能用,不能用包括类文件找不到,方法找不到,一运行报错。
气死我了。
1.原有的Android项目已经存在。
此处省略几个字。
2.在Android项目中创建 Flutter 的Module。
2.1File —— New —— New Module
当然也可以用命令行去创建,自行百度。
2.2据说要给setting.gradle 加入配置文件
PS:Flutter 的 module 创建完最后,AndroidStudio就自己有了这块代码了,不需要手动去写这块东西。Binding 报错,不用管好吧。
PS:接下来打开一个 Flutter 的main.dart 文件,会报错,需要你去设置一下flutter SDK。就可以了。文件有提示,因为我设置完了,不能截图。
2.3可以先运行一下flutter 项目。
3.Android页面跳转到 Flutter页面
3.1创建一个FlutterActivity(配置清单文件记得加)
package com.supermax.flutter;
import io.flutter.embedding.android.FlutterActivity;
import android.os.Bundle;
public class FlutterActivityPage extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
3.2配置清单文件添加代码 FlutterActivity
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:theme="@style/AppThemeNoActionBar"
android:windowSoftInputMode="adjustResize" />
3.3MainActivity 里面加入跳转代码
package com.supermax.flutter;
import androidx.appcompat.app.AppCompatActivity;
import io.flutter.embedding.android.FlutterActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button btn_flutter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_flutter = findViewById(R.id.btn_flutter);
btn_flutter.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//直接使用 FlutterActivity 进行跳转
// startActivity(FlutterActivity
// .withNewEngine()
// .initialRoute("route")
// .build(MainActivity.this));
//FlutterActivityPage 继承FlutterActivity
startActivity(FlutterActivityPage
.withNewEngine()
.initialRoute("route")
.build(MainActivity.this));
}
});
}
}
3.4main.dart 里面加入接收的代码
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(_widgetForRoute(window.defaultRouteName));
}
Widget _widgetForRoute(String route) {
print("111=" + route);
switch (route) {
case 'route':
_toastMessage("111=" + route);
return MyApp();
default:
return Center(
child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
);
}
}
void _toastMessage(String title) {
Fluttertoast.showToast(
msg: title,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.black45,
textColor: Colors.white,
fontSize: 16.0);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
PS:可以开始了各位。
运行,点击,跳转,完美。
4.Flutter 页面跳转到 Android页面,使用了 MethodChannel.MethodCallHandler
4.1写一个类实现 MethodChannel.MethodCallHandler,并重写onMethodCall方法
package com.supermax.flutter;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterView;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
/**
* @Author yinzh
* @Date 2021/11/3 14:33
* @Description
*/
public class Flutter2AndroidHelp implements MethodChannel.MethodCallHandler {
public static String CHANNEL_NAME = "com.supermax";
private MethodChannel methodChannel;
private FlutterView flutterView;
private Activity mActivity;
private Flutter2AndroidHelp() {
}
private static Flutter2AndroidHelp instance;
public static Flutter2AndroidHelp getInstance() {
if (instance == null) {
synchronized (Flutter2AndroidHelp.class) {
if (instance == null) {
instance = new Flutter2AndroidHelp();
}
}
}
return instance;
}
private Flutter2AndroidHelp(Activity activity) {
this.mActivity = activity;
}
/**
* 接收Flutter传来的指令,进一步处理
* @param call
* @param result
*/
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (call == null) {
return;
}
Log.i("FlutterPluginJumpToAct", "method is " + call.method + " arguments is " + (call.arguments == null ? "" : call.arguments.toString()));
switch (call.method) {
case "withoutParams":
Intent intent = new Intent(mActivity, Flutter2AndroidActivity.class);
mActivity.startActivity(intent);
result.success("success");
break;
case "withParams":
if (call.arguments == null) {
return;
}
Intent intent1 = new Intent(mActivity, Flutter2AndroidActivity.class);
String text = call.arguments.toString();
intent1.putExtra("test", text);
mActivity.startActivity(intent1);
result.success("success");
break;
default:
result.notImplemented();
break;
}
}
public void registerWith(BinaryMessenger registrar, Activity activity) {
methodChannel = new MethodChannel(registrar, CHANNEL_NAME);
Flutter2AndroidHelp instance = new Flutter2AndroidHelp(activity);
//setMethodCallHandler在此通道上接收方法调用的回调
methodChannel.setMethodCallHandler(instance);
}
}
4.2FlutterActivity 里面注册
package com.supermax.flutter;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import android.os.Bundle;
public class FlutterActivityPage extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(getFlutterEngine());
Flutter2AndroidHelp.getInstance().registerWith(getFlutterEngine().getDartExecutor().getBinaryMessenger(),this);
}
}
4.3main.dart 写代码
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(_widgetForRoute(window.defaultRouteName));
}
Widget _widgetForRoute(String route) {
print("111=" + route);
switch (route) {
case 'route':
_toastMessage("111=" + route);
return MyApp();
default:
return Center(
child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
);
}
}
void _toastMessage(String title) {
Fluttertoast.showToast(
msg: title,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.black45,
textColor: Colors.white,
fontSize: 16.0);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
static MethodChannel _methodChannel= MethodChannel("com.supermax");
Map<String, String> map = { "Android": "好兄弟,我来了" };
void _incrementCounter() {
setState(() {
_counter++;
_jumpAndroid();
});
}
_jumpAndroid() async{
print("来了吗我擦");
_methodChannel.invokeMethod("withoutParams",map);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
4.4请把MainActivity里面的跳转代码改一下。
Intent intent = FlutterActivityPage
.withNewEngine()
.initialRoute("route")
.build(MainActivity.this);
intent.setClass(MainActivity.this, FlutterActivityPage.class);
startActivity(intent);
PS:里面有个坑,如果不重新指定Activity的话,只会默认去执行FlutterActivity的代码。