Skip to content

Refactor the way Android Plugins are included #29328

@dnfield

Description

@dnfield

Today, we include plugins directly as subprojects. This causes problems when there are dependency conflicts, and tools like Jetifier that should be able to help us resolve them aren't set up to run on subprojects (they assume the project will more or less internally consistent). In particular, this has caused problems for Android X (#23586 #27106). It's also meaningful for Add2App use cases, where we have customers who want to distribute Flutter in a more modular fashion (e.g. as AARs rather than as source code). The main concern right now is solving the Android X headaches though. The following dependencies in pubspec.yaml would cause an android project to fail to build because of such conflicts:

dependencies:
  shared_preferences: any
  flutter:
    sdk: flutter
  camera: 0.2.6
  firebase_auth: any

A quick POC resolves a lot of these problems:

  • Include plugins as includeBuild in settings.gradle rather than as a subproject.
  • Specify dependencies on plugins in the dependencies section of app/build.gradle.
  • For each plugin, make sure it has all of its dependencies specified correctly in its build.gradle (including a dependency on flutter.jar).

For example:

Change android/settings.gradle's plugins.each to:

plugins.each { name, path ->
    includeBuild "$path/android"
}

Remove the subprojects from android/build.gradle and align the gradle plugin with other plugins' requirements:

...
        classpath 'com.android.tools.build:gradle:3.3.1'
...
rootProject.buildDir = '../build'
// subprojects {
//     project.buildDir = "${rootProject.buildDir}/${project.name}"
// }
// subprojects {
//     project.evaluationDependsOn(':app')
// }
...

Add the right dependencies to android/app/build.gradle:

dependencies {
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'io.flutter.plugins.sharedpreferences:shared_preferences:1.0.0'
    implementation 'io.flutter.plugins.firebase.core:firebase_core:1.0.0'
    implementation 'io.flutter.plugins.firebaseauth:firebase_auth:1.0.0'
    implementation 'io.flutter.plugins.camera:camera:1.0.0'
}

This also requires changes in each plugin's build.gradle, at a minimum:

dependencies {
    api files('/Path/to/flutter/bin/cache/artifacts/engine/android-arm/flutter.jar')
}

The includeBuild method will get Gradle to build all these projects with one command, but is not ideal because it requires that all projects use the same gradle plugin version.

To remedy this, we should teach the flutter tool and/or flutter.gradle how to build Android plugins directly. This may end up including updating the plugin's gradle configuration so that it more correctly specifies its dependencies, including a dependency on flutter.jar from the framework/engine. We need to figure out if we can do that purely through the DSL or whether we'd actually have to generate a new build.gradle file for these purposes.

/cc @mklim @amirh @matthew-carroll @csells

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: existing-appsIntegration with existing apps via the add-to-app flowpackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyt: gradle"flutter build" and "flutter run" on AndroidtoolAffects the "flutter" command-line tool. See also t: labels.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions