拒绝魔改,flutter多渠道构建版本

用flutter开发项目一段时间后,发现切换环境实在太麻烦,每次都手动修改环境,随着参数的越来越多, 很容易就忘记修改哪个参数,导致环境切换出问题,所以就想到了android以前做是可以做多渠道的,所以也想试试flutter的多渠道。

准备工作

flutter命令

在 Flutter 1.17 中,Flutter 会将在编译前将 dart-defines 传递给 iOS、Android、macOS。

因此,可以几乎在各个时刻调用预先定义的 dart-defines。


--dart-define=DART_DEFINE_APP_ENV=debug

flutter端处理

  • 声明环境变量

// 声明的环境

abstract class EnvName {

  // 环境key

  static const String envKey = "DART_DEFINE_APP_ENV";

  // 环境value

  static const String debug = "debug";

  static const String release = "release";

  static const String debugServer = "debugServer";

}

  • 声明环境配置

///环境配置

class EnvConfig {

  ///服务器url

  final String? host;

  EnvConfig(

      {this.host

      });

}

  • 环境定义

// 开发环境

  static final EnvConfig _debugConfig = EnvConfig(

      host: "http://129.211.191.80:10003/app",

  );

  // 后端本地服务器

  static final EnvConfig _debugServerConfig = EnvConfig(

      host: "http://192.168.1.162:10003/app",);

  // 发布环境

  static final EnvConfig _releaseConfig = EnvConfig(

      host: "https://api.dzds.dianzedushu.com/app");

  • 获取当前环境

// 获取到当前环境

  static const appEnv = String.fromEnvironment(EnvName.envKey);

就是通过 String.fromEnvironment 来获取当前环境,然后根据环境去取不同的值

  • 根据环境获取相关配置

static EnvConfig _getEnvConfig() {

    switch (appEnv) {

      case EnvName.debug:

        return _debugConfig;

      case EnvName.debugServer:

        return _debugServerConfig;

      case EnvName.release:

        return _releaseConfig;

      default:

        return _releaseConfig;

    }

  }

环境变量使用


static String ServerUrl = Env.envConfig.host!;

编译


flutter run --dart-define=DART_DEFINE_APP_ENV=debug

这样编译的app 就是你设置的环境

效果


附加

这样又会有另一个问题,每次都要通过命令编译,那有没有办法通过ide 直接来编译呢. 下面就介绍如何通过ide 来编译

AS

点开下图的地方

AS.png

在 additional run args 里面添加 --dart-define=DART_DEFINE_APP_ENV=debug

然后重复添加 release.

如下图


编译的时候选择对应的选项.

vs code

替换 launch.json 里面的内容


{

    // 使用 IntelliSense 了解相关属性。

    // 悬停以查看现有属性的描述。

    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387

    "version": "0.2.0",

    "configurations": [

        {

            "name": "flutter_app_2_0_debug",

            "request": "launch",

            "type": "dart",

            "args": [

                "--dart-define",

                "DART_DEFINE_APP_ENV=debug",

            ]

        },

        {

            "name": "flutter_app_2_0_server",

            "request": "launch",

            "type": "dart",

            "args": [

                "--dart-define",

                "DART_DEFINE_APP_ENV=server",

            ]

        },

        {

            "name": "flutter_app_2_0_release",

            "request": "launch",

            "type": "dart",

            "args": [

                "--dart-define",

                "DART_DEFINE_APP_ENV=release",

            ]

        }

    ]

}

在调试模式里面选择对应的环境.

原生多渠道

上面只能修改flutter 自己的环境, 有时候我们需要用到第三方库,需要再原生环境里面配置不同的数据,这时候怎么办呢.别急.来看看我怎么替换原生环境数据的

以我项目为例, 我接入的融云sdk 需要配置不同环境的key.

iOS

ios 是通过 xcconfig 来生成变量的.

我们再 user-define 里面发现 DART-DEFINES 里面会多一个 flutter.inspector.structuredErrors 值, 这个貌似不符合xcconfig的key定义.所以处理方式是把这个值给处理掉. 然后根据dart-defines 获取当前环境 然后通过脚本生成xcconfig.

如图. 新建一个 scheme.


在如图位置 添加脚本.


脚本代码


# Type a script or drag a script file from your workspace to insert its path.

function urldecode() { : "${*//+/ }"; echo "${_//%/\\x}"; }

IFS=',' read -r -a define_items <<< "$DART_DEFINES"

debug_env=DART_DEFINE_APP_ENV=debug

debug_server_env=DART_DEFINE_APP_ENV=debugServer

for index in "${!define_items[@]}"

do

    define_items[$index]=$(urldecode "${define_items[$index]}");

done

if [ ${#define_items[*]} > 1 ]; then

    # # echo ${#define_items[*]}

    # echo $define_items

    if [ ${define_items[0]} = $debug_env ]; then

        define_items[1]=RONGYUN=@"\"lmxuhwagl66vd\""

    elif [ ${define_items[0]} = $debug_server_env ]; then

        define_items[1]=RONGYUN=@"\"lmxuhwagl66vd\""

    else

        define_items[1]=RONGYUN=@"\"z3v5yqkbz22m0\""

    fi

    # unset define_items[1]

fi

# if [ ${#define_items[*]} > 0 ]; then

#    define_items

# fi

# fi

# echo ${define_items[1]}

# printf $define_items

# unset define_items[1]

# printf $define_items

# printf "$s\n" "${define_items[@]}"

printf "%s\n" "${define_items[@]}" > ${SRCROOT}/Flutter/DartDefines.xcconfig

这样就在 flutter 目录生成了 DartDefines.xcconfig文件

Debug.xcconfigRelease.xcconfig 分别引用这个文件.

编译后 就可以看到 RONGYUN 被添加到 用户定义的key里面去了

使用

在 Flutter 目录新建一个 Dart.xcconfig文件


DART_DEFINE_APP_ENV=release

#include "DartDefines.xcconfig"

GCC_PREPROCESSOR_DEFINITIONS = $(inherited) RONGYUNKEY='$(RONGYUN)'

Debug.xcconfigRelease.xcconfig 分别引用这个文件.


NSString * rongyunKey = [RONGYUNKEY stringByAppendingPathExtension:@""];

    //生产环境

    [[RCIMClient sharedRCIMClient] initWithAppKey:rongyunKey];

android

安卓主要通过gradle 来生成

定义多渠道的值

在项目根目录新建一个 dart.properties 文件

添加如下内容


debug=rongyun=lmxuhwagl66vd,

debugServer=rongyun=lmxuhwagl66vd,

release=rongyun=z3v5yqkbz2

通过gradle 来生成环境值

在 app 下面的 build.gradle 的 android 里面添加如下内容


/// 设置默认配置参数

    def dartDefine = [

            DART_DEFINE_APP_ENV: 'debug',

    ]

    if (project.hasProperty('dart-defines')) {

        dartDefine = dartDefine + project.property('dart-defines')

                .split(',')

                .collectEntries { entry ->

                    def pair = URLDecoder.decode(entry).split('=')

                    [(pair.first()): pair.last()]

                }

    }

    println(dartDefine)

    def dartFile = rootProject.file("dart.properties")

    def dartProperties = new Properties()

    dartProperties.load(new FileInputStream(dartFile))

    println(dartProperties)

    def currentEvn = dartDefine.DART_DEFINE_APP_ENV

    println(currentEvn)

    def currentProperties = dartProperties["$currentEvn"]

//

    println(currentProperties)

    dartDefine = dartDefine + currentProperties

            .split(',')

            .collectEntries { entry ->

                def pair = URLDecoder.decode(entry).split('=')

                [(pair.first()): pair.last()]

            }

    println(dartDefine)

在 defaultConfig 中的 manifestPlaceholders 添加 RONGYUN : dartDefine.rongyun.

androidmanifest.xml 中定义 meta


<meta-data

            android:name="RONGYUN"

            android:value="${RONGYUN}" />

java中使用


val appInfo: ApplicationInfo = this.packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)

val rongyunKey: String? = appInfo.metaData.getString("RONGYUN")

RongIMClient.init(this, "$rongyunKey")

这样就完全做到了多渠道构建!

码字不易!!!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,302评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,563评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,433评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,628评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,467评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,354评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,777评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,419评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,725评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,768评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,543评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,387评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,794评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,032评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,305评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,741评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,946评论 2 336

推荐阅读更多精彩内容