Repository navigation
Refactor the way Android Plugins are included #29328
Description
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: anyA quick POC resolves a lot of these problems:
- Include plugins as
includeBuildin settings.gradle rather than as a subproject. - Specify dependencies on plugins in the
dependenciessection ofapp/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.
Activity
dnfield commentedon Mar 13, 2019
Depending on what the solution ends up looking like in the end, we may want to distribute some of this work independently from Flutter tool - perhaps as an independent gradle plugin or as Dart package - so that we could retroactively apply this to stable channel without requiring an upgrade.
mklim commentedon Mar 14, 2019
I've had to tweak these steps slightly to get the proof of concept working on my machine.
android/local.propertiesfrom my app to the android dir of all the different plugin repos to get around a missing sdk error. I do have$ANDROID_HOMEset in my environment correctly so this shouldn't theoretically be necessary, probably some strange things going on there.compileOnlyinstead ofapito avoid a duplicate classpath conflict.mklim commentedon Mar 15, 2019
I put up a very rough WIP of building the plugins as AARs and then including them at runtime at #29460. It's not ready to merge yet though, mostly because it's still blocked on two larger problems:
subprojectsdeclarations fromandroid/build.gradleand theplugins.eachloop fromandroid/settings.gradlelike mentioned in the first comment of this issue. I think arguably this shouldn't require manual intervention to work at all, but if it does we need to gate it behind a check for the changes and use the current logic still otherwise.rmtmckenzie commentedon Mar 22, 2019
Since this is being worked on now, something to consider... some of the APIs from the compat/androidx libraries depend on FragmentActivity being passed to them rather than a Context or Activity. In any plugins in the current system that basically means trying to cast the activity that is passed into the plugin to FragmentActivity and failing if the activity isn't a compat/androidx library.
A good example of this is the androidx biometric library's BiometricPrompt which takes a FragmentActivity.
Also see issue #29819 which describes a problem with FlutterFragmentActivity when using the AndroidX libraries - I don't know if that's something that would be affected by this work or not.
dnfield commentedon Mar 25, 2019
@rmtmckenzie - @matthew-carroll is working on a larger project to make that possible AFAIK
matthew-carroll commentedon Mar 25, 2019
FYI @dnfield @mklim I've got a thread going on over in #29819 that will probably resolve @rmtmckenzie's comment, but it's unclear what the solution is. We're facing an AndroidX vs support lib problem. Have either of your efforts treated that issue at-large?
14 remaining items
blasten commentedon Oct 31, 2021
Refactoring the way Android plugins are included in Flutter won't provide additional benefits at the moment.
The task itself is expensive to implement. It will also increase build times, will require different code paths for local plugin development, and maintaining a service for hosting 3P maven packages.
Due to the above, this feature is out-of-scope, and unlikely to be implemented.
github-actions commentedon Nov 14, 2021
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.