美文网首页
Flutter插件开发

Flutter插件开发

作者: SiriDx | 来源:发表于2019-11-15 09:44 被阅读0次

    创建插件目录

    flutter create -i objc -a java --template=plugin demo
    
    -i, 表示指定iOS的语言, objc, swift
    -a, 表示指定安卓的语言, java, kotlin
    

    通过上面命令,创建一个名为demo的plugin模板, 并生成以下目录结构

    目录结构

    - android // 插件相关 Android 代码
    - ios // 插件相关 iOS 代码
    - lib // 插件相关 Dart 代码
    - example // 示例项目, 用于调试当前开发的插件
    - pubspec.yaml // 插件配置文件
    

    example目录

    example目录, 是一个示例项目, 用于调试当前开发的插件

    在example/lib/main.dart中, 默认生成一些示例代码. 代码如下:

    import 'package:flutter/material.dart';
    import 'dart:async';
    import 'package:flutter/services.dart';
    import 'package:demo/demo.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      String _platformVersion = 'Unknown';
    
      @override
      void initState() {
        super.initState();
        initPlatformState();
      }
    
      Future<void> initPlatformState() async {
        String platformVersion;
        try {
          platformVersion = await Demo.platformVersion;
        } on PlatformException {
          platformVersion = 'Failed to get platform version.';
        }
    
        if (!mounted) return;
    
        setState(() {
          _platformVersion = platformVersion;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Plugin example app'),
            ),
            body: Center(
              child: Text('Running on: $_platformVersion\n'),
            ),
          ),
        );
      }
    }
    

    示例中的代码, Demo.platformVersion, 实际上是调用了lib目录中, Demo类的get方法platformVersion, 也就是我们写的插件代码

    lib目录

    lib目录, 主要用来存放, 开发的插件所需要的dart代码

    在lib/demo.dart, 中可以找到默认生成的示例代码, 代码如下:

    import 'dart:async';
    import 'package:flutter/services.dart';
    
    class Demo {
      static const MethodChannel _channel =
          const MethodChannel('demo');
    
      static Future<String> get platformVersion async {
        final String version = await _channel.invokeMethod('getPlatformVersion');
        return version;
      }
    }
    
    

    以上代码, 创建了一个名字为demo的MethodChannel对象, 并提供一个get platformVersion方法, 在该方法中调用invokeMethod方法, 去调用原生代码中, 名字为getPlatformVersion的方法.

    MethodChannel

    flutter与原生的交互, 可以通过MethodChannel来实现, MethodChannel是双向的, 通过它可以在flutter中调用原生代码, 也可以在原生代码调用flutter代码

    ios目录

    ios目录, 主要用来存放, 开发的插件所需要的iOS代码

    在ios目录中, ios/Classes/DemoPlugin.m, 中可以找到getPlatformVersion对应的原生代码, 代码如下:

    #import "DemoPlugin.h"
    
    @implementation DemoPlugin
    + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
      FlutterMethodChannel* channel = [FlutterMethodChannel
          methodChannelWithName:@"demo"
                binaryMessenger:[registrar messenger]];
      DemoPlugin* instance = [[DemoPlugin alloc] init];
      [registrar addMethodCallDelegate:instance channel:channel];
    }
    
    - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
      if ([@"getPlatformVersion" isEqualToString:call.method]) {
        result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
      } else {
        result(FlutterMethodNotImplemented);
      }
    }
    
    @end
    

    android目录

    android目录, 主要用来存放, 开发的插件所需要的android代码

    在android目录中, android/src/main/java/com/example/demo/DemoPlugin.java, 中可以找到getPlatformVersion对应的原生代码, 代码如下:

    package com.example.demo;
    
    import io.flutter.plugin.common.MethodCall;
    import io.flutter.plugin.common.MethodChannel;
    import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
    import io.flutter.plugin.common.MethodChannel.Result;
    import io.flutter.plugin.common.PluginRegistry.Registrar;
    
    /** DemoPlugin */
    public class DemoPlugin implements MethodCallHandler {
      /** Plugin registration. */
      public static void registerWith(Registrar registrar) {
        final MethodChannel channel = new MethodChannel(registrar.messenger(), "demo");
        channel.setMethodCallHandler(new DemoPlugin());
      }
    
      @Override
      public void onMethodCall(MethodCall call, Result result) {
        if (call.method.equals("getPlatformVersion")) {
          result.success("Android " + android.os.Build.VERSION.RELEASE);
        } else {
          result.notImplemented();
        }
      }
    }
    

    原生代码

    原生代码中, 也都创建一个名为demo的MethodChannel对象. (与lib目中的dart代码中的MethodChannel名字一致).

    通过注册, 监听该channel的回调. 在回调中通过判断call.method的值, 来区分flutter中调用的哪个方法.

    如示例中判断是否等于getPlatformVersion, 并在当中执行对应的原生代码, 获取设备相关的系统版本.

    问题

    在iOS中运行示例时, 可能会出现Sending crash report to Google. 查看打印可以发现

    An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=22):
    Failed to install the requested application
    The application's Info.plist does not contain CFBundleVersion.
    Ensure your bundle contains a CFBundleVersion.
    

    出现的原因是VersionBuild内容为空:

    Snip20191115_2.png

    填写上对应的版本号即可.

    相关文章

      网友评论

          本文标题:Flutter插件开发

          本文链接:https://www.haomeiwen.com/subject/nuigyctx.html