简体   繁体   中英

How to change $(PRODUCT_BUNDLE_IDENTIFIER) in Xcode?

I am build different flavor of Flutter app with different Firebase environment (development and production). I need set different bundle ID for development and production in Xcode for iOS apps.

I am use schemes to configure the different flavor (in Build Settings I add environment value for every configuration).

But I have big issue with change $(PRODUCT_BUNDLE_IDENTIFIER) . I need add suffix .development to normal app id for development app id.

I have try follow this method (use User Defined Settings) and change info.plist to get variable from User Defined Settings but it not work.

Error is:

The operation couldn't be completed. Application “$(EXAMPLE_BUNDLE_ID)" is unknown to FrontBoard.

So it seem when pass in User Defined Setting it is not interpolate correct.

I have also try mix method of add default PRODUCT_BUNDLE_IDENTIFIER and User Defined Settings. For example: com.example.app$(EXAMPLE_BUNDLE_ID) where EXAMPLE_BUNDLE_ID = .development

I also try reference User Defined Setting $(EXAMPLE_BUNDLE_ID) by direct add it to Bundle Identifier in Target General tab under 'Identity'. But this then change to : -- EXAMPLE_BUNDLE_ID-

I have also try in info.plist use $(PRODUCT_BUNDLE_IDENTIFIER)$(EXAMPLE_BUNDLE_ID) for Bundle Identifier value. But this give similar error:

The operation couldn't be completed. Application “com.example.app$(EXAMPLE_BUNDLE_ID)" is unknown to FrontBoard.

Again this look like interpolation issue.

Anyone know solution? I have look but cannot find answer.

This easy for android because just use applicationIdSuffix ".development” in productFlavors . But I cannot find way like this for Xcode.

Do you need to have different package name (Android) and bundle id (iOS) because you need to use Firebase Auth plugin?

In this case for iOS project you shold consider using PlistBuddy and you could set it adding a Run Script in your XCode build phases like that

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

在此处输入图片说明

Anyway if you don't use Firebase Auth , you can have the same bundle id in different firebase projects.

If you need then to differenziate firebase projects file between staging and production, you could have a look here:

How to choose between development and production firebase project based on build flavours?

UPDATE

So following OP chat, knowing that he's following this tutorial to setup flutter flavors I've tryed myself to see where we were stuck.

Starting point is the following:

  • Two Firebase project
  • Use of Firebase Auth module (so the need to change the bundle id between projects)
  • And of course two different GoogleService-Info.plist

I start with Xcode bundle id and GoogleService-Info.plist set to production (just an option)

在此处输入图片说明

Then I've save both GoogleServices-Info-staging.plist and GoogleServices-Info-production.plist save in my ios/Runner folder

在此处输入图片说明

Then I setup this build script before the script for Compile Sources

# 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

And I called it Setup Firebase Environment (you can call it what you want)

在此处输入图片说明

This script store also some logs (with timestamp) in a file called environment.txt inside ios folder in order to easy check what xcode build has done

在此处输入图片说明

And now about Schemes and Build Configurations :

I've done two Build Configuration that are the exact copy of my Debug Build Configuration and I called them

在此处输入图片说明

  • Debug-Runner-staging
  • Debug-Runner-production

The rule of thumb is to name the build configurations as 'Debug-<your flavor>' and you need to have a scheme for every flavors you have, so I have these:

  • Runner-staging whose Run calls Debug-Runner-staging build configuration
  • Runner-production whose Run calls Debug-Runner-production build configuration

在此处输入图片说明

在此处输入图片说明

So now if I call flutter run --flavor Debug-staging I have a build that runs on my staging firebase project.

and if I call flutter run --flavor Debug-production I have a build that runs on my production firebase project.

在此处输入图片说明

在此处输入图片说明

UPDATE 2

Just for completness you could change bundle id also here:

在此处输入图片说明

Anyway it seems that there's a strange behavior that once you build a flavour a second time flutter command build correctly the flavor but run the previos build flavor .

As building with XCode and switching with schemes all works as expected (even the run of the right application) I guess that this could be a flutter command issue. So I suggest you trying file an issue here linking also this SO question/answer.

UPDATE 3

After a bit of intel I've found that flutter tools set the applicaiton launching environment before building the project. So when we change CFBundleIdentifier inside Info.plist the first time, the second time we launch flutter run it takes the previous modified value and try launching this bundle id while during build we are changing it because we are building a different variant.

A possible solution could be to launch a script that change the CFBundleIdentifier inside Info.plist before calling fluetter run .

For example starting with a Info.plist with a production bundle id of com.example.flutterAppAuthFlavours we could do something like that

在此处输入图片说明

在此处输入图片说明

Here I've used sed command just to think different, but you could call always our belowed PlistBuddy to make the change before calling flutter run .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM