Add value to Info.plist array after building (but before installing) - ios

I have an Xcode project that builds into a few different apps (whitelabels) using different configurations.
For a new payment method I need each app to have a unique CFBundleURLScheme.
I wrote the following "Run Script" that is before Compile Sources in "Build Phases".
INFO_PLIST="${PROJECT_DIR}/${INFOPLIST_FILE}"
plutil -insert CFBundleURLTypes.0.CFBundleURLSchemes.0 -string "swish${PRODUCT_BUNDLE_IDENTIFIER//.}" $INFO_PLIST
This adds the value swishourbundleidentifier. (So, swish + our.bundle.identifier, but without the dots)
This currently changes the actual Info.plist. What I want is that it changes the Info.plist that's in the folder where the app is built to, so that it is overridden each time (so there are no double values) and that the added value doesn't show up in git.
How would I go about that? I guess it's simply changing "${PROJECT_DIR}/${INFOPLIST_FILE}", but to what?
If any more information is needed, please let me know.
EDIT: Actually, if it is possible, a better solution would be to add something like swish${PRODUCT_BUNDLE_IDENTIFIER//.} in the Info.plist's URL Schemes. So that it's compiled to that on build time, but no double values. I tried this but it doesn't seem to work like that unfortunately.

You could access to build directory with
$CONFIGURATION_BUILD_DIR/$CONTENTS_FOLDER_PATH
Reference: https://help.apple.com/xcode/mac/10.2/#/itcaec37c2a6

(Xcode 11.2)
It is possible to do what you're asking:
You can get the path of the app bundle's Info.plist at ${TARGET_BUILD_DIR}/${INFOPLIST_PATH}.
BUT: In the New Build System, any custom build steps will run before the New Build System's Process .../Info.plist step, so you cannot edit the app bundle's plist via a Run Script step to Build Phases, because your changes will just be overwritten:
To run a shell script after Xcode finishes building, you can add it to your scheme(s) as a build post-action:
Product > Scheme > Edit Scheme... > Build > Post-actions
If you're going to reference any build system environment variables (e.g. BUILT_PRODUCTS_DIR or INFOPLIST_PATH), make sure you select your app target in Provide build settings from.
Add your shell script, but remember that if you edit any file in the app bundle (i.e. Info.plist), you'll need to re-sign the app. Add this to your script:
export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
/usr/bin/codesign --force --sign - --entitlements "${TARGET_TEMP_DIR}/${FULL_PRODUCT_NAME}.xcent" --timestamp=none "${CODESIGNING_FOLDER_PATH}"

App bundle is read-only. Info.plist is in app bundle

Related

Flutter: Could not find the built application bundle at build/ios/iphonesimulator/Runner.app

I am trying to run my application in debug mode from VSCode. However, every time, regardless if I am running on a simulator or a real device, the debug console outputs
Could not find the built application bundle at build/ios/iphonesimulator/Runner.app.
or
Could not find the built application bundle at build/ios/iphoneos/Runner.app.
When I went to the specified directory, my app bundle is being built every time but instead of being named Runner.app it is named MyAppName.app. I suspect the difference in name is causing the VSCode compiler to not being able to locate Runner.app.
My question: How do I change my build settings so that the build bundle is named Runner.app again?
You might have updated the Display Name from Runner to your app name
Just open your project in Xcode and Put "Runner" back in Display Name
if you want to change the application name please go into info.plist and change bundle name from there.
Note: Changing this will not effect your app’s display name.
Did you change the "Display Name" of Runner in your Xcode project? After I tried to change the "Display Name" to a custom name I got your mentioned error. After I renamed it back to "Runner" everything works fine again.
This may be caused by the value of PRODUCT_NAME in case it has a space character.
Let remove all space characters in your PRODUCT_NAME value.
Add CFBundleDisplayName key to the Info.plist if you want to config the app name (bellow the app icon).
eg.
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleDisplayName</key>
<string>$(APP_DISPLAY_NAME)</string>
// xcconfig file
PRODUCT_NAME = Flutter_App
APP_DISPLAY_NAME = Flutter Dev
Maybe you changed name of the application via xcode? Then in
ios/Runner.xcodeproj/project.pbxproj and find
PRODUCT_NAME
Then set
PRODUCT_NAME = Runner
Before Run use flutter clean && flutter run
Change App name to Runner. If this doesn't work then Select Runner->Runner(Target)->Build Settings->Packaging-> "Product Name" change it to Runner.
That will definitely work.
This happened to me when I created PUSH certificates for my app and also updated Flutter SDK.
Not sure what caused this but below solution worked for me.
To resolve this, try below measures, preferably sequentially in terminal:
cd "$(xcrun --sdk iphoneos -- show-sdk-platform-path)/DeviceSupport"
sudo ln -s 10.3.1\ \(14E8301\) 10.3
After running these commands, it should work fine, and if not, try run this command below in terminal:
flutter clean
More details :
https://xinyustudio.wordpress.com/2019/02/12/flutter-could-not-install-build-ios-iphoneos-runner-app/
https://medium.com/#xinyustudio/flutter-could-not-install-build-ios-iphoneos-runner-app-1f355f18c9d9

Could not get GOOGLE_APP_ID in Google Services file from build environment

For setting up firebase i am using two config 1.GoogleService-Info-test.plist, 2.GoogleService-Info-prdn.plist for UAT and Production. For installing crashlytics using firebase i have followed firebase documentation https://firebase.google.com/docs/crashlytics/get-started?authuser=1#ios. But when i try to run, it throws error in build phase while running script.
I tried without changing config file name and it worked.
Error msg at build phase while running fabric run script "Could not get GOOGLE_APP_ID in Google Services file from build environment".
Can anyone suggest better solution to achieve my requirement.
This is one way you can do it, by having your projects environments separated by targets, by doing so you can then add your different plist files and just check the target that they belong to, that way when you compile the target it will take it's corresponding plist file
Another way to do it, or to look up how to do it, it's called multiple environments with firebase, here are some helpful links
Use different GoogleService-Info.plist for different build schemes
https://medium.com/rocket-fuel/using-multiple-firebase-environments-in-ios-12b204cfa6c0
This worked for me:
When install Crashlytic with Firebase, for multiple scheme, you can have error Could not get GOOGLE_APP_ID in Google Services file from build environment. You can fix it by:
In Build Settings, add a user define for file name in User Defined:
In Build Phases, tap plus button, New Run Script Phase above your Crashlytic build phase, and type this code to the text field. Remember to rename %YOUR_CUSTOM_PATH_TO_FOLDER% to your path to Plist files:
GOOGLE_SERVICE_INFO_PLIST_FROM="${PROJECT_DIR}/%YOUR_CUSTOM_PATH_TO_FOLDER%/${FIREBASE_CONFIG_FILE}.plist"
BUILD_APP_DIR="${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}"
GOOGLE_SERVICE_INFO_PLIST_TO="${BUILD_APP_DIR}/GoogleService-Info.plist"
cp "${GOOGLE_SERVICE_INFO_PLIST_FROM}" "${GOOGLE_SERVICE_INFO_PLIST_TO}"
This worked for me:
Make sure you add the Xcode Crashlytics build phase after Copy Bundle Resources.
I had this in my "Build Phases" and it's works
"${PODS_ROOT}/FirebaseCrashlytics/run"
"${PODS_ROOT}/FirebaseCrashlytics/upload-symbols" -gsp "${PROJECT_DIR}/MyApp/GoogleService-Info.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
Our project only one target, but we need to use two Firebase config files GoogleService-Info-Prod.plist and GoogleService-Info-Dev.plist.
I had this in my "Build Phases" and it works.
if [ "${CONFIGURATION}" = "Release" ]; then
${PODS_ROOT}/FirebaseCrashlytics/run -gsp ${PROJECT_DIR}/RushCard/FirebaseConfig/GoogleService-Info-Prod.plist
else
${PODS_ROOT}/FirebaseCrashlytics/run -gsp ${PROJECT_DIR}/RushCard/FirebaseConfig/GoogleService-Info-Dev.plist
fi
In my case I created New Run Script Phrase above Compile Sources, that's why I always see
Could not get GOOGLE_APP_ID in Google Services file from build environment
When I moved Crashlytic's run script at the end of list bug was disappear. Please look the following screen shot:
And article about it is here
I use multiple configurations for several white-labelled apps. I added a User-Defined variable FIREBASE_SUFFIX and changed my script to the following:
${PODS_ROOT}/FirebaseCrashlytics/run -gsp ${PROJECT_DIR}/Firebase/GoogleService-Info-${FIREBASE_SUFFIX}.plist
NOTE: I use Carthage for firebase here: https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md. If you're this same setup, you should use something like this instead (replace the path to where you put your script files):
${PROJECT_DIR}/scripts/run -gsp ${PROJECT_DIR}/Firebase/GoogleService-Info-${FIREBASE_SUFFIX}.plist
Another way is to make sure one plist keeps the original name GoogleService-Info.plist
Different targets meant more work to update CI for me.
This is valid for Xcode 11 at least, not tested on any other versions
I was using new Firebase/Crashlytics which beta and getting error "No Google App ID or Google Services file provided" when I try to upload manually dSYMS
Here is command:
/path/to/pods/directory/FirebaseCrashlytics/upload-symbols
-gsp/path/to/GoogleService-Info.plist -p ios /path/to/dSYMs
Then I reliaze there should be space between "-gsp" and path to Google.plist after that It worked.
The solution for me was removing the call to upload-symbols script.
One of the Crashlytics guides mentions you should add this:
${PODS_ROOT}/FirebaseCrashlytics/run
/path/to/pods/directory/FirebaseCrashlytics/upload-symbols <- Not needed
I misinterpreted this... the run script already calls upload-symbols so there's no need to add a second call.
Make sure in Xcode file explorer (i.e on the left side) "GoogleService-Info.plist" is showing. If not you have to drag and drop "GoogleService-Info.plist" in the Xcode panel.
In my case problem is I copy-pasted the file in the project location, due to this file reference is missing in the Project info.
Well all above answers purpose a possible solution for this issue, in my case GoogleService.plist file was missing from 'Copy Bundle Resources' by adding into it worked in my case..
To check the file goto
Project Directory >> Build Phases >> Copy Bundle Resources
add it add here if you find missing.
If these solutions provided above do not work, I solved mine by going to Build phases as shown on this image. Click on plus and add Google plist
I was able to fix this by locate where is my GoogleService-Info.plist, copy it to ios folder in Flutter and run with this script
"$PODS_ROOT/FirebaseCrashlytics/upload-symbols" --flutter-project "$PROJECT_DIR/firebase_app_id_file.json" -gsp "$PROJECT_DIR/GoogleService-Info.plist" -p ios "$DWARF_DSYM_FOLDER_PATH/$DWARF_DSYM_FILE_NAME"
Update:
I found a better solution:
Just upgrade all firebase package to lastest version
Remove Crashlytics build script
Run flutter clean, flutter pub get
pod install (in ios folder)
I had this issue because I didn't download GoogleService-Info.plist file from Firebase console.
If you have your project on Firebase but missing this file in Xcode, don't worry, you don't need to do the setup again from the beginning. Just go to:
Project Settings > General > Scroll down and in the "Your Apps" panel you will see the file and you can download it and import it in the Xcode project.
I had the same error, also due to the fact that I have multiple bundle identifier and therefore I have a build phase script called Firebase Script (that pinpoints to the correct GoogleService-Info.plist ) that was running after the Crashlytics script.
The solution is to run Firebase Script before the Crashlytics script.
In my case I had a different name in my file, his name was GoogleService-Enterprise-Info.plis when I change it to the normal name GoogleService-Info.plist, IT WORK FINE !!
I faced the same issue for #react-native-firebase/crashlytics
In case you are facing this issue, you probably have missed the 'ios setup' instruction mentioned in below link. Please follow the instruction to fix the issue.
https://rnfirebase.io/#generating-ios-credentials
Just download from Settings of your projects and place for your correct target which you are running.
This error would be shown if there is a space in your project name or in the path of your project.
Read more in this GitHub Issue
Additionally to other answers..
I faced that problem with exact same error message and in my case everything was ok with file GoogleService-Info.plist except that it was genereated with wrong Bundle ID for application (it was changed in XCode much later than initial Firebase setup happened), so I had to create new app in Firebase Console with correct Bundle ID (it's not able to edit) and download new GoogleService-Info.plist
If you are using one of the popular build scripts going around for handling multiple different environments, it is probably useful to know that you should use a different GoogleService-Info.plist destination based on the target platform:
// iOS
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
// watchOS
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.appex
// macOS
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Resources
Ultimate guide:
Assure that in Runner folder you have file GoogleService-Info.plist and it is attached in your project
If you don't have this file go to Firebase Console, add you IOS app and download the GoogleService-Info.plist file, then add it to you project's Runner folder by XCode.
If there is no such file in XCode but it exists physically in the folder then right click on Runner folder (in Runner project) -> Add files to Runner -> Select that file
If you want to use multiple flavors add ENV_SUFFIX in Runner (target) -> Build Settings -> User-Defined (on the bottom)
Still in the target's Runner change tab to Build Phases -> Press Plus button -> New Run Script Phase -> Name it as Copy GoogleService-Info.plist and add this line
cp Runner/GoogleService-Info_${ENV_SUFFIX}.plist Runner/GoogleService-Info.plist
IMPORTANT! This script has to be before Initialize Crashlytics step or any other Firebase related script (you can drag it to the top)
Add other GoogleService-Info.plist files with suffix for the env. In my case those would be the _dev _prod and _tst files from the first screen shot
Enjoy multiflavor app
Try downgrading, it worked for me!
I used:
'Fabric', '1.9.0'
'Crashlytics', '3.12.0'

Where is the Run Script and Build Phase in Xcode?

To get Carthage set up, the documentation says that you need to add a Run Script.
On your application targets’ “Build Phases” settings tab, click the
“+” icon and choose “New Run Script Phase”. Create a Run Script in
which you specify your shell (ex: bin/sh), add the following contents
to the script area below the shell:
/usr/local/bin/carthage copy-frameworks
and add the paths to the frameworks you want to use under “Input
Files”, e.g.:
$(SRCROOT)/Carthage/Build/iOS/Box.framework
$(SRCROOT)/Carthage/Build/iOS/Result.framework
$(SRCROOT)/Carthage/Build/iOS/ReactiveCocoa.framework
This script works around an App Store submission bug triggered by
universal binaries and ensures that necessary bitcode-related files
and dSYMs are copied when archiving.
However, I can't find the Build Phases tab anymore or Run Script in the Build Settings search. The Xcode 8 Release Notes mention
Xcode 8 provides completely rewritten AppleScript support. A new
scripting dictionary provides the ability to automate Xcode workflows.
Does that mean there is no more Run Script? I looked at AppleScript but honestly it looks overwhelmingly complex. Do I need to learn AppleScript just to add the simple one liner that I used to do in Xcode?
/usr/local/bin/carthage copy-frameworks
It is still there. Make sure you click everywhere indicated in red in the image below.
Carthage maintainers updated README, it is necessary to add output paths too to prevent useful copying of frameworks. I have released simple script named Carting to automate these steps.

React Native running app on device without server

Its unbelievable how bad the documentation is for React Native, they just put as little as possible for everything. I've already managed to run my app using option 1 but option 2 is even more unclear: https://facebook.github.io/react-native/docs/running-on-device-ios.html
I don't know there's no example of the terminal command react-native bundle in full so I know what is actually required there. For example --entry-file <path> what path? The whole path from my hard drive root to this folder, or just the file itself? --bundle-output....? What the hell do I need to put for that? I don't know why they need to make it so damn unclear.
I'm surprised there's no other resources online that give the instructions more clearly. I guess that's why there aren't so many React Native apps on the app store.
I hope you also find that this is a much easier approach. In the example below, my app was named BleMobileApp. Feel free to change it to your app's name.
RUN APP ON DEVICE WITHOUT DEBUG SERVER
Duplicate the main deployment target and name it BleMobileApp-Deploy.
Make sure to REMOVE the DEBUG=1 flag in BleMobileApp-Deply's Build settings (Do not touch the original target BleMobileApp!)
Add a New Run Script Phase to BleMobileApp-Deploy's Build phases and paste following command:
yes | cp -rf ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/main.jsbundle $SRCROOT/main.jsbundle
That's it!
(OPTIONAL) In case you would like to MINIFY the JS Bundle!
Edit file ./node_modules/react-native/scripts/react-native-xcode.sh like below (Line 43~47)
2. Change the default run script like below (For BleMobileApp-Deploy target):
export NODE_BINARY=node
FORCE_MINIFYING=true ../node_modules/react-native/scripts/react-native-xcode.sh
This should do the trick for you.
Happy coding!
From React Native Docs:
Configure release scheme Building an app for distribution in the App Store requires using the Release scheme in Xcode. Apps built for Release will automatically disable the in-app Developer menu, which will prevent your users from inadvertently accessing the menu in production. It will also bundle the JavaScript locally, so you can put the app on a device and test whilst not connected to the computer.
To configure your app to be built using the Release scheme, go to Product → Scheme → Edit Scheme. Select the Run tab in the sidebar, then set the Build Configuration dropdown to Release.
This can be done from the terminal:
react-native run-ios --device "My iPhone" --configuration Release
the best way i could find,
just follow the step bellow
Product → Scheme → Edit Scheme
Select the Run tab in the sidebar
Build Configuration dropdown to Release
sometimes metro bundle starts, may be its bug in IOS but you can close it
Please see the attached screenshot

Target Properties changes by xcodebuild command

How can i manipulate my iOS Target Properties by xcodebuild command tool ?
In example, i have one project with one target and with Facebook SDK Key in Target Properties in Info tab
FacebookAppID: 01234567891234
And with console command xcodebuild i'm compiling two Apps with Developer and Production provisions with two console commands:
For Developer:
xcodebuild -project Projectname.xcodeproj clean install OBJROOT=ObjRoot ... CODE_SIGN_IDENTITY={iPhoneDeveloper} PROVISIONING_PROFILE="Dev.mobileprovision"
For Distribution:
xcodebuild -project Projectname.xcodeproj clean install OBJROOT=ObjRoot ... CODE_SIGN_IDENTITY={iPhoneProduction} PROVISIONING_PROFILE="Prod.mobileprovision"
And i need use in Developer one FacebookAppID, and in Production a other FacebookAppID, and how i can change my command lines for realize this?
Thanks
Arguments to xcodebuild are best used for values that change every time they're invoked, like a destination directory that includes a build number.
For data as foundational as a Facebook app ID, I'd recommend using your build configurations, e.g. "Debug" and "Release". Create a user-defined build setting (in Xcode 5.0.2, Editor -> Add Build Setting -> Add User-Defined Setting) named something like "FACEBOOK_ID", and in your Info.plist, set your desired key's value to ${FACEBOOK_ID}. In your target's build settings, define FACEBOOK_ID differently for your Debug and Release configurations. Your code then now has to pull the current value out of Info.plist at runtime.
If you really want to override build settings as arguments to xcodebuild, you can do so, just by adding "FACEBOOK_ID=12341234" to the end of the command, but this only works if you've done the work I just described to make FACEBOOK_ID into a configuration-specific build setting. I can't think of any sound reasons to keep this kind of app data outside of a build configuration.
If build configurations are new to you, I'd suggest starting with WWDC 2012 session 408, "Working with Schemes and Projects in Xcode".

Resources