Flutter 安卓分渠道打包

Flutter Jun 20, 2020

一、Android原生部分

修改'android/app/build.gradle'文件

android {
    [...]

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 27
        testInstrumentationRunner 	"android.support.test.runner.AndroidJUnitRunner"
    }

    flavorDimensions "app"
    productFlavors {
        // 主要是为了不同的渠道包使用不同的 包名 版本号 等
        app1 {
            dimension "app"
            applicationId "com.example.app1"
            versionCode 1
            versionName "1.0"
        }

        app2 {
            dimension "app"
            applicationId "com.example.app2"
            versionCode 1
            versionName "1.0"
        }
    }

    buildTypes {
        [...]
    }
}

二、Flutter部分(根据不同渠道,在flutter中获取对应的变量值)

lib 下创建一个 'app_config.dart' 文件,用来处理渠道变量。

import 'package:flutter/material.dart';

class AppConfig extends InheritedWidget {
  AppConfig(
      {this.appDisplayName, this.appInternalId, this.channel, Widget child})
      : super(child: child);

  final String appDisplayName;
  final int appInternalId;
  final String channel;

  static AppConfig of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<AppConfig>();
  }

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) => false;
}

将入口 'main.dart' 文件改为 'main_common.dart',并将其中main方法改为mainCommon

// 将main方法改为 mainCommon
void mainCommon() {
  // main方法中的逻辑代码
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var config = AppConfig.of(context);
    return _buildApp(config.appDisplayName,config.channel);
  }

  Widget _buildApp(String appName,String channel){
    return MaterialApp(
      title: '$appName,$channel',
      theme: ThemeData(
        primaryColor: Color(0xFF43a047),
        accentColor: Color(0xFFffcc00),
        primaryColorBrightness: Brightness.dark,
      ),
      home: HomePage(),
    );
  }
}

分别创建两个渠道对应的入口文件 'main_app1.dart' 和 'main_app2.dart'

/// main_app1.dart'
import 'package:yourproject/app_config.dart';
import 'package:yourproject/main_common.dart';
import 'package:flutter/material.dart';
 
void main() {
  var configuredApp = AppConfig(
    appDisplayName: "App 1",
    appInternalId: 1,
    channel:'channel App 1'
    child: MyApp(),
  );
 
  mainCommon();
 
  runApp(configuredApp);
}
/// main_app2.dart'
import 'package:yourproject/app_config.dart';
import 'package:yourproject/main_common.dart';
import 'package:flutter/material.dart';
 
void main() {
  var configuredApp = AppConfig(
    appDisplayName: "App 2",
    appInternalId: 1,
    channel:'channel App 2'
    child: MyApp(),
  );
 
  mainCommon();
 
  runApp(configuredApp);
}

现在就可以在flutter中直接使用配置好的变量了,最好是在入口处 'main_common.dart' 存下来,方便以后任意位置使用

// 将main方法改为 mainCommon
void mainCommon() {
  // main方法中的逻辑代码
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var config = AppConfig.of(context);
    // 缓存下来,方便其他任意地方(没有context的地方)使用
    SpUtil.putString('appDisplayName', config.appDisplayName);
    SpUtil.putString('channel', config.channel);
    return _buildApp(config.appDisplayName,config.channel);
  }

  Widget _buildApp(String appName,String channel){
    return MaterialApp(
      title: '$appName,$channel',
      theme: ThemeData(
        primaryColor: Color(0xFF43a047),
        accentColor: Color(0xFFffcc00),
        primaryColorBrightness: Brightness.dark,
      ),
      home: HomePage(),
    );
  }
}

三、运行、打包渠道包

// 运行
flutter run --flavor app1 -t lib/main_app1.dart

// 打包
flutter build apk --flavor app1 -t lib/main_app1.dart
flutter build apk --no-shrink --flavor app1 -t lib/main_app1.dart

Tags