Flutter 77: illustration of the history of Android Native project access to the Flutter Module

With the gradual development and improvement of Flutter, more and more scenarios are used in combination with Native. Xiaocai tries to connect a historical Android Native project to the Flutter Module today;


The development of Flutter is very fast. Most plug-ins are suitable for Android X. for the convenience of future development, the following version of plugins is preferred to upgrade and adapt to Android X;

minSdkVersion 17
targetSdkVersion 26

compileSdkVersion 28
buildToolsVersion "28.0.3"

I've tried small dishes before Flutter upgrade for Android x Android's processing is similar, and the dishes try to adapt to the actual project;

1. Add Android X configuration

Add the following configuration in the android/gradle.properties file:

2. Migrate to AndroidX

The small dish is upgraded through the migrate to Android X in Android Studio (manual upgrade requires a huge number of files to be modified), select this project - > refactor - > migrate to Android X; however, the current version of the small dish is 3.0.0, at this time, it is prompted that the Gradle needs to be > = 3.2.0, so the small dish needs to upgrade the Gradle first;

3. Gradle upgrade

Upgrade the version of Gradle in the android/build.gradle file, and Sync synchronization will be prompted by the following two prompts:;

classpath 'com.android.tools.build:gradle:3.2.0'

3.1 compile is no longer recommended. Replace the compile in each Module with api / implementation;

Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html

3.2 in the project of small dishes, Java 8 is supported by retrorambda before, and Java 8 is supported by default after gradle > 3.0.0. Small dishes will be introduced and removed;

One of the plugins you are using supports Java 8 language features. To try the support built into the Android plugin, remove the following from your build.gradle:
    apply plugin: 'me.tatarka.retrolambda'
To learn more, go to https://d.android.com/r/tools/java-8-support-message.html

4. Repeat the second step, migrate to Android x

Pay attention to choosing the bottom Do Refactor, which will save us a lot of work. Only individual file import or xml needs to be changed, otherwise we need to manually modify a large number of file import, etc;

android.support androidx
android.support.annotation.NonNull; androidx.annotation.NonNull;
android.support.annotation.Nullable; androidx.annotation.Nullable;
android.support.annotation.IntRange; androidx.annotation.IntRange;
android.support.design.widget.CoordinatorLayout; androidx.coordinatorlayout.widget.CoordinatorLayout;
android.support.v4.content.ContextCompat; androidx.core.content.ContextCompat;
android.support.v4.widget.DrawerLayout; androidx.drawerlayout.widget.DrawerLayout;
android.support.v4.app.Fragment; androidx.fragment.app.Fragment;
android.support.v4.graphics.drawable.RoundedBitmapDrawable; androidx.core.graphics.drawable.RoundedBitmapDrawable;
android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
android.support.v7.widget.RecyclerView; androidx.recyclerview.widget.RecyclerView;
android.support.v7.app.AlertDialog; androidx.appcompat.app.AlertDialog;
... ...

5. Sync synchronous packaging inspection

If there are individual xml files that need to be adjusted, just follow the prompts to fine tune them; debug / release needs to be packaged for inspection; this upgrade is basically completed to adapt to Android X;

Flutter Module

I've tried it before Android native integrated shuttle module , there are relevant Flutter projects in the small dish group, so it is no longer new, and the integration method is very simple;

1. Introducing the path of fluent module in setting.gradle
setBinding(new Binding([gradle: this]))
evaluate(new File(
2. Introduce fluent dependency in APP / build.project
implementation project(':flutter')
3. Post sync verification

The dishes have been arranged before Native interaction between Flutter and Android , but only one fluteractivity is provided for page Jump for the convenience of verification;

public class FlutterMainActivity extends FlutterActivity {
    protected void onCreate(@Nullable Bundle savedInstanceState) {

The fletterapplication is not used for small dishes, and the following questions are prompted at this time;

Caused by: java.lang.IllegalStateException: ensureInitializationComplete must be called after startInitialization
    at io.flutter.embedding.engine.loader.FlutterLoader.ensureInitializationComplete(FlutterLoader.java:153)
    at io.flutter.view.FlutterMain.ensureInitializationComplete(FlutterMain.java:80)
    at io.flutter.app.FlutterActivityDelegate.onCreate(FlutterActivityDelegate.java:144)
    at io.flutter.app.FlutterActivity.onCreate(FlutterActivity.java:89)
    at com.test.FlutterMainActivity.onCreate(FlutterMainActivity.java:13)
    at android.app.Activity.performCreate(Activity.java:6367)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2397)

After initializing in advance in FlutterMainActivity, new problems will be prompted;

protected void onCreate(@Nullable Bundle savedInstanceState) {

UncaughtException detected: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.test-2/base.apk", zip file "/data/app/com.test-2/split_lib_dependencies_apk.apk", zip file "/data/app/com.test-2/split_lib_slice_0_apk.apk", zip file "/data/app/com.test-2/split_lib_slice_1_apk.apk"],nativeLibraryDirectories=[/data/app/com.test-2/lib/arm, /data/app/com.test-2/base.apk!/lib/armeabi, /data/app/com.test-2/split_lib_dependencies_apk.apk!/lib/armeabi, .../split_lib_slice_8_apk.apk!/lib/armeabi, /data/app/com.test-2/split_lib_slice_9_apk.apk!/lib/armeabi, /vendor/lib, /system/lib]]] couldn't find "libflutter.so"
    at java.lang.Runtime.loadLibrary(Runtime.java:379)
    at java.lang.System.loadLibrary(System.java:1086)
    at io.flutter.embedding.engine.loader.FlutterLoader.startInitialization(FlutterLoader.java:122)
    at io.flutter.embedding.engine.loader.FlutterLoader.startInitialization(FlutterLoader.java:93)
    at io.flutter.view.FlutterMain.startInitialization(FlutterMain.java:45)
    at com.test.FlutterMainActivity.onCreate(FlutterMainActivity.java:14)

After querying, it is found that the current project NDK only supports the armeabi architecture, while the one supported by Flutter is armeabi-v7a, which will be tested after being added; if the project has special requirements that NDK must be armeabi, you can consider copying the flitter.so of armeabi-v7a into the project;

ndk {
    abiFilters "armeabi", "armeabi-v7a", "x86"


Small expansion

In the process of adapting Android x, the following problems are encountered, not all of which are involved, and the records are for reference only;

Q1: All flavors must now belong to a named flavor dimension.

The following error will be prompted when multi-channel packaging is performed after the upgrade of Gradle;

FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':app'.
> All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org

When gradle > 3.0, you need to specify a kind of flavor dimensions for multi-channel packaging. It is recommended that you do not directly use the name of main, or new duplicate key problems will occur easily. Com.android.build.gradle.internal.api.artifact.buildableartificimpl

// Before modification
productFlavors {
  test1 {}
  test2 {}
  main {}
// After modification
flavorDimensions "main"
productFlavors {
  test1 { dimension "main" }
  test2 { dimension "main" }
  main0 { dimension "main" }
Q2: com.android.builder.dexing.DexArchiveBuilderException

During the course of running, the small dish also prompts the error of DexArchiveBuilderException;


Looking up the small dishes is the problem of not specifying Java8. Just add 1.8;

compileOptions {
    sourceCompatibility 1.8
    targetCompatibility 1.8
Q3: Unable to find method '...getOutputs()Ljava/util/List'
Error:Unable to find method 'com.android.build.gradle.api.BaseVariant.getOutputs()Ljava/util/List;'.
Possible causes for this unexpected error include:<ul><li>Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
<a href="syncProject">Re-download dependencies and sync project (requires network)</a></li><li>The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.

After several checks, it is found that ButterKinfe version is lower, so upgrade to the latest version of 10.2.1 supporting Android X; note that Java 8 environment is required at this time;

dependencies {
  implementation 'com.jakewharton:butterknife:10.2.1'
  annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.1'

So far, the history project of Xiaocai has been upgraded and adapted to Android X and connected to the fluent module. The next step is the interaction between the two. Upgrading and adaptation is a difficult and complex process, and there may be many unexpected problems. I hope you can settle down and solve them slowly. If you have any problems, please give me more guidance!

Source: little monk aze

Tags: Android Java Gradle DrawerLayout

Posted on Sun, 23 Feb 2020 04:13:38 -0500 by Gafaddict