相关文章推荐
英俊的鞭炮  ·  Bash script in ...·  6 月前    · 
不敢表白的小马驹  ·  Echarts - ...·  1 年前    · 
  1. 我们的应用集成了 TalkingData 这个第三方工具来统计日活、事件等,需要在应用启动时初始化SDK,这个时候需要传入当前渠道,以便数据的统计。

  2. 由于最开始是用脚本一个个打包,一直想解决打包过慢的问题,但是网上大多教程是基于命令行参数或 flavor ,实质上并没有根本解决打包效率的问题。直到发现了文章的主角 walle

应用解决方案

walle

walle 是美团开源的一个打包插件,这里就不做介绍了, 传送门

flutter插件

由于源码是 Android 端的,就想着写一个 Flutter 插件吧。代码也很简单,已经上传到 pub 仓库。使用步骤可以参考 Github | Pub仓库

经过线上测试,存在部分机型获取不到渠道的情况,请慎重使用

参考 example

  1. 在 android/build.gradle 文件中添加依赖
buildscript { repositories { // 不加这个找不到walle依赖 maven { url 'https://maven.aliyun.com/repository/jcenter' maven { url 'https://maven.aliyun.com/repository/google' google() mavenCentral() rootProject.allprojects { repositories { // 同上 maven { url 'https://maven.aliyun.com/repository/jcenter' maven { url 'https://maven.aliyun.com/repository/google' google() mavenCentral() // ... // 末尾添加 dependencies { implementation 'com.meituan.android.walle:library:1.1.7'
  1. Android端注册文件(android/src/main/java/net/niuxiaoer/package_by_walle/PackageByWallePlugin.java)
import com.meituan.android.walle.WalleChannelReader;
/** PackageByWallePlugin */
public class PackageByWallePlugin implements FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;
  private Context applicationContext;
  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    this.applicationContext = flutterPluginBinding.getApplicationContext();
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "package_by_walle");
    channel.setMethodCallHandler(this);
  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPackingChannel")) {
      try {
        // 这里调用walle的方法
        String channel = WalleChannelReader.getChannel(this.applicationContext);
        result.success(channel);
      } catch(Exception e) {
        result.success("unknown");
    }  else if (call.method.equals("getPackingInfo")) {
      ChannelInfo channelInfo = WalleChannelReader.getChannelInfo(this.applicationContext);
      if (channelInfo != null) {
        Map<String, String> extraInfo = channelInfo.getExtraInfo();
        result.success(extraInfo);
      } else {
        result.success(null);
    } else {
      result.notImplemented();
  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  1. iOS端注册文件(ios/Classes/PackageByWallePlugin.m)
@implementation PackageByWallePlugin + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"package_by_walle" binaryMessenger:[registrar messenger]]; PackageByWallePlugin* instance = [[PackageByWallePlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([@"getPackingChannel" isEqualToString:call.method]) { result(@"AppStore"); } else { result(FlutterMethodNotImplemented);
  1. dart文件(lib/package_by_walle.dart)
class PackageByWalle {
  static const MethodChannel _channel = MethodChannel('package_by_walle');
  static Future<String?> get getPackingChannel async {
    final String? version = await _channel.invokeMethod('getPackingChannel');
    return version;
  static Future<Map<dynamic, dynamic>?> get getPackingInfo async {
    if (Platform.isAndroid) {
      final Map<dynamic, dynamic>? info = await _channel.invokeMethod('getPackingInfo');
      return info;
    } else {
      return null;

使用脚本的方式打一个渠道包需要3-4分钟,总共就需要等待半个多小时。现在一共只需要三分钟左右,效率方面提升很大。

本文已同步到个人博客

背景我们的应用集成了TalkingData这个第三方工具来统计日活、事件等,需要在应用启动时初始化SDK,这个时候需要传入当前渠道,以便数据的统计。由于最开始是用脚本一个个打包,一直想解决打包过慢的问题,但是网上大多教程是基于命令行参数或flavor,实质上并没有根本解决打包效率的问题。直到发现了文章的主角 walle。应用解决方案wallewalle是美团开源的一个打包插件,这里就不做介绍了,传送门。flutter插件由于源码Android端的,就想着写一个Flutter插件吧。
首先在lib建立多个main.dart,比如main_local.dart表示本地开发运行时执行的入口文件,main_develop.dart和main.dart分别表示开发环境和生产环境: ├── api/ ├── main.dart ├── main_develop.dart ├── models/ ├── pages/ ├── utils/ └── widgets/ 这样如果...
2019-06-19 公司已经开始在项目中使用Flutter进行跨平台开发了,并且已经在其中一款应用上线了,过程并没有多曲折,按照官网教程一步步进行,继承、打包、测试、发版。 最近另外一个项目有新的需求,也开始使用Flutter,在集成打包的时候出现了问题: A/flutter: [FATAL:flutter/shell/common/shell.cc(218)] Check failed: vm. Must be able to initialize the VM. 收集到的错误日志如下:
1.配置--dart-define,如下: --dart-define=APP_CHANNEL=www.baidu.com --dart-define=OTHER_VAR=这是测试环境
Flutter多渠道调试设置 (安卓篇,Android Studio) 在build.gradle中定义不同的风味(flavor),一套代码可在同一个设备上同时安装名称、图标、applicationId不同的两个应用 android { flavorDimensions "app" productFlavors { // 生产环境 flavoronline { dimension
类似于Android第三方库引入是在gradle文件中,Flutter相要引入第三方包也要对应配置文件pubspec.yaml。 yaml全称是 :Yet Another Markup Language ,任是一种标记语言。 这里我是采用了官方的例子来展示如何引入第三方包:https://flutterchina.club/get-started/codelab/ 我们直接看pubspec.yaml 这个文件 name: startup_namer description: A new Flutt
Flutter支持在不同的渠道上进行打包,可以根据不同的渠道配置不同的应用包。下面是实现Flutter多渠道打包的步骤: 1. 在Flutter项目根目录下的`android/app`目录下创建一个名为`channel`的文件夹,用于存放不同渠道的配置文件。 2. 在`channel`文件夹下创建不同渠道的配置文件,例如`channel/dev.properties`、`channel/prod.properties`等。配置文件的内容可以包括应用包名、应用名称、应用图标、应用版本号等信息。例如: # dev.properties # 应用包名 package_name=com.example.dev # 应用名称 app_name=dev_app # 应用图标 app_icon=dev_icon # 应用版本号 app_version=1.0.0 3. 在`android/app/build.gradle`文件中添加如下配置: android { // ... defaultConfig { // ... //应用包名 applicationId "com.example.app" //应用名称 manifestPlaceholders = [ appName: "My App" //应用版本号 versionCode 1 versionName "1.0.0" // ... // ... buildTypes { release { // ... //在release模式下,根据不同渠道打包 applicationVariants.all { variant -> variant.outputs.all { def outputFile = outputFileName if (outputFile.endsWith('.apk') || outputFile.endsWith('.aab')) { def fileName = outputFile.replace(".${outputFile.split("\\.").last()}", "") def channelPropertiesFile = file("channel/${variant.flavorName}.properties") if (channelPropertiesFile.exists()) { def channelProperties = new Properties() channelProperties.load(new FileInputStream(channelPropertiesFile)) outputFileName = "${fileName}_${channelProperties.getProperty("app_version")}_${channelProperties.getProperty("app_name")}.apk" output.outputFileName = outputFileName manifestPlaceholders = [ appName: channelProperties.getProperty("app_name"), appIcon: channelProperties.getProperty("app_icon") 4. 在Flutter项目根目录下运行以下命令,生成不同渠道的应用包: flutter build apk --flavor dev flutter build apk --flavor prod 其中,`--flavor`参数指定了打包时所使用的渠道配置文件。 5. 打包完成后,在`build\app\outputs\flutter-apk`目录下可以看到生成的不同渠道的应用包。 注意事项: - 渠道名称需要与`buildTypes`中的名称一致。 - 配置文件中的属性名需要与`build.gradle`文件中指定的属性名一致。 - 打包时需要分别运行不同渠道的打包命令。