Integrating Firebase Crashlytics for iOS Widget extensions for multiple environments— Part III
In this tutorial, we will be looking at how to add Crashlytics to your iOS widget extension.
I will suggest you have a quick look at Part-I and Part-II of this tutorial in case you have not integrated firebase in your application. Links are appended at the end too.
Requirement
All the crashes that occur in your widget should be reported in the Development/Testing and Production stages. The development/testing crash should get logged in the Development project and Production crashes should be logged in Production.
Prerequisite
I have assumed that you have integrated the Widget Extension into your application and added FirebaseCrashlytics to your project. I also assume that you are working with Cocoapods.
Problem
Having ONE GoogleService-Info.plist which reports all the crashes in one project
Having just one Project on Firebase and only one app for all the environments was getting messy as it was getting difficult to identify for which target the crash was happening. Below is the list of environments we had to deal with and will be used as an example
Environment
Development, QA, and Release.
Solution:
I have created a new project on the firebase dashboard and added 3 applications Dev, QA, and Release to it.
Note: If you want to learn how I created multiple apps follow first part of this series at https://bit.ly/3rv4K38
Download all the 3 GoogleService-Info.plist and put them in the respective folder.
for eg. The plist created for development will reside in Widget --> DEV
,
QA plist will be in Widget --> QA
and Release plist to Widget --> Release
.
The arrangement looks something like this.
OPTIONAL:
You can add these plist to your widget extension, BUT you should not link them. Unchecking the check box ensures that you do not end up copying all the plist into the bundle.
Adding shell-script to copy the correct plist to Widget Bundle
How to ensure that the correct plist is added to the widget bundle and we will get crashes for it?
For that, we will be writing a script that takes care of copying the correct Plist for a given Environment to the bundle. I will add the script and will try to explain how it works.
I have saved the script as widgetscript.sh
in folder shell script at the root of the project.
Get the source path
For selecting the correct plist path we need the following things:
1. Bundle Identifier
- We have added all the bundle id’s that would be used
2. Environment
- Dev, QA, RELEASE
Based on Bundle identifier
we figure out the Environment
.PLIST_LOCATION
is created by appending these with the plist name.
Here is an exampleFirebase/${Environment}/GoogleService-info.plist
that becomesFirebase/DEV/GoogleService-info.plist
your source path if the bundle ID id com.blacksheep.dev
Get the destination path
The destination is simple to create; which is basically the path to the final WidgetExtension.appex ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.appex
Copy the plist from source to destination
Once we have both the locations, we copy the plist from the source to the destination path.
Adding shell-script to Xcode
Open Xcode and go to Build Phases of Widget Target.
Tap on the + icon on the left of the window and select New Script Phase.
Add shellscript/widgetscript.sh
to the project. This will run the custom shell script after building the target.
The script is added and now it’s time to build the application and check if the correct plist is copied. Once the script is executed you can open the path at ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.appex
to check if the correct plist is copied.
In case you encounter errors while building apps, we have added logs at appropriate places to help you resolve the issue.
Issue:
If your build fails with below error, you need to provide permission to run the shell-script./Users/username/Library/Developer/Xcode/DerivedData/CrashlyticsDemoApp-afuovelrzqqgzdazlyioykmuqloh/Build/Intermediates.noindex/CrashlyticsDemoApp.build/Debug-iphonesimulator/CrashlyticsDemoApp.build/Script-AFD5C5B026AD46BB001BF8AA.sh: line 2: shellscript/widgetscript.sh: Permission denied
Fix:
Open terminal and navigate to location of widgetscript.sh and run following command on terminal.chmod 755 widgetscript.sh
Issue:
Bundle-id does not match with the bundle-id specified in plist file.Fix:
Check the bundle id of your widget target and the GoogleService-info.plist.
Both should match.
Issue:
Error message when bundle identifier is not valid or when the plist is not present at a valid path or the path is incorrect. Fix these before moving ahead.Fix:
Check if the Plist is present in the folder
Final Steps
If everything works correctly you will see the correct GoogleService-info.plist
at the location ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.appex
. You can check the build status in the Project navigator to get the path of the installed app.
Let’s verify if the correct plist was copied to the bundle.
You may open the CrashlyticsWidgetExtension.appex
from the project and see the Package contents to check if the GoogleService-Info.plist is present.
Configuring firebase to Widgets Extension
Go o your Widget file and configure crashlytics. Something like this
Add -FIRDebugEnabled
in your Arguments passed on launched
for your widget scheme. This will show any issues with firebase in your XCode console. Something like this:
Crash in Firebase console
Once this is done. Add a forced crash in your code and check the firebase console.
Important:
1. If you are running the app in debug mode configuration, you need to set theDebug Information Format
toDWARF with dsym File
. This will report crashes from simulator or device when running in debug format.
2. You will not see any crashes when connected to Xcode in debugging mode. You need to crash and reopen the app without running from Xcode in debugging mode.
3. The first crash reports in 15 mins if above 2 steps are followed. Have some patience, it’s not your fault.
And that’s how we are done with crashlytics setup for your widget.
I have added a complete project here. If you are stuck do use this project to solve your problem.
Did I miss any use cases? Let me know down in the comments. If you still face issues while adding crashlytics let me know in the comments below. I will be more than happy to help you.