以前都是准备几台不同的 android 手机安装不同环境的包,如果想一个手机安装不同环境的包,只能删了重新打然后重新安装。
解决问题的根本原因是,构建不同环境的包,假设我有三个环境
- Staging -> .env.Staging -> com.duolegamehelper.staging - Alpha -> .env.alpha -> com.duolegamehelper.alpha - Production -> .env.production -> com.duolegamehelper.production
|
那么我就打包的时候,通过不同的.env
配置文件,动态的把包名和 APP 的名字打进去。
研究了半天,其实react-native-config
是可以解决这个问题的,只不过需要修改打包的gradle
脚本。
react-native-config
安装完了react-native-config
以后,准备自己的不同环境的.env
文件到项目的根目录。
➜ DuoleGameHelper git:(main) ✗ find . -type f -name ".env*" ./.env.production ./.env.alpha ./.env.staging
|
APP_PACKAGE_NAME='com.duolegamehelper.alpha' APP_NAME='Alp-Duole'
|
iOS
iOS
还没整明白,先整 android 的…
iOS
比较特殊,就算是控制台能运行,将来打包还是得打开Xcode
…
这里我在网上找到了一个比较可行的方法。
Xcode 创建不同环境的scheme
- 复制几个和默认相同配置的
scheme
,然后build
> Pre-actions
,输入脚本
记得勾选Shared
…
rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}" echo ".env.alpha" > /tmp/envfile
|
"${SRCROOT}/../node_modules/react-native-config/ios/ReactNativeConfig/BuildXCConfig.rb" "${SRCROOT}/.." "${SRCROOT}/tmp.xcconfig"
|
- 创建
Config
项目右键New file
> 搜索Config
> Save as iOS/Config
输入以下内容:
- 注意配置
Config
清除缓存
ios-cache-cleaner.sh
#!/bin/bash
echo "Cleaning Xcode DerivedData..." rm -rf ~/Library/Developer/Xcode/DerivedData/*
echo "Cleaning iOS build folder..."
echo "Cleaning Watchman cache..."
|
构建脚本
package.json
里面添加不同scheme
的构建脚本
"run:ios:bate": "./ios-cache-cleaner.sh && react-native run-ios --scheme \"JP-Bate\"", "run:ios:staging": "./ios-cache-cleaner.sh && react-native run-ios --scheme \"JP-Staging\"", "run:ios:alpha": "./ios-cache-cleaner.sh && react-native run-ios --scheme \"JP-Alpha\"",
|
运行
chmod +x ios-cache-cleaner.sh ./ios-cache-cleaner.sh && react-native run-ios --scheme "JP-Alpha"
|
Android
修改build.gradle
,
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
def appName = project.env.get("APP_NAME") ?: "Def-Duole" def timeStamp = new Date().format("yyyyMMdd_HHmmss") def packageName = project.env.get("APP_PACKAGE_NAME") ?: "com.duolegamehelper"
|
修改 APP 的包名
这是这一讲的核心内容 …
- applicationId "com.duolegamehelper" + applicationId project.env.get("APP_PACKAGE_NAME")
|
修改 APP 在桌面上面展示的名字
resValue "string", "app_name", appName
|
修改 APP 构建时候的文件名
我想每次打包的时候,
`${环境名}-${APP名}-${时间戳YYYY-MM-DD HH:mm:ss}.apk`,
|
android.applicationVariants.all { variant -> if (variant.buildType.name == "release") { variant.outputs.all { outputFileName = "${project.env.get("APP_NAME")}_${timeStamp}.apk" } } }
|
打包命令
ENVFILE=.env.staging ./gradlew assembleDebug ENVFILE=.env.production ./gradlew assembleRelease
|
react-native-config -> Config.xxx 读取不到配置
现在原生层面的问题解决了,但是之后会发现:
import Config from "react-native-config"; Config.APP_PACKAGE_NAME; Config.APP_NAME;
|
都是拿不到东西的。
我们要明白react-native-config
的本质是打包的时候生成BuildConfig
,然后读取里面的内容。
翻看源代码发现,他是通过build_config_package
来进行反射,
然后找到生成的BuildConfig
,
/Users/net.cctv3.i/DuoleGameHelper/android/app/build/generated/source/
➜ ~ cd /Users/net.cctv3.i/DuoleGameHelper/android/app/build/generated/source/ ➜ source git:(main) ✗ tree . └── buildConfig ├── debug │ └── com │ └── duolegamehelper │ └── BuildConfig.java └── release └── com └── duolegamehelper └── BuildConfig.java
|
也就是说,不管你打的什么环境的包,他读取的永远是com.duolegamehelper.BuildConfig
。
所以,
- def packageName = project.env.get("APP_PACKAGE_NAME") ?: "com.duolegamehelper" - resValue "string", "build_config_package", packageName + resValue "string", "build_config_package", "com.duolegamehelper"
|
这个build_config_package
是不同加环境后缀的。
useEffect(() => { if (Platform.OS == "android") { let constants = NativeModules.SystemModule.getConstants(); console.log("NativeModules.SystemModule.getConstants(): ", constants); console.log("react-native-config: ", Config); } return function () {}; }, []);
|
{ "DEBUG": true, "IS_NEW_ARCHITECTURE_ENABLED": false, "VERSION_CODE": 1, "APP_NAME": "Sta-Duole", "APP_PACKAGE_NAME": "com.duolegamehelper.staging", "IS_HERMES_ENABLED": true, "BUILD_TYPE": "debug", "APPLICATION_ID": "com.duolegamehelper.staging", "VERSION_NAME": "1.0" }
|