在现有Android 项目中加入Flutter页面(1)FlutterActivity、FlutterView 、FlutterFragment

序、上半年准备在原有的项目中接入一些Flutter页面 。当时就是一个感受,一个字,真坑。

讲真的,我有一个大胆的猜测,大部分使用Flutter的项目,应该很少更新Flutter的版本。尽管Flutter已经更新到了***。怎么说呢?

接入时遇到的问题,搜索出来的博客几乎不能用,不能用包括类文件找不到,方法找不到,一运行报错。

气死我了。

1.原有的Android项目已经存在。

此处省略几个字。

2.在Android项目中创建 Flutter  的Module。

2.1File —— New —— New Module 

在现有Android 项目中加入Flutter页面(1)FlutterActivity、FlutterView 、FlutterFragment

在现有Android 项目中加入Flutter页面(1)FlutterActivity、FlutterView 、FlutterFragment

 当然也可以用命令行去创建,自行百度。

2.2据说要给setting.gradle 加入配置文件

在现有Android 项目中加入Flutter页面(1)FlutterActivity、FlutterView 、FlutterFragment

 PS:Flutter 的 module 创建完最后,AndroidStudio就自己有了这块代码了,不需要手动去写这块东西。Binding 报错,不用管好吧。

PS:接下来打开一个 Flutter 的main.dart 文件,会报错,需要你去设置一下flutter SDK。就可以了。文件有提示,因为我设置完了,不能截图。

在现有Android 项目中加入Flutter页面(1)FlutterActivity、FlutterView 、FlutterFragment

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的代码。

上一篇:路由


下一篇:BGP概述及基础配置(二)