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:
Firebase project
Firebase Auth
module (so the need to change the bundle id between projects)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 configurationRunner-production
whose Run calls Debug-Runner-production build configurationSo 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
.