I'm Zero, not to say a lot, Brain Map
Brain Map Combing
As long as you follow Flutter, this article is definitely useful==>Highly recommended ➕ Collection
Introduction to Multi-Channel Packaging
The main role of multi-channel packaging is to meet the operational needs of products, statistical channels and activity results.
Previously native (Android, iOS) development of App had a variety of tools to assist us in multi-channel packaging.
In our development process, we also need to be responsible for the channel function. Native development tools can basically satisfy our debugging channel package content, but more configuration is needed on Flutter to complete. Below is a description of the entire process and details from Configuration=>Debugging=>Packaging.
Multi-Channel Configuration
From Flutter v1.17 Beginning with the Flutter command tool, the ability to customize parameters was added, dart-define, which allows us to set parameters when packaging or running App.
First determine the Flutter version, my version is v1.22.6
flutter run --dart-define=APP_CHANNEL=ZeroFlutter
Of course you can pass multiple sets of parameters
flutter run --dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart
You need to write this in Dart code, it must correspond to the command parameters
// main.dart class EnvironmentConfig { static const APP_CHANNEL = String.fromEnvironment('APP_CHANNEL'); static const OTHER_VAR = String.fromEnvironment('OTHER_VAR'); }
Run to view results
- Modify the code for the Flutter project first
// my_home_page.dart Text( 'App Channels: ${EnvironmentConfig.APP_CHANNEL}', style: Theme.of(context).textTheme.bodyText1, ), Text( 'Other parameters: ${EnvironmentConfig.OTHER_VAR}', style: Theme.of(context).textTheme.bodyText1, ),
- Then run the project
flutter run --dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart
- View results
Here you can see that the parameters have been displayed, and the next step is how to use the specific business layer. The following also describes the usage scenario, and continue to look down 👇
Multi-channel Debugging
We've already seen the results, but it's impossible to run them all the time on the command line during the development process. It would be great if you could do multi-channel debugging with the IDE. Here's how to configure VS Code and Android Studio, respectively.
VS Code Configuration
- Create a launch first. JSON startup file
- Then configure the startup parameter item
{ "version": "0.2.0", "configurations": [ { "name": "Flutter", "request": "launch", "type": "dart", // This is the newly added command parameter "args": [ "--dart-define", "APP_CHANNEL=Flutter", "--dart-define", "OTHER_VAR=Dart" ] }, // Here is to configure multiple channels { "name": "Mi", "request": "launch", "type": "dart", "args": [ "--dart-define", "APP_CHANNEL=Mi", "--dart-define", "OTHER_VAR=Android Light" ] } ] }
Then there's the channel information for configuration, so let's switch between Flutter and Mi to see what happens.
Android Studio Configuration
- Configure command parameters first
- Add Mi Channel Configuration Parameters
Copy the Flutter configuration first, then change the name to Mi, and modify the command parameters to configure Mi and Android Light
Now that Android Studio is almost configured, let's switch runs to see what happens
Now that the IDE has been configured, [detailed configuration files can be accessed from GitHub within the project], there's so much to say about packaging 📦 Don't worry, I need to configure a sophisticated equipment for you, after which our packaging is a command thing.
Configure Native Packaging Scripts
Android
- Change Gradle Configuration
Usually Android's multi-channel is for Android Manifest. XML writes a <meta-data/>, if you want to keep the original statistics unchanged, then first we need to get the contents of the channel command parameters (--dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart), then we need to change the Gradle configuration
// android/app/build.gradle ///Get channel parameter usage, set default here def dartEnvironmentVariables = [ APP_CHANNEL: 'main', 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()] } }
- How to use (rename apk)
// android/app/build.gradle android{ // Rename apk applicationVariants.all { variant -> variant.outputs.all { output -> if(variant.buildType.name == "release"){ // Get Version def versionName = variant.versionName def versionCode = variant.versionName // Set a new name def newApkName ="app_v${defaultConfig.versionName}_${defaultConfig.versionCode}_channel_${dartEnvironmentVariables.APP_CHANNEL}.apk" outputFileName = new File(newApkName) } } } }
- Execute Packaging
flutter build apk --dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart // Output path of packaged apk ✓ Built build/app/outputs/flutter-apk/app-release.apk (15.4MB). // Open packaged apk open build/app/outputs/apk/release/
Here you can see that the packaged APK has been renamed app_v1.0.0_1_channel_ZeroFlutter.apk, which allows us to distinguish between different app stores.
Packaging script optimization
If we execute the Mi Channel Packaging command again, we will find the previously packaged app_ V1. 0.0_ 1_ Channel_ ZeroFlutter. The apk disappeared because it was cleaned up, so we moved the apk into one channel package folder after each package, and then proceeded with the next channel package.
flutter build apk --dart-define=APP_CHANNEL=Mi --dart-define=OTHER_VAR=Android Light
Optimized script if:
- Channel Packaging Script
# fapk_channel.sh flutter build apk --dart-define=APP_CHANNEL=$1 --dart-define=OTHER_VAR=$2 cd build/app/outputs/apk/release/ cp -R *.apk /Users/zero/apk/$1/ cd /Users/zero/apk/$1/ open .
- Batch Packaging
fapk_channel.sh ZeroFlutter Dart fapk_channel.sh Mi Android Light
This will allow the packaging to be fully automated. After you start the script, you can go and have a cup of coffee and pack the coffee.
Once packaged, we can test each channel package and upload it to the corresponding app store.
Use scenarios
data statistics
On the operational side, we need to figure out the download, installation, use, daily, weekly, monthly and activity effects of each app store (channel), so it is very necessary to distinguish them according to the channel. The following figure is the distribution of our App daily channel.
On the development side, we need to distinguish the exception of each channel, and the corresponding symbol files are different when packaging. Bugly can do this to complete the configuration of different channel symbol files.
// android/app/build.gradle bugly { appId = 'ZeroFlutter' appKey = 'GitHub:https://github.com/yy1300326388' // Configure channel parameters here appChannel = "${dartEnvironmentVariables.APP_CHANNEL}" }
For example, if we need to set up the channel information for the alliance, we can call the Api settings directly from the Dart code.
///Initialize the federation, direct EnvironmentConfig.APP_CHANNEL Inbound Channel Parameters UmengSdk.initCommon(kUmengAndroidAppkey, kUmengIosAppkey, EnvironmentConfig.APP_CHANNEL);
Then you can see the statistics in the background to facilitate our further operation and development
Channel Distribution
Each app store has different requirements, some are card copy configuration, some are card copyright information, some are card rights use, different processing may be done for different channels, we can add a judgment to handle different logic, or use mixin
EnvironmentConfig.APP_CHANNEL == 'Mi' ? Text( "Millet Channel Display", style: Theme.of(context).textTheme.bodyText1, ) : SizedBox()
Here we run ZeroFlutter and Mi channels to see the effect
summary
This is the end of this article. We mainly talk about the configuration of command parameters, IDE configuration and debugging techniques of channel packages during the development process. Finally, we talk about the use of channel packages scenarios.
This is the first in a series of articles titled Buried Point Statistics in Flutter - Data Mind Wins and Loses. After that, I will continue to share the following to keep an eye on me and let you know when I update it.
Buried Statistical Articles Planning Directory in Flutter
- Flutter Multi-Channel Packaging Details
- Flutter Global Routing Monitoring
- Flutter Global Exception Capture
- Flutter's latest global traceless buried point
Source warehouse
The scripts and sample code used are all on GitHub
Reference Links
- Flutter 1.17 — no more Flavors, no more iOS Schemas. Command argument that changes everything
- Creating flavors for Flutter
- The Flutter command-line tool
About me
- 15-18 years of smart hardware-related App development using Android native
- In May 188, I came across Flutter by chance and started to learn by myself. weather_flutter It's my entry-level practice project for Flutter (I still think he's a great fit for Flutter entry exercises right now)
- In August 188, tremendous pressure (Flutter did not have Release 1.0 at that time) began to use Flutter to develop enterprise projects and to develop and maintain more than a dozen Flutter plug-in packages (because plug-in resources were scarce at that time)
- Up to now, four enterprise Flutter App s have been leading and participating online, and one App currently in charge has a cumulative user base of 120W+, which gives you a great experience using Flutter
👏 Welcome ➕ follow ➕ Forward, any questions are always below 👇 Message, I will reply first time Oh