Flutter federated android plugin - only see interface method

391 views Asked by At

Running the simplest example in a flutter android plugin(federated), I keep getting:

MissingPluginException(No implementation found for method getPlatformVersion on channel plugins.mydomain.com/my_package)

It is like it only sees the interface, and not the implementation for the Android plugin?

This is never called in Android dart implementation(see: Android dart plugin implementation further down)

  static void registerWith() {
    MyPackagePlatform.instance = MyPackageAndroid();
  }

Git clone
You can just git clone the federated plugin, and do melos bootstrap, then you should be able to see the error running the android example.

git clone https://github.com/JCzz/my_package

If you use Android Studio just edit the path for the configuration, and run my_package/example, then you should be good to go.

Teaser

package pubspec.yaml:

name: my_package_android
description: A new flutter plugin project.
version: 0.0.1
homepage:

environment:
  sdk: ">=2.16.2 <3.0.0"
  flutter: ">=2.5.0"

dependencies:
  flutter:
    sdk: flutter
  my_package_platform_interface:
    path: ../my_package_platform_interface

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^1.0.0

flutter:
  plugin:
    implements: my_package
    platforms:
      android:
        package: com.example.my_package_android
        pluginClass: MyPackageAndroidPlugin
        dartPluginClass: MyPackageAndroid

Interface package:

abstract class MyPackagePlatform extends PlatformInterface {
  MyPackagePlatform() : super(token: _token);

  static MyPackagePlatform _instance = MethodChannelMyPackage();

  static final Object _token = Object();

  static MyPackagePlatform get instance => _instance;

  Future<String?> get platformVersion async {
    throw UnimplementedError('getPlatformVersion property has not been implemented.');
  }

}

Android dart plugin implementation:

import 'dart:async';

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

const MethodChannel _channel = MethodChannel('plugins.mydomain.com/my_package_android');

class MyPackageAndroid extends MyPackagePlatform {

  /// Registers this class as the default instance of [UrlLauncherPlatform].
  static void registerWith() {
    MyPackagePlatform.instance = MyPackageAndroid();
  }

  @override
  Future<String?> get platformVersion async {
    final String? version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  @override
  Future<bool> canLaunch(String url) async {
    final bool canLaunchSpecificUrl = await _canLaunchUrl(url);
    if (!canLaunchSpecificUrl) {
      final String scheme = _getUrlScheme(url);

      if (scheme == 'http' || scheme == 'https') {
        return await _canLaunchUrl('$scheme://flutter.dev');
      }
    }
    return canLaunchSpecificUrl;
  }

  Future<bool> _canLaunchUrl(String url) {
    return _channel.invokeMethod<bool>(
      'canLaunch',
      <String, Object>{'url': url},
    ).then((bool? value) => value ?? false);
  }

  String _getUrlScheme(String url) {
    final int schemeEnd = url.indexOf(':');
    if (schemeEnd == -1) {
      return '';
    }
    return url.substring(0, schemeEnd);
  }

}

Android native plugin:

package com.example.my_package_android;

import android.app.Activity;
import android.util.Log;

import androidx.annotation.NonNull;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
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.embedding.engine.plugins.activity.ActivityAware;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/** MyPackageAndroidPlugin */
public class MyPackageAndroidPlugin implements FlutterPlugin, MethodCallHandler {
  private static final String TAG = "MethodCallHandlerImpl";

  private MethodChannel channel;

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "plugins.mydomain.com/my_package_android");
    channel.setMethodCallHandler(this);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }
   
}
1

There are 1 answers

0
Chris G. On

Re-installed/created a new device simulator and did flutter clean both in the app-facing package and in the example app - and now it works.