How to change $(PRODUCT_BUNDLE_IDENTIFIER) in Xcode?
Asked Answered
B

1

9

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.

Brioche answered 3/2, 2019 at 19:5 Comment(0)
T
22

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

enter image description here

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)

enter image description here

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

enter image description here

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)

enter image description here

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

enter image description here

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

enter image description here

  • 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

enter image description here

enter image description here

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.

enter image description here

enter image description here

UPDATE 2

Just for completness you could change bundle id also here:

enter image description 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

enter image description here

enter image description here

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.

Tate answered 3/2, 2019 at 21:40 Comment(10)
Thanks for reply! Yes is because I use Firebase Auth for Google sign in. I have try you suggestion use PlistBuddy but still not work. If leave build script last get error: The project's Bundle ID is inconsistent with either the Bundle ID in 'GoogleService-Info.plist’, or the Bundle ID in the options if you are using a customized options I have check GoogleService-Info.plist and it have correct Bundle ID. I also check in Xcode and it have correct bundle ID. So I confused. Bundle ID in Xcode info.plist match Bundle ID in GoogleService-Info.plist but have this error message.Brioche
Thanks for update! But still have issue and strange behaviour. Maybe this can explain something. For example when run flutter run --flavor development and then after quit and run flutter run --flavor production it build correct app but open wrong one. Maybe this why I get error : The project's Bundle ID is inconsistent with either the Bundle ID in 'GoogleService-Info.plist’? Maybe there is problem with way we are change bundle ID?Brioche
@Brioche if you follow my guide and follow my road all works fine. As you can see I personally tested it. No errors man. Check your setup and put logs. Try to follow my example as straight as possible.Tate
Thanks. I follow exact. It work sometime no error! but when do more run it open wrong app after build. Try change app name for different bundle so can see.Brioche
@Brioche really? Try doing a flutter clean and flutter stop before your flutter run.Tate
Yes I have try but still error: The project's Bundle ID is inconsistent with either the Bundle ID in 'GoogleService-Info.plist’Brioche
@Brioche That’s strange. It doesn’t happen to me.Tate
Why must specify build config in every scheme? From script it will copy correct GoogleService-Info.plist file and make correct change to CFBundleIdentifier.Brioche
@Brioche Hey bro, look here. As you can see I get the error you get only when I have a misconfiguration, otherwise all works as expected. As for your question regarding specifying a build config in every scheme, that's not true. Both scheme and configs are project level configuration. Scheme has actions like build/run/archive/profile etc. and you can setup a different cofiguration to each action. I suggest you to study a little more this XCode topics in order to find out your misconfiguration.Tate
@Brioche I had the same problem: The project's Bundle ID is inconsistent with either the Bundle ID in 'GoogleService-Info.plist’, or the Bundle ID in the options if you are using a customized options I have check GoogleService-Info.plist. I solved it with placing GoogleService-Info.plist in Runner folder. After running the script in Building Phases it gets replaced and everything works OK.Uxorial

© 2022 - 2024 — McMap. All rights reserved.