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);
}
}
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.