Skip to content

[Federated Plugins] Provide a way to override a default/endorsed platform implementation #80374

Description

@ryanheise

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.

Activity

  1. stuartmorgan-g commented on Apr 13, 2021

    @stuartmorgan-g
    Contributor

    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.

  2. ryanheise commented on Apr 14, 2021

    @ryanheise
    Author

    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?

  3. added
    in triagePresently being triaged by the triage team
    c: proposalA detailed proposal for a change to Flutter
    toolAffects the "flutter" command-line tool. See also t: labels.
    and removed
    in triagePresently being triaged by the triage team
    on Apr 14, 2021
  4. ryanheise commented on Apr 14, 2021

    @ryanheise
    Author
    /// 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_audio could 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".

  5. ryanheise commented on May 28, 2022

    @ryanheise
    Author

    Is the way to override an endorsed platform implementation now documented anywhere in the latest up-to-date documentation on federated plugins?

  6. stuartmorgan-g commented on May 31, 2022

    @stuartmorgan-g
    Contributor

    No; we're unlikely to formally document this until it works for native code as well, otherwise it will be very confusing.

  7. added
    a: pluginsSupport for writing, building, and running plugin packages
    on Feb 9, 2023
  8. 5 remaining items

  9. stuartmorgan-g commented on Oct 17, 2023

    @stuartmorgan-g
    Contributor

    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.

  10. Gustl22 commented on Oct 18, 2023

    @Gustl22
    Contributor

    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 the flutter params, 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.

  11. Gustl22 commented on Oct 19, 2023

    @Gustl22
    Contributor

    Quick update to an implementation, which works for me by removing the default plugin as follows:

  12. Gustl22 commented on Oct 22, 2023

    @Gustl22
    Contributor

    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

  13. added a commit that references this issue on Jul 11, 2024
    d55a5f9
  14. github-actions commented on Jul 25, 2024

    @github-actions

    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 -v and a minimal reproduction of the issue.

  15. locked as resolved and limited conversation to collaborators on Jul 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: pluginsSupport for writing, building, and running plugin packagesteam-toolOwned by Flutter Tool teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-toolTriaged by Flutter Tool team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions