This article addresses how to package Flutter elegantly and quickly in multiple environments (test environment, development environment, etc.), multiple channels.

Configuration in the Flutter

Define a class that gets a custom channel name from the environment. The key specified here is ANDROID_CHANNEL. You can define the key as you want.

Class EnvConfig{/// flutter run --dart-define=ANDROID_CHANNEL=flutter /// Android Studio can configure the parameters for running the flutter --dart-define=ANDROID_CHANNEL=flutter static const CHANNEL=String.fromEnvironment('ANDROID_CHANNEL',defaultValue: 'unknown'); }Copy the code

You can also get multiple, different types of content from the environment.

class EnvConfig{
  static const CHANNEL=String.fromEnvironment('ANDROID_CHANNEL',defaultValue: 'unknown');
  static const VERSION=int.fromEnvironment('ANDROID_VERSION',defaultValue: 1);
}
Copy the code

At this point, run the parameters in the command:

flutter build apk --dart-define=ANDROID_CHANNEL=xiaomi
Copy the code

In this way, the value of CHANNEL is Xiaomi, which is the so-called CHANNEL name. If multiple — dart-defines are used, separate them by Spaces.

flutter build apk --dart-define=ANDROID=xiaomi --dart-define=ANDROID_VERSION=2
Copy the code

This allows business logic operations to be performed based on the variable CHANNEL, such as the Alliance statistics CHANNEL.

Android Studio configuration

In daily development, it is not always possible to use the command line to configure the run parameters.

Configure run args as above.

If you need to configure multiple environments, such as development environment, test environment, formal environment, you can also do this way to avoid manually changing the code, error.

  1. Copy the existing configuration
  2. Changing the Configuration NamenameFor example, production environment:main-prod
  3. Modify different environment parameters

Apk Package name output

When the Flutter is compiled or packaged, it passes the –dart-define parameter to the Build. gradle file of the Android APP component. So you can get content in the following ways.

def dartEnvironmentVariables = [
        ANDROID_CHANNEL: 'android',
]
​
if (project.hasProperty('dart-defines')) {
    println('print dart defines proerty')
    dartEnvironmentVariables = dartEnvironmentVariables + project.property('dart-defines')
            .split(',')
            .collectEntries { entry ->
                def pair = new String(entry.decodeBase64(), 'UTF-8').split('=')
                println(pair.first()+':'+pair.last())
                [(pair.first()): pair.last()]
            }
}
Copy the code

Here’s a note:

The values transmitted by the DARt-GUST are encrypted, so they need to be decrypted, and different versions of the Flutter are encrypted in different ways. Use the above code entry.decodeBase64() on Flutter 2.2. The old version uses the following code urldecoder.decode (entry).

def dartEnvironmentVariables = [
    ANDROID_CHANNEL: 'android',
    OTHER_VAR: 'other',
]
​
if (project.hasProperty('dart-defines')) {
    dartEnvironmentVariables = dartEnvironmentVariables + project.property('dart-defines')
        .split(',')
        .collectEntries { entry ->
            def pair = URLDecoder.decode(entry).split('=')
            [(pair.first()): pair.last()]
        }
} 
Copy the code

If you find that you cannot access them, you can print the contents of project.property(‘ dart-ANNOTated ‘) to see what coding format is available, or check the latest documentation.

Once the channel name is obtained, it is time to configure the APK name, where the custom package name is printed only in the formal environment.

android{ applicationVariants.all { variant -> variant.outputs.all { output -> if(variant.buildType.name == "release"){ def newApkName="${dartEnvironmentVariables.ANDROID_CHANNEL}_app_v${defaultConfig.versionName}_${defaultConfig.versionCode}.a pk" outputFileName = new File(newApkName) } } } }Copy the code

Ok, so the package name of the package output has its own channel. Path should be a project directory/build/app/outputs/apk/release.

Automatic packing

Through the above method, each pack can only play a channel package, so many app stores, tired ah.

In the project root directory, write the script build_channel.sh as follows:

Flutter build apk, dart - define = ANDROID_CHANNEL = $1 CD project root directory/build/app/outputs/apk/release mv *. Apk other directoriesCopy the code

The project root directory needs to be changed to the actual project directory. Since each package overwrites the previous APK, you need to move to another folder after you wrap an APK.

Then create the build_apk.sh script.

build_channel.sh xiaomi
build_channel.sh huawei
build_channel.sh meizu
build_channel.sh vivo
build_channel.sh oppo
build_channel.sh yingyongbao
build_channel.sh m360
Copy the code

According to their own channels, according to the above format can be added.

Finally, you can run the build_apk.sh script. Also note the permission issue of the two scripts chomd 777 XXX.