“This is the 11th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge juejin.cn/post/698796…

With the gradual development and improvement of Flutter, more and more scenes are used in combination with Native. Today, we try to add a historical Android Native project to the Flutter Module;

AndroidX

The development of Flutter is very fast and most of the add-ons are for AndroidX. For the convenience of future development, the side dishes should be upgraded from the following versions to AndroidX;

MinSdkVersion 17 targetSdkVersion 26 compileSdkVersion 28 buildToolsVersion "28.0.3"Copy the code

The side dish has been tried to upgrade the Flutter to AndroidX. Android handles it similarly. The side dish has been tried to fit the actual project.

Add 1.AndroidXconfiguration

The android/gradle. The properties file to add the following configuration:

android.useAndroidX=true
android.enableJetifier=true
Copy the code
2. Migrate to AndroidX

Migrate to AndroidX using Android Studio (manual upgrade requires modifying a large number of files), go to this project -> Refactor -> Migrate to AndroidX; But the dish current Gradle version is 3.0.0, this time prompt Gradle need >= 3.2.0, so the dish needs to upgrade Gradle;

3. Gradle upgrade

Upgrade gradle version in Android /build.gradle file; When Sync is synchronized, the following two prompts are displayed.

The classpath 'com. Android. Tools. Build: gradle: 3.2.0'Copy the code

3.1 compile is not recommended. Compile is replaced with API/implementation in each Module.

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.htmlCopy the code

3.2 Side dishes in the project passed beforeretrolambdasupportJava8In theGradle > 3.0.0And then by defaultJava8, side dishes will be introduced to remove;

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
Copy the code

4. Repeat step 2.Migrate to AndroidX

Note to select the bottom Do Refactor, will help us to save a huge amount of work, only need to import individual files or XML needs to change, otherwise we need to manually modify a large number of files imported;

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. SyncSynchronous packing inspection

If some XML files need to be adjusted, fine tune them as prompted. Debug/release needs to be packaged for validation; The upgrade to AndroidX is basically complete.

Flutter Module

I have tried the Original Android Integrated Flutter Module before. The Flutter Module already has a related project, so I will not create a new one. The integration method is very simple.

1. setting.gradleThe introduction ofFlutter ModuleThe path
setBinding(new Binding([gradle: this]))
evaluate(new File(
        '/Users/user/Documents/workspace/flutter_module02/.android/include_flutter.groovy'
))
Copy the code
2. app/build.projectThe introduction of Flutter dependence
implementation project(':flutter')
Copy the code
3. SyncPost-synchronous check

The side dish has previously arranged the Flutter to interact with Android native, but to verify the convenience of the side dish only provides a FlutterActivity for the page to jump to;

public class FlutterMainActivity extends FlutterActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); }}Copy the code

FlutterApplication is not used for the side dish, and the following problem is displayed;

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)
Copy the code

After early initialization in FlutterMainActivity, a new problem is displayed.

protected void onCreate(@Nullable Bundle savedInstanceState) {
    FlutterMain.startInitialization(this);
    super.onCreate(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)
Copy the code

The NDK only supports armeabi, while the Flutter supports Armeabi-V7A. If there is a special requirement that the NDK must be Armeabi, consider copying the Flutter of Armeabi-V7A into the project.

ndk {
    abiFilters "armeabi", "armeabi-v7a", "x86"
}
Copy the code

      

A small extension

Side dish in the adaptation of AndroidX process also encountered the following problems, not all projects involved, records for reference only;

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

[Bug Mc-10864] – When multichannel packaging is performed after Gradle upgrade, the following error is displayed.

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
BUILD FAILED in 0s
Copy the code
A1:

Gradle > 3.0 requires a flavor dimensions for multichannel packaging. It is recommended not to use the name of main directly. Otherwise, new duplicate keys may occur. com.android.build.gradle.internal.api.artifact.BuildableArtifactImpl

FlavorDimensions "main" productFlavors {test1 {} test2 {} main {}} flavorDimensions "main" productFlavors {test1 {dimension "main" } test2 { dimension "main" } main0 { dimension "main" } }Copy the code
Q2: com. Android. Builder. Dexing. DexArchiveBuilderException

Dishes in the process of running also suggests DexArchiveBuilderException error;

com.android.builder.dexing.DexArchiveBuilderException
Copy the code
A2:

Side dishes are not specified Java8, add the specified 1.8 can;

CompileOptions {sourceCompatibility 1.8 targetCompatibility 1.8}Copy the code
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.Copy the code
A3:

After checking, I found that ButterKinfe is a lower version, so you can upgrade to the latest version 10.2.1 supporting AndroidX. Note that you need a Java8 environment at this point;

Dependencies {implementation 'com. Jakewharton: butterknife: 10.2.1 annotationProcessor 'com. Jakewharton: butterknife - compiler: 10.2.1'}Copy the code

So far, the history of the dish has been upgraded to AndroidX and added to the Flutter Module. The next step is to interact with each other. Upgrade and adaptation is a difficult and complex process, and there may be many unexpected problems. I hope I can settle down and solve them slowly. If you have any questions, please guide!

Source: Young Monk Atze