如何在Xcode中更改$(PRODUCT_BUNDLE_IDENTIFIER)?

8
我正在使用不同的Firebase环境(开发和生产)构建不同风格的Flutter应用程序。 我需要在Xcode中为iOS应用程序设置不同的包标识符,以便在开发和生产中设置不同的bundle ID。
我使用方案来配置不同的风格(在Build Settings中为每个配置添加环境值)。
但是,我遇到了更改$(PRODUCT_BUNDLE_IDENTIFIER)的大问题。 我需要将后缀.development添加到正常的应用程序ID以获取开发应用程序ID。
我尝试了this method(使用用户定义的设置),并更改了info.plist以从用户定义的设置中获取变量,但它没有起作用。
错误是:
“$(EXAMPLE_BUNDLE_ID)”应用程序未知于FrontBoard。
因此,当传递用户定义的设置时,它似乎无法正确插入。
我还尝试了混合方法,添加默认的PRODUCT_BUNDLE_IDENTIFIER和用户定义的设置。例如:com.example.app$(EXAMPLE_BUNDLE_ID),其中EXAMPLE_BUNDLE_ID = .development 我也尝试直接将用户定义设置$(EXAMPLE_BUNDLE_ID)引用到“标识”下Target General选项卡中的Bundle Identifier中。但是这会变成:-- EXAMPLE_BUNDLE_ID-info.plist中,我也尝试使用$(PRODUCT_BUNDLE_IDENTIFIER)$(EXAMPLE_BUNDLE_ID)作为Bundle Identifier值。但这会出现类似的错误:
操作无法完成。应用程序“com.example.app$(EXAMPLE_BUNDLE_ID)”未知于FrontBoard。
这似乎又是一个插值问题。
有人知道解决办法吗?我已经搜索过了,但找不到答案。
对于Android来说,这很容易,只需在productFlavors中使用applicationIdSuffix ".development”。但我找不到像Xcode这样的方式。
1个回答

22
你是否需要使用Firebase Auth插件而需要在Android上使用不同的``package name``和iOS上使用不同的``bundle id``?
如果是iOS项目,在这种情况下,您应该考虑使用``PlistBuddy``并在``XCode build phases``中添加一个``Run Script``来设置它。
if [ "${CONFIGURATION}" = "Debug" ]; then
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.example.developmento.appName" "$PROJECT_DIR/Runner/Info.plist"
echo "Changed bundle id for developement $PROJECT_DIR/Runner/Info.plist"
else
echo "Nothing to do"
fi

enter image description here

无论如何,如果您不使用Firebase Auth,则可以在不同的Firebase项目中具有相同的Bundle ID。
如果您需要区分暂存和生产之间的Firebase项目文件,则可以在此处查看: 如何根据构建风格选择开发和生产Firebase项目? 更新
因此,根据OP聊天,了解他正在按照此教程设置flutter flavors,我自己尝试了一下,看看我们卡在哪里。
起点如下:
两个Firebase项目 使用Firebase Auth模块(因此需要在项目之间更改bundle id) 当然还有两个不同的GoogleService-Info.plist
我从Xcode的Bundle ID和GoogleService-Info.plist设置为生产开始(只是一个选项)。

enter image description here

然后我将GoogleServices-Info-staging.plistGoogleServices-Info-production.plist两个文件保存在我的ios/Runner文件夹中。

enter image description here

然后我在编译源代码脚本之前设置了这个构建脚本。

# Type a script or drag a script file from your workspace to insert its path.
if [ "${CONFIGURATION}" == "Debug" ] || [ "${CONFIGURATION}" == "Debug-Runner-staging" ]; then 

echo "Setting up staging firebase environment"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.example.staging.flutterAppAuthFlavours" "${PROJECT_DIR}/Runner/Info.plist"
cp -r "${PROJECT_DIR}/Runner/GoogleService-Info-staging.plist" "${PROJECT_DIR}/Runner/GoogleService-Info.plist" 
echo "$(date) staging flavour - Configuration: ${CONFIGURATION}" > "${PROJECT_DIR}/environment.txt"

elif [ "${CONFIGURATION}" == "Debug-Runner-production" ]; then 

echo "Setting up production firebase environment"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.example.flutterAppAuthFlavours" "${PROJECT_DIR}/Runner/Info.plist" 
cp -r "${PROJECT_DIR}/Runner/GoogleService-Info-production.plist" "${PROJECT_DIR}/Runner/GoogleService-Info.plist"
echo "$(date) production flavour - Configuration:  ${CONFIGURATION}" > "${PROJECT_DIR}/environment.txt"

fi

我称之为设置Firebase环境(您可以根据自己的喜好进行命名)

enter image description here

这个脚本还会将一些带有时间戳的日志存储在名为environment.txt的文件中,该文件位于ios文件夹中,以便轻松检查Xcode构建所做的工作。

enter image description here

现在让我们谈谈{{Schemes}}和{{Build Configurations}}:

我创建了两个{{Build Configuration}},它们是我的{{Debug Build Configuration}}的完全副本,并将它们命名为

enter image description here

  • 调试-Runner-staging
  • 调试-Runner-production

命名构建配置的经验法则是将其命名为'调试-<您的风味>',并且您需要为每个风味都有一个方案,因此我有以下方案:

  • Runner-staging,其运行调用调试-Runner-staging构建配置
  • Runner-production,其运行调用调试-Runner-production构建配置

enter image description here

enter image description here

现在,如果我调用flutter run --flavor Debug-staging,我就会得到一个可以在我的staging firebase项目上运行的构建版本。
如果我调用flutter run --flavor Debug-production,我就会得到一个可以在我的production firebase项目上运行的构建版本。

enter image description here

enter image description here

更新2

为了完整性,您也可以在此处更改捆绑标识符:

enter image description here

无论如何,似乎存在一种奇怪的行为,即当您第二次构建flavour时,flutter命令会正确构建flavour,但运行上一个构建的flavour
由于使用XCode构建并使用方案进行切换都按预期工作(甚至是正确应用程序的运行),因此我猜测这可能是一个flutter命令问题。因此,我建议您尝试在此处提交问题,并链接到此SO问题/答案。
更新3
经过一些调查,我发现flutter tools在构建项目之前设置了应用程序启动环境。因此,当我们第一次更改Info.plist中的CFBundleIdentifier时,第二次启动flutter run时它会获取先前修改的值并尝试启动此bundle id,而在构建期间,我们正在更改它,因为我们正在构建不同的变体。
一个可能的解决方案是在调用fluetter run之前启动更改Info.plist中的CFBundleIdentifier脚本
例如,从具有生产包idcom.example.flutterAppAuthFlavoursInfo.plist开始,我们可以这样做。

enter image description here

enter image description here

在这里我使用了sed命令来表现不同,但是在调用flutter run之前,您可以始终调用我们喜爱的PlistBuddy来进行更改。


@FlutterFirebase 如果你按照我的指南和路线走,一切都会很顺利。正如你所看到的,我亲自测试过了。没有错误,伙计。检查你的设置并记录日志。尽可能直接地按照我的示例进行操作。 - shadowsheep
谢谢。我会精确地遵循这个步骤。有时候它可以工作而且没有错误!但是当运行更多次后,构建后它会打开错误的应用程序。尝试为不同的 bundle 更改应用程序名称以便查看。 - FlutterFirebase
@FlutterFirebase 真的吗?在执行 flutter run 前尝试执行 flutter cleanflutter stop - shadowsheep
是的,我已经尝试过了,但仍然出现错误:“项目的Bundle ID与'GoogleService-Info.plist'中的Bundle ID不一致。” - FlutterFirebase
为什么每个方案都必须指定构建配置?从脚本中,它将复制正确的GoogleService-Info.plist文件并对CFBundleIdentifier进行正确的更改。 - FlutterFirebase
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接