Repository navigation
[Federated Plugins] Provide a way to override a default/endorsed platform implementation #80374
Description
Activity
The PR for #52267 has logic to handle this for Dart plugin registration; we should be able to extend that same logic to any native plugin implementation.
By my understanding, that PR describes configuration changes to the plugins themselves, but I'm trying to understand what an app developer would need to configure to choose the overriding platform. Currently we would do something like this in the app's pubspec:
dependencies: just_audio: just_audio_audiokit_ios:
where just_audio already includes a default iOS implementation, and each of those two packages would define . What mechanism controllable by the app itself can prevent the default implementation from loading? I assumed the plugin class is a property of the plugin rather than the app, but would the app need to define the plugin class for each override plugin it uses, in addition to adding the package dependency?
- addedin triagePresently being triaged by the triage teamPresently being triaged by the triage teamc: proposalA detailed proposal for a change to FlutterA detailed proposal for a change to FluttertoolAffects the "flutter" command-line tool. See also t: labels.Affects the "flutter" command-line tool. See also t: labels.and removedin triagePresently being triaged by the triage teamPresently being triaged by the triage team
on Apr 14, 2021 /// Resolves the platform implementation for Dart-only plugins. /// /// * If there are multiple direct pub dependencies on packages that implement the /// frontend plugin for the current platform, fail. /// * If there is a single direct dependency on a package that implements the /// frontend plugin for the target platform, this package is the selected implementation. /// * If there is no direct dependency on a package that implements the frontend /// plugin for the target platform, and the frontend plugin has a default implementation /// for the target platform the default implementation is selected. /// * Else fail. /// /// For more details, https://flutter.dev/go/federated-plugins.Thanks, I think I understand the algorithm.
I was slightly confused by the wording above, because
just_audiocould be considered as providing a default iOS implementation itself, but it could also be considered as being a "direct pub dependency that implements the frontend plugin for the current platform".Is the way to override an endorsed platform implementation now documented anywhere in the latest up-to-date documentation on federated plugins?
No; we're unlikely to formally document this until it works for native code as well, otherwise it will be very confusing.
Reacted by August- addedP2Important issues not at the top of the work listImportant issues not at the top of the work list
on May 31, 2022 - addeda: pluginsSupport for writing, building, and running plugin packagesSupport for writing, building, and running plugin packages
on Feb 9, 2023 5 remaining items
Are there tendencies, how this will be approached?
The comments above yours describe how this will be implemented.
You already wrote two solutions here, although they do not exclude each other and the second one does not solve the problem of this thread directly: #81650 (comment)
My comment there is not about solutions to this issue; it's about solving a different problem.
But still, I haven't looked into the code and don't know if it's actually possible to prevent a native plugin from registering
This will, when implemented, cause the overridden implementation not to be registered.
The comments above yours describe how this will be implemented.
Yes, now I got it. I just never saw how this actually is implemented in the
pubspec.yaml. But I found also the exact code line now.So in dart it just works by adding a direct dependency to the developers application, it automatically detects if it has an implementation of an existing plugin package. And then prefer the direct dependency over the default one.
I was always the opinion one needs to actually declare the plugin override in the pubspec via theflutterparams, but that isn't the case.And it's already described in words here for non-endorsed plugins:
name: example dependencies: my_plugin: ^0.0.1 my_plugin_android_alternative: ^0.0.1
So the registration for the alternative native plugin is already working, just the deregistration of the default one is not yet. I may have a deeper look into this.
Quick update to an implementation, which works for me by removing the default plugin as follows:
- Needs to add filtering / resolving with the mentioned concept to ensureReadyForPlatformSpecificTooling or more specifically to refreshPluginsList as these files are read by the native implementations to determine their dependencies.
- Also may needs filtering in injectPlugins / injectBuildTimePluginFiles to avoid them to generate their dart registration files (but not quite sure).
- Depends on [flutter_tools] Migrate platforms away from .flutter-plugins #48918 (Android missing only) to ensure the plugins are removed on the specific platform only and not for all platforms (which can not be distinguished in the old
.flutter-pluginsfile) if it has more than one native implementation (at least I think that could be possible).
I created a PR now (#137040) which aims to solve this issue. It's not ready yet (missing parts are listed in the PR description), but maybe one can comment, if it's leading in the right direction and one can have a look in the TODOs in the code.
Hope it can help to solve this issue :D
- added a commit that references this issue
on Jan 22, 2024 - added a commit that references this issue
on Feb 26, 2024 - added a commit that references this issue
on Mar 7, 2024 - added a commit that references this issue
on Apr 5, 2024 - added a commit that references this issue
on Apr 22, 2024 - added a commit that references this issue
on May 7, 2024 - added a commit that references this issue
on Jul 11, 2024 This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.- locked as resolved and limited conversation to collaborators
on Jul 25, 2024
Use case
It would be desirable for a federated plugin to have a default implementation for iOS, either inside the plugin or an endorsed separate package, and to then allow apps to choose an alternative platform implementation to override that default. E.g. for just_audio, we will have a default AVQueuePlayer-based implementation, but an alternative AudioKit implementation and an alternative VLC implementation.
However, I don't think this override ability has been added to Flutter yet, although it was implied in the design doc.
What happens instead is that the generated plugin registrant will automatically add both the default/endorsed plugin AND any additional plugin the app adds to their pubspec with the intention of overriding the default. Since both are listed, alphabetical order will dictate which one is effective.
Proposal
Currently a platform implementation is endorsed by adding its dependency to the plugin's front-end and so it's going to get added to the generated plugin registrant regardless of any attempt to override it.
I'm not sure on the best solution, but maybe either the mechanism to endorse an implementation needs to be something other than a normal dependency, or otherwise the flutter tool should add some special cases to the code that generates the generated plugin registrant to detect overrides and avoids adding both the override and the default.