Skip to content

android.lifecycle resolution can be trivially broken by transitive dependencies in Android libraries #43383

@mklim

Description

@mklim

Our attempts to solve v2 lifecycle transitive dependency issues are incomplete. There can still trivially be crashes from the wrong version. This was discovered recently by @goderbauer when running module_test failed on stable with the latest plugin versions.

Background

The v2 Android Embedding brings in multiple dependencies on Android Support libraries. At runtime Gradle will fail to build if a project appears to require different versions of the same library, which is trivial to happen in a Flutter context because plugins can and do include their own versions. In addition to that, plugins that use the v2 embedding need to include their own versions in order to compile against the engine at all.

We are generally trying to work around this by asking Flutter plugins developers to point to a pub package that includes Lifecycle so that they're forced to resolve to the same version. https://pub.dev/packages/flutter_plugin_android_lifecycle

Immediate problem

Right now module templates created and built with stable will fail to compile if including a v2 embedding plugin because of this issue.

  1. flutter channel stable && flutter create -t module foo
  2. Include any of the migrated flutter/plugins as a dependency in pubspec.yaml. device_info, shared_preferences, etc.
  3. flutter build apk

The build will fail with "Android dependency 'android.arch.lifecycle:runtime' has different version for the compile (1.1.0) and runtime (1.1.1) classpath.".

Root cause and larger issue

The module template is failing on master because its Java code transitively includes a conflicting lifecycle version through com.android.support:appcompat.

+--- com.android.support:appcompat-v7:27.1.1
|    +--- com.android.support:support-annotations:27.1.1
|    +--- com.android.support:support-core-utils:27.1.1
|    |    +--- com.android.support:support-annotations:27.1.1
|    |    \--- com.android.support:support-compat:27.1.1
|    |         +--- com.android.support:support-annotations:27.1.1
|    |         \--- android.arch.lifecycle:runtime:1.1.0
[...]
\--- project :shared_preferences
|         +--- android.arch.lifecycle:runtime:1.1.1 (*)

This is a larger existential issue than just the module template having conflicts and needing to be updated.

  • If Java dependencies can cause conflicts, that means that our approach of depending on a pub flutter_plugin_android_lifecycle package will not work in all cases. We don't have a current approach to try and prevent this.
  • It will be trivially easy and likely for add to app developers to hit conflicts in this way. com.android.support:appcompat is a very common dependency for typical Android app development.

Immediate mitigation

This means that strictly speaking none of the migrated plugins are compatible with stable and should probably be rolled back. /cc @matthew-carroll @amirh If we had a fix we could forward fix them instead, but I don't know if there is an immediate short term one.

Potential long term fixes

I don't have any solid ideas here yet.

There is a Gradle script to force apps to use a given version for a package. We could add that in, but I don't like the idea of deciding dependency resolution in all cases like this.

/cc @blasten

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: existing-appsIntegration with existing apps via the add-to-app flowc: crashStack traces logged to the consoleengineflutter/engine related. See also e: labels.p: firebaseFirebase pluginspackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyt: gradle"flutter build" and "flutter run" on Android

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions