Administrator
发布于 2024-07-11 / 90 阅读
0
0

Flutter调用原生iOS及Android

本地环境如下:

Flutter 2.2.0-10.1.pre • channel beta

Dart 2.13.0

之前创建了一个Flutter项目,项目中需要判定手机蓝牙是否打开,这时候就需要调用原生代码,但是在网上查看资料时候发现很多资料过时或不能用,原因应该是电脑上的Flutter版本比较高,搞定之后就记录一下。

项目创建时选择了支持Kotlin及Swift,所有项目整体的结构可能不太一样

Flutter端代码

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

class BeControlPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text('被控制端'),
      ),
      body: TestWidget()
    );
  }
}

class TestWidget extends StatefulWidget {
  @override
  _TestIosWidgetState createState() => _TestIosWidgetState();
}

class _TestIosWidgetState extends State<TestWidget> {

  // 调用原生相关代码
  Future runMethod() async{
    // 自定义的通道且名字为test,在原生中会使用到,只要对的上通道名称才可调用相关方法
    const platform = const MethodChannel('test');
    var result;
    try{
      // Flutter提供三种方法与原生交互
      // MethodChannel  用于 Flutter 与 原生平台之间函数的互相调用
      // BasicMessageChannel    它传递的是字节数组,使用时自定义编解码器
      // EventChannel   用于 Flutter 与 原生平台之间事件的通信
      // 这里使用的是MethodChannel方式
      result = await platform.invokeMethod('isHavePermission');
      return Future.value(result);
    } on PlatformException catch (e){
      return Future.error(e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: FlatButton(
        onPressed: () async{
          // 点击按钮后通过原生方法获取到返回值
          var futureValue = await runMethod();
          // 拿到返回值后弹出框显示返回值
          return showDialog(context: context, builder: (context){
            return AlertDialog(
              content: Text(
                futureValue,
                textAlign: TextAlign.center,
              ),
            );
          });
        },
        child:
          Text(
              '信我,得永生',
              style: TextStyle(fontSize: 18.0),
          ),
        color: Colors.red,
        textColor: Colors.white,
        ),
    );
  }
}

iOS端

  1. 新建OC文件,命名为FlutterNativePlugin,继承与NSObject,.h文件如下:
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>

NS_ASSUME_NONNULL_BEGIN

@interface FlutterNativePlugin : NSObject<FlutterPlugin>

@end

NS_ASSUME_NONNULL_END      
  1. 在AppDelegate里注册工具类
 import UIKit
 import Flutter

 @UIApplicationMain
 @objc class AppDelegate: FlutterAppDelegate {
   override func application(
     _ application: UIApplication,
     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
   ) -> Bool {
     GeneratedPluginRegistrant.register(with: self)
     FlutterNativePlugin.register(with: self.registrar(forPlugin: "FlutterNativePlugin") as! FlutterPluginRegistrar)
     return super.application(application, didFinishLaunchingWithOptions: launchOptions)
   }
 }

Android端

Android端多说一点,由于在Flutter1.12后Flutter官方舍弃了io.flutter.app.FlutterActivity,所以网上很多代码就可能无法使用了

  1. 新建后的Flutter项目Android目录各种标红

    这时候鼠标随便打开Android目录下的某一个文件,点击代码编辑区上方的

    使用Android打开会下载一些依赖,并且也无标红了

  2. 编写MainActivity代码:

    很多文章中写的,如https://www.jianshu.com/p/310c28abc9f3文中的代码:

    他导入的是io.flutter.app.FlutterActivity头文件,导入此文件这样写不会有问题,而且相关代码写在onCreate方法中,但是在Flutter1.12后此方法废弃,新建的项目均导入的是io.flutter.embedding.android.FlutterActivity头文件,详情见官方文档,所以,如果你的Flutter版本大于1.12,则正确的代码为:

package com.imowfms.flutter_app

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {
    private val channel = "test"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger,channel)
                .setMethodCallHandler { call, result ->
                    // 你的代码
                    if (call.method == "isHavePermission"){
                        result.success("有了-Android")
                    }else{
                        result.notImplemented()
                    }
                }
    }
}

此时,三部分的代码都完成了,运行看看效果

  • Android

  • iOS


评论