30

Flutter 添加到现有项目

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzIxNzU1Nzk3OQ%3D%3D&%3Bmid=2247489954&%3Bidx=1&%3Bsn=a03d1b8c93015e73dbee1c36ef01bf9b
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

code小生 一个专注大前端领域的技术平台 公众号回复 Android 加入安卓技术群

作者:言就尔宿1992

链接:https://www.jianshu.com/p/9425dd2baacc

声明:本文已获 言就尔宿1992 授权发表,转发等请联系原作者授权

Flutter 添加到现有项目 (Android)

最近一直在看Flutter 的内容, 加上近期更新的Flutter1.12 有一些Flutter 的api 发生了改变, 所以 某些和android 交互的地方 就发生了变化

比如开始使用的新的插件api 旧的 PluginRegistry.Registrar 不会立即被弃用, 而使用了新的FlutterPlugin, FlutterActivity 的 从io.flutter.app.FlutterActivity 到 io.flutter.app.FlutterActivity

接下来 就是 添加到现有项目步骤 基于androdx

  1. 创建一个原生的Android项目 直接通过AndroidStudio 创建一个androd 项目

  2. 然后在AS 中 通过 new Project 选择 FlutterModule 创建一个Flutter module 创建的时候记得 勾选androidx

  3. 再 androd项目中 app 下 build.gradle 中添加

android{
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

然后 再setting.gradle 中添加

setBinding(new Binding([gradle:this]))
evaluate(new File(
        settingsDir.parentFile,
        '你的flutter module 的名字/.android/include_flutter.groovy'
))

编译

然后成功之后再android 项目中的 build.gradle 中添加

implementation project(path: ':flutter')

编译

调整Flutter 库中关联的.android 中的flutter 的库 中的build.gradle 的 compileSdkVersion minsdkVersion 以及 targetSdkVersion和主项目保持一致,

我用的是 在acticity 中 添加FlutterFragement 首先 Activity 继承 FragmentActivity

对了如果 Android 项目中是androdx 的话 需要再 Flutter项目中修改 pubspec.yaml

moudule 下的 androidX 是否为true;

接下来是我 Flutter 项目中的代码 就是 官方生成的代码 自己稍微改了下

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

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> {
  static const platform = const MethodChannel("com.battery.io/battery");

  String _battery = "获取电池电量";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
             _battery
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _getBatteryLevel,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  Future<Null> _getBatteryLevel() async {
    String battery = "获取电池电量";

    try {
      int result = await platform.invokeMethod("getBatteryLevel");

      battery = "获取到的电量 $result";
    } on PlatformException catch (e) {


      // 未获取到电池电量
      battery = "未获取到电池电量";


    }


    setState(() {
      _battery = battery;
    });
  }
}

其实 这篇文章主要就是记录了 fragment 和flutter 的交互

此处写了一个方法 通过Flutter 中的方法来调用 android 中的方法 我是通过 android 中添加一个Fragment 来加载Flutter 的界面

先上代码 --> Activity

package com.storm.stormandflutterdemo

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import com.storm.stormandflutterdemo.Utils.LogUtils
import com.storm.stormandflutterdemo.flutterplugin.BatteryPlugin
import io.flutter.embedding.android.FlutterFragment
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor

class CustomActivity : FragmentActivity() {


    companion object {


        val TAG_FLUTTER_FRAGMENT = "flutter_fragment"

        val TAG = "CustomActivity"

        fun startSelf(activity: Activity) {

            var intent = Intent(activity, CustomActivity::class.java)
            activity.startActivity(intent)
        }
    }

    var flutterFragment: FlutterFragment? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_custom)
        startFlutter()
    }


    private fun startFlutter() {


        initPlugin()
        
        
        var fm = supportFragmentManager


        flutterFragment =
            fm.findFragmentByTag(MainActivity.TAG_FLUTTER_FRAGMENT) as FlutterFragment?


        if (flutterFragment == null) {


            var newFlutterFragment =  FlutterFragment.withCachedEngine("my_flutter").build<FlutterFragment>()


            flutterFragment = newFlutterFragment


            fm.beginTransaction()
                .add(R.id.fl_content, flutterFragment!!, MainActivity.TAG_FLUTTER_FRAGMENT).commit()



            LogUtils.d(TAG, "是否未null ? -->  ${null == flutterFragment}")



            flutterFragment!!.onAttach(this)

        }


    }


    private fun initPlugin() {



        var flutterEngine = FlutterEngine(this)

        flutterEngine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault())

        FlutterEngineCache.getInstance()
            .put("my_flutter",flutterEngine)

        BatteryPlugin.registerWith(flutterEngine)


    }


    override fun onResume() {
        super.onResume()

    }
}

此处 有个问题 就是我当时再创建FlutterFragment 总是爆红 开始的时候 发现导入的包不一样

FlutterFragment 用的是 v4包,而我用的是androidx 的包, 其实我可以改成v4包的 但是考虑到以后 api 29 以后 的 会维护androidX 而放弃androd v4 v7 各个版本的维护 所以自己就钻牛角尖, 索性都换成androdX 的去寻找方法

查过来查过去 FlutterFragment 的继承的Fragment 始终是v4 包下的Fragment 即使我删除了这个FlutterModule 重新创建的开始勾选了androidX 还是 v4包 , 在Android项目中 中 还是爆红...

妈蛋 结果就是 我试着运行 竟然正常运行 ... enen . 这边还爆红 也Flutter 加载出来了 .........###Fuck说

另一方面就是 Flutter1.12 以后更换了api 因为我也是最近开始看 , 有的地方不是很懂 各位大神觉得有什么不对的地方 留言一起讨论共同进步, 之前的如果要加载插件 , 就是在当前的activity 或者是fragement 中 注册 传入 PluginRegistry.Registrar 记得之前的 FlutterActivity 或者FlutterFragment 都实现了 这个接口, 所以直接传入this 拿到activity 的引用 , 不过在1.12 之后 改成了新的 直接 传入 FlutterEngine 来注册交互的插件。

其实initPlugin 这个方法 放入 Application 中也可以 通过一个tag , 然后 创建 FlutterFragment 的时候通过tag 来创建 , 然后插件注册

插件-->

package com.storm.stormandflutterdemo.flutterplugin

import androidx.annotation.Keep
import androidx.annotation.NonNull
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry
import io.flutter.plugin.common.MethodChannel
import java.lang.reflect.Method

/**
 *
 * @author storm_z
 * @date @{DATE}
 * @email [email protected]
 *
 * @Describe
 */
@Keep
object BatteryPlugin {

    public const val CHANNEL  = "com.battery.io/battery"




    fun registerWith(@NonNull flutterEngine: FlutterEngine){

        val shimPluginRegistry = ShimPluginRegistry(flutterEngine)

        val registrar = shimPluginRegistry.registrarFor("com.battery.io")

        val context = registrar.activeContext()

        val channel = MethodChannel(registrar.messenger(), CHANNEL)

        var value = 0 ;
        channel.setMethodCallHandler { call, result ->



            when(call.method){

                "getBatteryLevel" -> {

                    value += 20
                    result.success(value)
                }
            }
        }


    }
}

这次 主要是想要吧 Flutter 放入到 android 的 Fragment 中来尝试 , 看了很多博客 和官方文档 都是介绍怎么在 Fragment 中使用但是交互方面 都是1.12 版本之前的 , 或者说在 FlutterActivity 中的 , 所以 自己在捣鼓出来之后就记录一下 然后有什么问题 一起讨论 共同进步 很少写这个 以后慢慢规范 . 去尝试 FlutterView 了 ......


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK