脑图梳理
多渠道打包介绍
多渠道打包的主要作用是满足产品的运营需求,统计渠道和活动效果。
在之前原生(Android、iOS)开发 App 有各种工具来辅助我们完成多渠道打包。
在我们开发过程中也需要为渠道功能负责,原生的开发工具就基本满足我们调试渠道包内容,但是在 Flutter 上需要更多的配置才可以完成,下文将一一介绍从配置=>调试=>打包的全部流程和细节。
多渠道配置
从 Flutter v1.17 开始,Flutter 命令工具增加了自定义参数的功能 --dart-define,我们可以用这个命令参数在打包或运行 App 时设置参数即可。
首先确定
Flutter版本,我的版本是v1.22.6
flutter run --dart-define=APP_CHANNEL=ZeroFlutter
当然你可以传递多组参数
flutter run --dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart
在 Dart 代码中你需要这样写,一定是和命令参数是对应的
// main.dartclass EnvironmentConfig {static const APP_CHANNEL = String.fromEnvironment('APP_CHANNEL');static const OTHER_VAR = String.fromEnvironment('OTHER_VAR');}
运行查看结果
先修改
Flutter项目对应的代码// my_home_page.dartText('App 渠道:${EnvironmentConfig.APP_CHANNEL}',style: Theme.of(context).textTheme.bodyText1,),Text('其他参数:${EnvironmentConfig.OTHER_VAR}',style: Theme.of(context).textTheme.bodyText1,),
然后运行项目
flutter run --dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart
查看结果

这里可以看到已经把对应的参数内容显示出来了,接下来就是具体业务层怎么来使用的问题了,下面内容也会介绍使用场景,继续往下看👇
多渠道调试
我们已经看到效果了,但是在开发过程中我们不可能一直在命令行运行看效果,如果可以配合 IDE 进行多渠道调试开发那就很棒了,下面分别介绍一下 VS Code 和 Android Studio 的配置方法。
VS Code 配置
- 先创建一个
launch.json启动文件

然后配置启动参数项目
{"version": "0.2.0","configurations": [{"name": "Flutter","request": "launch","type": "dart",// 这里是新加的命令参数"args": ["--dart-define","APP_CHANNEL=Flutter","--dart-define","OTHER_VAR=Dart"]},// 这里是配置多个渠道{"name": "Mi","request": "launch","type": "dart","args": ["--dart-define","APP_CHANNEL=Mi","--dart-define","OTHER_VAR=安卓之光"]}]}
然后这里就出现了配置的渠道信息,我们分别切换
Flutter和Mi运行看看效果

Android Studio 配置
先配置上命令参数

- 添加
Mi渠道配置参数
先复制一下 Flutter 配置,然后修改名字为 Mi,同时修改命令参数配置为 Mi 和 安卓之光
到这里 Android Studio 的配置就基本完毕了,我们切换运行看看效果


到这里已经完成了 IDE 的配置,【详细的配置文件可以访问 GitHub 在项目内获取】,讲了这么多怎么还不说打包📦的事情,别着急我需要给你配置一个精良的装备,后面我们的打包就是一个命令的事情。
配置原生打包脚本
Android
- 更改
Gradle配置
通常 Android 的多渠道是给 AndroidManifest.xml 写一个 <meta-data/> ,如果要保持原来原生的统计方式不变,那么首先我们需要获渠道 命令参数(--dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart)的内容,则需要更改 Gradle 配置
// android/app/build.gradle/// 获取渠道参数使用,这里设置一下默认值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()]}}
如何使用(重命名 apk)
// android/app/build.gradleandroid{// 重命名 apkapplicationVariants.all { variant ->variant.outputs.all { output ->if(variant.buildType.name == "release"){// 获取版本def versionName = variant.versionNamedef versionCode = variant.versionName// 设置新名称def newApkName ="app_v${defaultConfig.versionName}_${defaultConfig.versionCode}_channel_${dartEnvironmentVariables.APP_CHANNEL}.apk"outputFileName = new File(newApkName)}}}}
执行打包
flutter build apk --dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart// 打包后 apk 的输出路径✓ Built build/app/outputs/flutter-apk/app-release.apk (15.4MB).// 打开打包后的 apkopen build/app/outputs/apk/release/

这里看到已经将打包后的 APK 重命名为app_v1.0.0_1_channel_ZeroFlutter.apk,方便我们区分发布到不同的应用商店。iOS
这里 iOS 打包需要先执行
build命令,然后再去Xcode上进行打包上传flutter build ios --dart-define=APP_CHANNEL=ZeroFlutter --dart-define=OTHER_VAR=Dart
打包脚本优化
此时如果我们再执行
Mi渠道打包命令,则会发现之前打包好的app_v1.0.0_1_channel_ZeroFlutter.apk不见了,因为被清理了,所以我们每打包好一个后将 apk 移动到一个渠道包文件夹中,然后继续执行下一个渠道的打包。flutter build apk --dart-define=APP_CHANNEL=Mi --dart-define=OTHER_VAR=安卓之光
优化后的脚本如果下:
渠道打包脚本
# fapk_channel.shflutter build apk --dart-define=APP_CHANNEL=$1 --dart-define=OTHER_VAR=$2cd build/app/outputs/apk/release/cp -R *.apk /Users/zero/apk/$1/cd /Users/zero/apk/$1/open .
批量打包
fapk_channel.sh ZeroFlutter Dartfapk_channel.sh Mi 安卓之光

这样打包就可以全自动完成啦,启动脚本后,就可以去喝杯咖啡啦,喝完咖啡也打包好了。
打包完毕后我们就可以分别对渠道包测试完毕后就上传到对应的应用商店啦使用场景
数据统计
在运营侧,需要统计出每个应用商店(渠道)的下载、安装、使用、日活、周活、月活、活动效果等情况,所以按照渠道区分是非常有必要的,如下图就是我们App 日活渠道分布的情况。

在开发侧,我们需要区分每个渠道的异常情况,打包时对应的符号文件也是不同的,比如 Bugly 可以这样配置就完成不同渠道符号文件的配置。// android/app/build.gradlebugly {appId = 'ZeroFlutter'appKey = 'GitHub:https://github.com/yy1300326388'// 这里配置渠道参数即可appChannel = "${dartEnvironmentVariables.APP_CHANNEL}"}
再比如我们需要设置友盟渠道信息,可以直接通过 Dart 代码调用 Api 设置即可。/// 初始化友盟,直接将 EnvironmentConfig.APP_CHANNEL 传入渠道参数UmengSdk.initCommon(kUmengAndroidAppkey, kUmengIosAppkey, EnvironmentConfig.APP_CHANNEL);
渠道分发
每个应用商店的要求各不相同,有的卡文案配置,有的卡版权信息,有的卡权限使用,针对不同的渠道可能要做不同的处理,我们可以增加一个判断来处理不同的逻辑,或者是用
mixinEnvironmentConfig.APP_CHANNEL == 'Mi'? Text("小米渠道显示",style: Theme.of(context).textTheme.bodyText1,): SizedBox()
这里我们分别运行
ZeroFlutter和Mi渠道看看效果
总结
到这里本文就完毕了,我们主要聊了命令参数的使用配置,以及在开发过程当中渠道包的 IDE 配置和调试技巧,最后聊了一下渠道包的使用场景。
本文是 《Flutter 中的埋点统计-数据思维定胜负》系列文章的第一篇,之后将持续分享以下内容,可以持续关注我,更新内容后会第一时间通知到您。
Flutter 中的埋点统计文章规划目录
- Flutter 多渠道打包详解
- Flutter 全局路由监控
- Flutter 全局异常捕获
- Flutter 最新的全局无痕埋点
源码仓库
用到的脚本和示例代码均在 GitHub 上了
- flutter_multi_channel
-
🔗 参考链接
Flutter 1.17 — no more Flavors, no more iOS Schemas. Command argument that changes everything
- Creating flavors for Flutter
- The Flutter command-line tool
关于我
简介内容:
本文以百万级 Flutter 实战项目为起点,全面细致的讲解了 Flutter 多渠道的配置、调试、打包、调优的核心内容。又综合运营数据驱动方面展示了实际配置技巧。内容简单、通俗、易懂、细致。

