huazi

huazi

An Introduction to Flutter's Android Hybrid Development

This article was written for internal sharing within the company and is based on an outdated version of Flutter, so there may be inaccuracies. Please point them out. Now it is posted on the blog and will be improved in the future.

Introduction#

Flutter is Google's mobile UI framework that allows you to quickly build high-quality native user interfaces on iOS and Android. Flutter can work with existing code.
Flutter has the following features:

  • Fast development with millisecond-level hot reload, where your app's interface updates immediately after modification.
  • Unified application development experience.
  • Native performance.
    Currently, many large companies have started using Flutter in their projects, such as Xianyu and Meituan, and have received positive feedback.
    https://github.com/alibaba/flutter-go
    The article is currently relatively simple, and each module can be refined in the future.

Introduction and Installation of Flutter#

For building Flutter applications, due to the differences in development language (Dart), virtual machine, and build tools compared to developing native applications, Flutter SDK is required for support.
Flutter is somewhat similar to Gradle. Different developers may install different versions of Flutter, and when the Flutter SDK versions are inconsistent, there may be compatibility issues with Dart APIs or Flutter virtual machines. (This issue can be handled by referring to Android Gradle management, where the Gradle version is bound to the project)

Specific Flutter SDK installation can be done according to the official documentation: https://flutter.dev/docs/get-started/install/macos
Or the Flutter Chinese documentation: https://flutterchina.club/setup-macos/

The installation process is relatively straightforward. If there are issues with the firewall, you can refer to the Chinese documentation, which provides temporary mirrors for Flutter developers in China.

Once configured, you can use various Flutter commands, such as flutter doctor.

Four Types of Flutter Projects#

In a Flutter project, there are usually several types of projects, which are briefly described below:

  1. Flutter Application
    A standard Flutter app project that includes both the Dart layer and the native platform layer.

  2. Flutter Module
    A Flutter component project that only includes the Dart layer implementation, with the native platform layer sub-project automatically generated by Flutter and hidden.

  3. Flutter Plugin
    A Flutter platform plugin project that includes both the Dart layer and the native platform layer implementation.

  4. Flutter Package
    A Flutter pure Dart plugin project that only includes the Dart layer implementation and often defines some common widgets.

Using Flutter in Existing Projects#

It is currently not feasible to convert an existing project into a pure Flutter project. Currently, only partial module functionality can be developed using Flutter, such as the expression function in the current magnetic field project. Therefore, Flutter officially provides a way to add Flutter to existing native projects:
https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps

The desired effect is as follows:

  • Non-Flutter developers are not aware of the change.
  • No impact on existing projects.
  • No need to modify the existing continuous integration and build release.
  • Convenient for Flutter developers to develop.

The official project adds the Flutter project as a module dependency. However, this requires significant modifications to the project and is only suitable for developers. Therefore, we need to consider other methods. In the documentation, we know that by using ./gradlew flutter:assemble, an AAR can be packaged. This AAR is actually the product generated by Flutter and packaged as an AAR for use in projects. We can use this to only use the AAR, which basically meets the above conditions. However, if we generate an AAR each time and then copy it to the libs folder of the main project, it would be too cumbersome. It would be even better if the AAR could be remotely depended upon. In this case, the above requirements would be met. For the native project, it would only be a remote dependency, and when an update is needed, only the version number needs to be modified.

So far, we have outlined the process:

  • Flutter AAR as a remote dependency.
  • Local configuration to determine whether it is a Flutter development environment.
    • If the development environment is enabled, use the local dependency method.
    • If the development environment is disabled, use the remote dependency.
    • Disabled by default.
  • Flutter project can automatically package and upload the AAR to a remote repository.

The project structure of the Flutter module is shown in the following diagram:

flutter_android_img.jpeg

The .android and .ios directories are automatically generated and can be deleted at any time. They are obtained by running flutter packages get. The Flutter code is mainly located in the lib directory. Note that there is a Flutter directory in both the .android and .ios directories, which is our Flutter library project. This is the library project used to generate the AAR for Android and the framework for iOS. If we generate a pure Flutter project using flutter create xxx, this Flutter directory will not exist.

Challenges Encountered in Development#

  1. Project configuration productFlavor prevents the packaging of flutter_assets into the APK

Actually, this is a bug in the new version of Flutter. The build process of Flutter is done through flutter.gradle. In the new version, some changes have been made, which caused certain tasks to not be executed due to hard-coded reasons, resulting in the inability to package flutter_assets into the APK. This leads to crashes.

A temporary solution was implemented:

  • Create a proxy Flutter build Gradle file, namely flutter_proxy.gradle, copied from flutter.gradle.
  • Modify the logic of executing tasks related to productFlavor in flutter_proxy.gradle to ensure that the packaging tasks for the relevant productFlavor are executed.
  • Replace flutter.gradle with flutter_proxy.gradle in build.gradle.

This allows normal packaging using Gradle. The downside is that flutter package get needs to be modified every time.

Note: This bug has been fixed in the new version of the Flutter SDK.

  1. There is also a question about why installing the AAR generated by ./gradlew flutter:assemble causes a crash when opening a Flutter page from a native page, but it works fine when the flutter command is removed from ./gradlew assemble. It is suspected to be related to the packaging process, but it has not been investigated in depth.

  2. By default, when setting properties for the app bar, the status bar is also set.
    Solution: Adjust the status bar properties separately or modify the theme.

  3. The default build.gradle generated in the Flutter project depends on support version 27.1.1, but the project currently uses version 26.1.0, which causes dependency conflicts.

For remote dependencies, you can remove the support dependency as follows:

implementation('com.huazidev:test-futter-aar:0.0.2@aar', {
     exclude group: 'com.android.support'
})

For local development environments, you can configure it as follows:

implementation(project(':flutter')){
      exclude group: 'com.android.support'
}

Alternatively, you can modify all support dependencies in Gradle.


Next Chapter, To Be Improved#

  • Write scripts to automatically package and release AAR.
  • Publish to jcenter, Maven, and other open-source repositories.
  • Publish to a self-hosted private Maven repository.
  • Publish using JitPack (private repositories are charged).
  • Use GitHub's functionality as a package management repository (supports private repositories).
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.