flutter_plugin_annotations 0.0.9

flutter_plugin_annotations is part of the project plugin_gen.flutter and holds the annotations that should be placed in the dependencies bloc of your pubspec.yaml

@FlutterPlugin() #

This annotation should be applied to abstract classes that represents a plugin.

  • As the annotated class will generate a part file, you should add after the file imports part '${MY_CLASS_FILE_NAME}.g.dart'; to make the project work.

For instance, a file platform_plugin.dart, should have something like:

part 'platform_plugin.g.dart';

@FlutterPlugin()
abstract class PlatformPlugin {
 
  PlatformPlugin();

}

@MethodChannelFutures() #

MethodChannelFutures annotation should be placed at your plugin class together with FlutterPlugin, to enable the usage of methods and getters that return a Future<T> to have it's calls mapped into a MethodChannel.

  • As the annotated class will generate a part file that access flutter framework, you need to add the import import 'package:flutter/services.dart'; to the top of your class file.

You can see a class example here.

MethodChannelFutures.channelName #

If MethodChannelFutures.channelName has no path replacements: The plugin will have a static const MethodChannel that will be shared across all instances of the plugin.

If MethodChannelFutures.channelName has any String replacements, i.e platform_channel_with_id/{id}, the generated plugin will have a constructor with a String named parameter id that will be replaced in the given String when creating a new instance of the class. This may be useful when allocating native resources.

For instance:

part 'platform_plugin.g.dart';

@FlutterPlugin()
@MethodChannelFutures(channelName: 'method_channel_with_id/{id}')
abstract class PlatformPlugin {

  PlatformPlugin();
  
  Future<String> platform();

  factory PlatformPlugin(String id) {
    return _$PlatformPlugin(id: id);
  }
}

@OnMethodCall #

OnMethodCall is used to register a method as a callback at MethodChannel.setMethodCallHandler, so It needs to be applied to a plugin that uses @MethodChannelFutures in the class.

To make OnMethodCall work, the function where it is applied should:

  • return void.
  • Have all parameters as functions of signature Future<T> Function(R variable). Where T e R are any type supported by this project and variable will be used to map which method was called from the native side.

For instance:

part 'my_test_plugin.g.dart';

typedef Future<MyOtherData> OnData(MyData data);

@MethodChannelFutures(channelName: "my channel name")
abstract class PlaftormPlugin {
  
  PlaftormPlugin();

  @OnMethodCall()
  void configure({@required OnData onData});

}

Above we use a typedef to define a function OnData and use it as parameter to configure method. The generated code will use onData (The variable name in configure method) as a method name for the native side to call. So, when the the native side calls something like :

  
  // kotlin
  methodChannel.invokeMethod("onData", myData.toJson(), object : Result {
      override fun error(p0: String?, p1: String?, p2: Any?) {}

      override fun success(p0: Any?) {
        val other = MyOtherData.fromJson(p0!!)
        println(other)
      }

      override fun notImplemented() {}
    })

It will call the method OnData if it was registered.

How to register, you ask?


  @override
  void initState() {
    super.initState();
    widget.plugin.configure(onData: onData);
  }
  
  Future<MyOtherData> onData(MyData data) async {
    setState(() {
      onConfigureData = data.toString();
    });

    // This data goes to native side.
    return MyOtherData(otherData: "some other data");;
  }

  @override
  void dispose() {
    widget.plugin.configure(onData: null);
    super.dispose();
  }

@EventChannelStream() #

EventChannelStream should be applied to getters of type Stream<T>.

  • As the annotated class will generate a part file that access flutter framework, you need to add the import import 'package:flutter/services.dart'; to the top of your class file.

  • EventChannelStream.channelName does NOT support methods or path replacements.

Each getter annotated with EventChannelStream will generate a new static const EventChannel and a private Stream<dynamic> that will be reused for all readings done in a given getter.

For instance:

part 'platform_plugin.g.dart';

@FlutterPlugin()
abstract class PlatformPlugin {

  PlatformPlugin();
  
  @EventChannelStream('my event channel')
  Stream<String> get platform;

}

will generate:

part of 'platform_plugin.dart';

class _$PlatformPlugin extends PlatformPlugin {
  
  _$PlatformPlugin() : super();
  
  static const EventChannel _platformEventChannel =
      const EventChannel('my event channel');

  final Stream<dynamic> _platform = _platformEventChannel.receiveBroadcastStream();

  @override
  Stream<String> get platform {
    return _platform.map((result) {
      return retult;
    });
  }
}

@SupportedPlatforms() #

SupportedPlatforms, when applied to the same class as FlutterPlugin will work as a filter when declaring more restrict usage in a method or getter.

  • As this annotation will generate code that relies in dart:io, you should add the import import 'dart:io'; to the top of your class file.

Methods/getters annotated with SupportedPlatforms with a non empty list of SupportedPlatforms.only will generate code to raise exceptions for each platform not listed in the only field.

For instance:

part 'platform_plugin.g.dart';

@FlutterPlugin()
@SupportedPlatforms(
  only: [
    SupportedPlatform.IOS,
    SupportedPlatform.Android,
  ],
)
@MethodChannelFutures(channelName: 'platform_channel_with_id')
abstract class PlatformPlugin {
 
  PlatformPlugin();
 
  @SupportedPlatforms(
    only: [SupportedPlatform.Android],
  )
  Future<String> platform();
}

will generate:

part of 'platform_plugin.dart';
  
  @override
  Future<String> platform() async {
    if (Platform.isIOS)
      throw UnsupportedError('Functionality platform is not available on IOS.');

    final result = await _methodChannel.invokeMethod<String>('platform');
    return result;
  }
 

but if you remove the annotation from the class

part of 'platform_plugin.dart';

@FlutterPlugin()
@MethodChannelFutures(channelName: 'platform_channel_with_id')
abstract class PlatformPlugin {
  
  PlatformPlugin();
  
  @SupportedPlatforms(
    only: [SupportedPlatform.Android],
  )
  Future<String> platform();

}

will generate:

  @override
  Future<String> platform() async {
    if (Platform.isIOS)
      throw UnsupportedError('Functionality platform is not available on IOS.');

    if (Platform.isWindows)
      throw UnsupportedError(
          'Functionality platform is not available on Windows.');

    if (Platform.isFuchsia)
      throw UnsupportedError(
          'Functionality platform is not available on Fuchsia.');

    if (Platform.isLinux)
      throw UnsupportedError(
          'Functionality platform is not available on Linux.');

    if (Platform.isMacOS)
      throw UnsupportedError(
          'Functionality platform is not available on MacOS.');

    final result = await _methodChannel.invokeMethod<String>('platform');
    return result;
  }

If your plugin is meant to run just in Android and IOS and you want to have a cleaner code generated, use SupportedPlatforms in the class.

[0.0.9]

  • Added OnMethodCall annotation.
  • Updated documentation.

[0.0.8]

  • Included assert tests.

Breaking changes

  • all annotations constructor parameters need to be != null, otherwise it will throw an exception.

[0.0.7]

  • Updated documentation.
  • Included example.

Breaking changes

  • Added FlutterPlugin annotation.
  • Renamed MethodCallPlugin to MethodChannelFutures.

[0.0.6]

  • Added EventChannelStream annotation.
  • Updated documentation.

[0.0.5]

  • Added support to filter which platforms the plugin has support.
  • Included README.md

[0.0.4]

  • Removed Flutter dependency.
  • Added SupportedPlatforms annotation.

[0.0.3]

  • Downgrade meta lib version.

[0.0.2]

  • Made channelName required.
  • Included documentation.
  • Included simple test.

[0.0.1]

  • Initial release.

example/README.md

platform_plugin #

A new Flutter plugin.

Getting Started #

This project is a starting point for a Flutter plug-in package, a specialized package that includes platform-specific implementation code for Android and/or iOS.

For help getting started with Flutter, view our online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_plugin_annotations: ^0.0.9

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_plugin_annotations/flutter_plugin_annotations.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
36
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
66
Learn more about scoring.

We analyzed this package on Aug 20, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:flutter_plugin_annotations/flutter_plugin_annotations.dart.

Maintenance suggestions

Package is pre-v0.1 release. (-10 points)

While nothing is inherently wrong with versions of 0.0.*, it might mean that the author is still experimenting with the general direction of the API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev.68.0 <3.0.0
meta ^1.1.6 1.1.7
Dev dependencies
test ^1.6.5