背景
在原生開發中經常要根據不同的渠道打不同的包,主要有以下場景:
- 開發環境、測試環境、生產環境等
不同的環境對應的要求也不一樣,這樣就要求根據需求打出不同的包以便於開發、測試方便的使用。
- 各個應用市場等
由於國記憶體在著有眾多的應用市場,在不同的應用市場可能有不同的統計需求,為此開發人員需要為每個應用市場釋出一個安裝包,在安裝包中新增不同的標識,以此區分各個渠道,方便統計app在應用市場的各種效果。
因此,每當發新版本時,運營會提供一個渠道列表,開發同學會根據這些渠道相應地生成等量的渠道包。隨著渠道越來越多,為了提高渠道打包的效率,因此催生了對多渠道打包的方式的研究。
同樣在 Flutter的專案開發中也涉及到這個問題,在這裡主要講怎麼配置開發包與生產包,並快速打出並執行相應的渠道包。
在這裡我將分別從Android 端、IOS 端、Flutter 端進行講解配置。
Android 配置
對於android,我們只要在app gradle模組中配置productFlavors即可,這裡我們在build.gradle 中 android 下面定義了dev、production兩種flavors。
[...]
android {
[...]
flavorDimensions "app"
productFlavors {
dev {//development
dimension "app"
resValue "string", "app_name", "多渠道打包${defaultConfig.versionCode}" // 設定預設的app_name
applicationId "${defaultConfig.applicationId}.dev"
manifestPlaceholders = [
QQ_APP_ID: "xxx",
CHANNEL_NAME: "dev",
LOCATION_APP_KEY : "xxx", /// 高德地圖key
]
}
production{
dimension "app"
}
}
}
[...]
複製程式碼
配置非常簡單,這裡可以設定不同的應用程式applicationId字尾, 同樣也可以設定不同flavors 的app_name,CHANNEL_NAME。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xx.xx">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:usesCleartextTraffic="true"
android:name="io.flutter.app.FlutterApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- 多渠道打包 -->
<meta-data
android:name="UMENG_CHANNEL"
android:value="${CHANNEL_NAME}" />
</application>
</manifest>
複製程式碼
IOS 配置
對於 ios,我們只需要在ios / Flutter資料夾中為每一個flavor建立相應的配置檔案,就像Flutter中預設預定義Debug.xcconfig和Release.xcconfig一樣,因為production正式包不用變包名與應用名,所以這裡就只建立 dev_debug.xcconfig、dev_release.xcconfig兩個檔案,
並在dev flavor對應的xcconfig中配置bundle_suffix,name_suffix。
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
bundle_suffix=.dev
name_suffix=${FLUTTER_BUILD_NUMBER}
複製程式碼
並在Info.plist檔案新增您定義的變數
然後針對每個 flavor 建立對應的scheme
記得在對話方塊中勾選上 shared現在選擇Runner專案並新增您需要選擇的配置作為之前建立的配置檔案作為配置檔案。
注意,對於每個以Release- [flavorName]和Debug- [flavorName]命名的falvor都有兩個配置。這裡注意名字不要重複。
為了使在打包、釋出時iOS應用使用正確的配置,這裡需要編輯scheme,將構建配置設定為所需的配置:
Flutter 配置
將main.dart重新命名為main_common.dart,把公共配置、執行部分定義在這裡,然後建立 main_dev.dart和main_production.dart檔案,引入main_common,根據需要在main_dev.dart和main_production.dart檔案設定不同的配置引數。
可在 main_dev.dart 中設定網路代理、以及第三方庫等的測試key。
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:flutter_common_utils/http/http_manager.dart';
import 'main_common.dart';
/// @desc 開發、測試環境入口
/// @time 2019-07-17 15:08
/// @author Cheney
Future<Null> main() async {
await initConfig();
//debug 抓包
(HttpManager().client.httpClientAdapter as DefaultHttpClientAdapter)
.onHttpClientCreate = (client) {
client.findProxy = (uri) {
return "PROXY http://10.1.10.111:8080";
};
client.badCertificateCallback =
(X509Certificate cert, String host, int port) {
return true;
};
};
///第三方庫 測試 key
}
複製程式碼
在main_production.dar配置正式的第三方庫 key等。
import 'main_common.dart';
/// @desc 正式環境入口
/// @time 2019-07-17 15:08
/// @author Cheney
Future<Null> main() async {
await initConfig();
///第三方庫 正式 key todo
initMaterialApp();
}
複製程式碼
在main_common 中初始公共配置:
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_common_utils/http/http_manager.dart';
import 'package:flutter_common_utils/log_util.dart';
import 'package:flutter_common_utils/sp_util.dart';
import 'package:oktoast/oktoast.dart';
import 'main.dart';
/// @desc 入口公共部分
/// @time 2019-07-17 15:08
/// @author Cheney
Future<Null> initConfig() async {
await SpUtil().init();
//日誌輸出
LogUtil.init(isDebug: true);
//初始化儲存管理
// await StorageUtil.getInstance();
}
///初始化 App
void initMaterialApp() {
HttpManager().init(
baseUrl: "xxx",
interceptors: [],
);
runApp(OKToast(child: HomeApp()));
}
複製程式碼
這樣在命令列就可以分渠道執行了:
flutter build --flavor dev -t lib/main-dev.dart
flutter build --flavor production -t lib/main-production.dart
如果你想直接大 IDE中直接分渠道包執行,則要編輯配置建立兩個對應的執行配置:
這裡建立了兩個 flutter 執行配置項,main_dev、main_production。在Dart entrypoint 中選擇上面建立的對應的 main_dev.dart、dart_production.dart。
在Build flavor 中選擇對應的 flavor(dev、production)。
此時在執行對應的main_dev、main_production就可以了。
最後
如果在使用過程遇到問題,歡迎下方留言交流。