Firebase Analytics events from iOS not showing up - ios

I am testing the new Google-powered Firebase, and have implemented remote notifications and crash reporting. I am, however, having massive problems with getting Analytics to work.
I track events with FIRAnalytics.logEventWithName(...) and save user pproperties with FIRAnalytics.setUserPropertyString(...). However, no matter what I do, no data shows up in the Firebase Analytics Console.
Well, I do receive some events, but those are not sent by me (like first_open and session_start). Also, this data seems to drop in after a very long time.
Furthermore, when I track events and save user data, I receive the following:
Upload task scheduled to be executed in approx. (s): 3102.294599890709
This seems really strange - Firebase waiting almost an hour before trying to send the next batch of data must be a bug, or is it configurable? When I waited that extremely long delay out, data was sent...but does not show up.

Firebase events are batched together and uploaded once every hour in order to prevent excessive battery drain on the devices. On iOS when you background the app before the 1h upload target the events will be dispatched at this time in the background.
You can enable debug logging for iOS (https://firebase.google.com/docs/analytics/ios/events#view_events_in_the_xcode_debug_console) to see when events are uploaded in debug console.
Once the events are uploaded there is delay at about 3h before the data will show up in the Firebase Analytics dashboard. Also the default day range excludes "today" so you only see events from yesterday. You can switch the date picker to include Today if you like to see the latest events.
The main reason to delay/batch data uploading is to save battery. Each time the network is used the device mobile network modem is put in hi power mode and stay in this mode for a while. If network is used regularly it has sever impact on the battery life. By batching the uploads together and delaying the upload the impact on the battery is significantly reduced.

In Swift it should be like:
FIRAnalytics.logEvent(withName: "SignUp", parameters: ["user_id": userid, "user_name": username])
To view this event in Firebase:
Go to Firebase console → Analytics tab
Click on DebugView tab; your Events are shown there
To view this event in Xcode:
In Xcode, select Product → Scheme → EditScheme
Select Run from left Menu
Select Arguments tab
In the Arguments Passed on Launch, add -FIRAnalyticsDebugEnabled
One dash only!!
Note that -FIRAnalyticsDebugEnabled has only ONE dash in front of it.

If you are not receiving events in console, it may be because you are not following naming convention, as I experienced if there is a space in event name it will never show up in the console like following:
mFirebaseAnalytics.logEvent("Add Camera", bundle);
But when you remove the space like following:
mFirebaseAnalytics.logEvent("Add_Camera", bundle);
Now you will see events in console, after approximately 3 hours.
Application will dispatch the data to console in following cases:
1- Data is more than an hours old
2- App goes into the background
You can watch this tutorial for more information:
Getting Started with Firebase Analytics on iOS: Events - Firecasts

Another thing to check is making sure your logging entries in the Arguments Passed on Launch are correct. They should start with a - e.g
-FIRAnalyticsDebugEnabled
and not
FIRAnalyticsDebugEnabled
I wasted an hour the other day wondering why nothing gets logged.

React-Native App (IOS/Android)
I had the same problem, debugView wasn't working, and streamView glitches a few times, the best way ive found to test my events was to logEvents with my createPageEvent() and then
the important thing is to put the app into background after logging the events, they will show up almost in realtime on firebase events or in streamView (check this article to see when events are sent to firebase)
events are only sent after 1 hour since they have been logged or immediately if you put your app in background.
import firebase, { RNFirebase } from 'react-native-firebase';
export default class AnalyticsService {
static async initialize() {
firebase.analytics().setAnalyticsCollectionEnabled(true);
}
static async createPageEvent(screen: string) {
firebase.analytics().setCurrentScreen(screen)
firebase.analytics().logEvent(`open_${screen}`)
}
}
the result is this in streamView almost realtime ->
Now you can start building funnels and stuff

first_open, session_start are listed by Firebase as Automatically collected events.
I can not help you with the extreme upload task delay you encounter on your custom events.. but Firebase Analytics is less than a week old and it may be just a bug on their side.
I found this StackOverflow question which mention the same debug lines but related to Google App Measurement or old Google Mobile Analytics SDK.
Also, be aware that Firebase Console won't show events in real-time (source):
You can view aggregrated statistics about your events in the Firebase console dashboards. These dashboards update periodically throughout the day. For immediate testing, use the logcat output as described in the previous section.

Just a simple note here: according to this little video https://www.youtube.com/watch?v=5pYdTgSkW5E after playing with your simulator you must press the home button on the Xcode, otherwise the data will not be sent to the server.

The most common problem most of the people are facing is the firebase is not logging events even though everything is working perfectly fine
This is what i found in there docs
If you need to deactivate Analytics collection permanently in a version of your app, set FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED to YES in your app's Info.plist file. Setting FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED to YES takes priority over any values for FIREBASE_ANALYTICS_COLLECTION_ENABLED in your app's Info.plist as well as any values set with setAnalyticsCollectionEnabled.
To re-enable collection, remove FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED from your Info.plist. Setting FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED to NO has no effect and results in the same behavior as not having FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED set in your Info.plist file.
So you have to remove FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED from your google-servicesinfo.plist file to make analytics work

Make sure your device is not set to battery save mode. In this mode events may be accumulated and sent only once in a while, even if you run firebase in debug mode as explained by others.

It takes too much time to update events in Firebase. Probably it is done once a day. See iOS or Android logging of Firebase events.
You can enable verbose logging to monitor logging of events by the SDK
to help verify that events are being logged properly. This includes
both automatically and manually logged events.
You can enable verbose logging as follows:
In Xcode, select Product > Scheme > Edit scheme...
Select Run from the left menu.
Select the Arguments tab.
In the Arguments Passed On Launch section, add
-FIRAnalyticsDebugEnabled.
The next time you run your app, your events will display in the Xcode
debug console, helping you immediately verify that events are being
sent.

Related

Firestore local cache is stale when returning to mobile app - can I force a re-sync?

I'm watching a cloud firestore list for changes using query.onSnapshop in a react-native-firestore app, currently testing on iOS.
While my app is in the foreground, I can make data changes elsewhere (eg. in my companion web app) and the mobile app immediately updates as expected. Usually, if I make changes while the app is closed or offline, they get picked up no problem once it is re-opened or comes online again. Happy days.
However, sometimes, when the app is in the background (not closed, just some other apps have been used in the meantime), I'll make a change elsewhere (eg. add/delete a record which meets the query's criteria), then when I come back to the app, the list does not change - eg. it contains deleted records, or doesn't contain the new ones. Nothing I do on the app can change this - it remains out-of-sync, even if I make local changes, like editing one of the records (even a deleted one). Changing network conditions also does nothing (eg. switching airplane mode off/on again).
The only way the list will get back in sync is if I make another change elsewhere, while the app is still in the foreground, or if I force-close the app and re-open it again.
The issue seems to occur when connecting to both the emulator, and the actual firestore.
I don't think I'm doing anything fancy. Basically following the examples in the documentation:
import React, { useEffect, useState } from 'react';
import firestore from '#react-native-firebase/firestore';
const MyAssignments = (props) => {
const [records, setRecords] = useState([])
useEffect(() => {
const onSnapshot = (snapshot) => {
console.log(snapshot) // this IS triggered but data is stale
setRecords(snapshot)
}
return firestore()
.collection('assignments')
.where('assignedTo', 'array-contains', props.userId)
.onSnapshot(onSnapshot, console.error);
}, [props.userId]);
// render the list
return ...
}
I'm not sure if this is a general firestore issue, a react-native-firebase issue, an issue with the underlying firebase ios SDK, or just my own misunderstanding?
In either case, is there a way to force the local cache to re-sync programatically, ideally when the app regains focus? Or has anyone solved a similar issue or have any ideas what to try next?
Edit 1: Note the code example above is slightly simplified for readability, as parts are spread across a few files and typed with typescript. In reality, I'm using crashlytics.recordError(e) for error handling in production, but console logging, as above, in development.
Edit 2: To debug, I've tried the following:
Switch on debug logging:
import firebase from '#react-native-firebase/app';
firebase.firestore.setLogLevel('debug');
However, this gave no extra logs in my javascript console.
I found I could view native device logs by following this guide and then filtering for Firebase, like so: idevicesyslog --match Firebase
This still shows very few logs, so I don't think debug logging is switched on properly. However, it does log this error every time I foreground the app:
<Notice>: 8.9.1 - [Firebase/Firestore][I-FST000001] WatchStream (10c244d58) Stream error: 'Unavailable: Network connectivity changed'
This error happens every time though. Even when the onSnapshot successfully picks up changes

Firebase Analytics seemingly works perfect, but just won't show up?

In a large app which uses Firebase extensively, I'm trying analytics,
-FIRDebugEnabled is set fine.
The date/time on the devices is set correctly.
I have tried all of simulator, tethered device, and even building through to TestFlight.
The needed stuff is in app startup ..
FirebaseConfiguration.shared.setLoggerLevel(.max)
FirebaseApp.configure()
// helps Analytics get going:
AnalyticsConfiguration.shared().setAnalyticsCollectionEnabled(true)
Again, Firebase realtime and database works perfectly throughout.
So using Analytics.logEvent# ...
Note that the items appear perfectly in Xcode console:
2018-07-24 08:27:23.868 Blah[7501] <Debug> [Firebase/Analytics][I-ACS023105] Event is
not subject to real-time event count daily limit. Marking an event as
real-time. Event name, parameters: select_content, {
firebase_event_origin (_o) = app;
firebase_realtime (_r) = 1;
item_name = tapMyProfile;
firebase_screen_class (_sc) = Blah.SomeScreen;
firebase_debug (_dbg) = 1;
firebase_screen_id (_si) = 8314738347840858914;
item_id = Blah-tapMyProfile;
content_type = tapMyProfile;
}
or ...
2018-07-24 08:56:12.393306-0500 Blah[7501:135963] [Firebase/Analytics][I-ACS023073] Debug
mode is enabled. Marking event as debug and real-time. Event name,
parameters: select_content, {
firebase_event_origin (_o) = app;
firebase_screen (_sn) = MyProfile;
item_name = tapCamera;
firebase_realtime (_r) = 1;
firebase_screen_class (_sc) = Blah.OldDevDotScreen;
firebase_debug (_dbg) = 1;
firebase_screen_id (_si) = 8314738347840858915;
item_id = Blah-tapCamera;
content_type = tapCamera;
}
Notice tapMyProfile or tapCamera, one of my custom events from Analytics.logEvent#
Analytics as such does seem to be working perfectly:
so, those numbers update every few hours etc.
Again every item appears perfectly in the Xcode console ..
But no matter what, nothing will show up on the Firebase debug console!
Nothing!
What the hell could the problem be?
(Additionally I have waited a day or more and they don't show up as events either.)
How can it be that just nothing is showing up in Debug???
TL:DR - Delete your app from your device / simulator, rebuild and launch from XCode.
I faced this exact same issue even though Firebase and Firebase Analytics in particular seemed to be set up perfectly.
I cannot give the exact logical explanation yet as to why this worked, however one hint came from this Firebase events tutorial at around 5 mins 30.
He mentions that the -FIRAnalyticsDebugEnabled settings get saved to disk.
So after configuring & integrating Firebase, I ran my app which was already installed to test everything works fine and it did but the Firebase Console did not show me any messages of app events.
It's good to double check that you are not using special characters when sending your events and also not going over the character threshold, however even if you make these errors, you should see default events of screen_open, app_open, user_engagement which were not showing up for me.
My only theory is that launching the app from an already installed state does not impact the new settings of -FIRAnalyticsDebugEnabled.
So when I deleted my app, re-build and run from XCode, the events start showing up.
Finally, while testing, you might use another device and you might wonder, I was seeing my events from the previous device but nothing happens for the next one which baffled me for a few moments, remember to switch the device
However, in conclusion, I can say this behavior is far from reliable and because after a period of time (2-3 hours) when I ran my app again, nothing showed up on the Firebase Console again as if -FIRAnalyticsDebugEnabled had been disabled.
Deleting and reinstalling worked again.
Update for 2022
The above steps still applies. Just 2 more additions of why you might not see events you seem to be logging successfully:
Do a clean + build + run
There are some keywords that seem to not get logged because they are probably already in use by the Analytics framework. For example when I was trying to track a search event and one of the keys in my parameters dictionary was keyword and this never seemed to get tracked so use something else and give it a go
Check your device's time setting. Time needs to be accurate.
Did you enable Debug View for your app?
As per the docs, there is a minor difference on enabling debug events on the real-time and debug view that is embedded into Firebase Console UI.
To enable Analytics Debug mode on your development device, specify the following command line argument in Xcode :
-FIRDebugEnabled
For real-time logs on XCode console for the Arguments Passed On Launch section, add:
-FIRAnalyticsDebugEnabled.
It is been a long time since this question has been post. I have been struggling with this problem for over a week.
Everything was ok in my side, I saw it worked, like yours, in the Xcode debug mode. My issue was I did not look to the Debug View which is under the Analytics -> DebbugView in Firebase Console
Here is Debug View at the end of the analytics: Debug View
Documents in Firebase is here: In the firebase documents but the image is old.
It is in Analytics -> Debug View
Hope this will help someone!
Simply select which device you want from this "DebugDevice" dropdown menu. It's on the top left corner.
(It was driving me crazy for couple of hours! I hope Google will improve the UI of Firebase)
Make sure that the logged event name is longer than 40 characters, there is a limit for the length of the event name and parameter name.
https://support.google.com/firebase/answer/9237506?hl=en
Maybe it's not related to the question above, but I think it could help someone. Here's my case:
I was misunderstanding about when the user engagement update, I was thinking that it would be updated immediately after I've sent the event!
But it's not. You must to wait.
If you're wondering that, have you been successful sent the event to the board or not. You should check on the Debug-View section.

NSURLSessionDownloadTask move temporary file

I'm trying to reach the file which I was downloading earlier by NSURLSession. It seems I can't read the location of the file, even though I'm doing it before delegate method ends (as the file is temporary).
Still, I'm getting nil when trying to access the data under location returned from NSURLSession delegate and error 257.
The code goes as following:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
NSError *movingError = nil;
NSData *fileData = [NSData dataWithContentsOfFile:location.path options:0 error:&movingError]; // is nil
NSLog(#"%#", movingError); // is error 257
}
What's wrong with this code..? I saw similar questions NSURLSessionDownloadTask - downloads but ends with error and iPhone - copying a file from resources to Documents gives an error but these completely doesn't apply to my case.
-- edit --
I've created a new project and pasted the very same code. It works... So:
1) In my project I'm receiving error 257, probably some configuration of the project is invalid or the fact I'm using backgroundTasks somewhere else in the app messes things up
2) Same as in 1 happens if I put the source files of this download to the external framework linked in by Carthage
3) On demo project I created (copy-pasted files used in 1 & 2) everything works corretly.
If someone has an idea what can cause the fact it isn't working - would be awesome.
Late to the discussion, but I've seen the same/similar issue and investigated.
With my investigation, what you are seeing is expected (should I say “it's observed”?).
But since I'm not 100% sure how you are using URL session, I put down below what I'm trying to do, followed by my observations (important ones only).
Also, I created a sample project and put it here as downLoader.zip. You can play and check how URL session background download works. But It's better to read thru below before trying to play, though this is fairly a long note.
A. what I'm trying to do
I'm developing kind a map app, where I need to download 1000+ of small size (0.5-150kB, mostly ~20kB) PNG files at a time. Total download size of them is ~50MB, and it takes a couple of minutes to download all of them. I think that keeping users to my app just waiting for download is bad design, so I made the app to use URL Session’s background download.
I have to admit, however, that Apple’s doc says that “Background sessions are optimized for transferring a small number of large resources that can be resumed as necessary.” So, the way I’m using background session is totally opposite. But, anyway...
B. what I've observed
Below, I’ve listed my observations and my guess of why. I should say guess since they are not documented.
(1) observation: sometimes, files that should come with didFinishDownlaodingTo don’t exist.
Temporary files are put at:
/var/mobile/Containers/Data/Application/randomHexString/Library/Caches/com.apple.nsurlsessiond/Downloads/yourName.yourApp. The randomHexString changes from app’s run to run. When the files don’t exist, the randomHexString that came with didFinishDownloadingTo is the one from the “previous” session. Now, “previous” here means the session at app’s previous run !, which clearly doesn't exist at the current session at current run.
There's another scenario for non-existent file, which is that the randomHexString is ok, but the files don't exist. This seems to happen after session cancel is requested (invalidateAndCancel) and before session becomes invalid (didBecomeInvalidWithError).
Guess: This happens especially on the development phase since we terminate the app while downloading, manually or by debugger or just by bug. It seems once the download requests are handed and accepted to the OS, the OS handles our requests even after the app quits. Note we can’t know if the OS has definitely accepted the requests or not. Even after the return from URLSessionDownloadTask:resume(), sometimes files don’t exit at the next launch and sometimes they do.
Workaround: If files don’t exist, just ignore them. In a while, “this time’s” files should come.
(2) observation: sometimes, the duplicated (same) files come with didFinishDownloadingTo.
My app converts downloaded PNG files to other format. W/in didFinishDownlaodingTo, I move temp files (== OS designated) to another my app’s directory, then spawn thread (GCD) to convert the format and delete downloaded temp files. So, the other thread (didFinishDownlaodingTo) to overwrite is an issue.
Workaround: I make list of URLSessionTask:taskIdentifier and w/in didFinishDownlaodingTo, check the duplication by retrieving the taskID list to ignore duplicated files.
(3) observation: even after the user terminated the app, OS relaunches the app again.
After the user terminated the app from task switcher, quite often, the OS relaunches the app w/ application:handleEventsForBackgroundURLSession:completionHandler.
Note the sequence of relaunch is that didFinishLaunchingWithOptions comes first as regular launch, then handleEventsForBackgroundURLSession comes next.
From user’s POV, when he/she terminated the app, that’s it, done! It looks strange even after they terminated the app, it relaunches in itself and notifies something to them. It's like a zombie.
Guess: The Apple’s document says “If the user terminates your app, the system cancels any pending tasks”. The definition of “pending tasks” is not clearly stated but I understand this is from iOS POV and not user’s or program developer’s. As guessed in (1), iOS seemed to have accepted the download requests, and they are not “pending tasks” anymore.
Workaround: I create a “flagFile” after all of download requests are handed to iOS w/ URLSessionDownloadTask:resume(), of which file means that “download is ongoing”. When users terminate the app, at UIApplicationDelegate:applicationWillTerminate, I delete the flag file. Or, if all of download requests not handed to iOS, there's no flag file. Then at app’s relaunch at UIApplicationDelegate:handleEventsForBackgroundURLSession, I check if we have the flag file. If missing, then I can assume that users terminated. Two choices here. Choice-1: I will not recreate URL session. What happens next is that iOS will terminate my app in about 20 seconds. I have no idea if this (== not creating the URL session) is a legal operation but it works. Users can launch w/in this 20 sec, so I put some more code to handle that scenario. Choice-2: I create URL session. What happens next is that iOS calls delegate methods didFinishDownlaodingTo/didCompleteWithError, followed by urlSessionDidFinishEvents. If I don't do anything here, the process (app) keeps alive indefinitely w/o any notification to users: nothing in task switcher. This is nothing more than waste of memory. The option here is to fire local notification and let users know of my app, so that they can go back to my app and can terminate (Again!), though my app clearly appears as a zombie. One issue for both choices: applicationWillTerminate may not be called in certain situation (though I've yet confirmed). At this case, flag file is left as regular ops and show zombie to users. So, the flag file method is just mitigation to the issue, but I think it works most of the time for my app.
Note the app is relaunched sometimes when it's killed by xcode debugger or killed by OS w/ bug (SEGFALUT).
(4) observation: after the app is terminated (by user, etc.) then relaunched by OS, the app is occasionally in active state (UIApplication.shared.applicationState is .active).
I want to notify the user on the download completion by local notification, but since it's active, local notification doesn't fire. So, I need to use UIAlertController instead. Therefore, I can't provide consistent user experience, and should look strange for users: most of the time local notification and very occasionally UIAlert. Note when app started in active state, it appears in task switcher.
Guess: totally no idea how this can happen. One good(?) thing is this happens only occasionally.
Workaround: seems none.
(5) observation: handleEventsForBackgroundURLSession/urlSessionDidFinishEvents is called just once.
I start the download after started background task (application.beginBackgroundTask). Then in expiration handler of beginBackgroundTask, I call endBackgroundTask. I don't know exactly why, but after endBackgroundTask, my process is still given lots of process time, so I can keep requesting download. This might be because download files keep coming w/ didFinishDownlaodingTo. To be a good citizen, I suspend to request further download, and fire local notification to user to put the app to foreground. Now, once I suspend the request, in 4-5 seconds, OS determines the URL session is over and handleEventsForBackgroundURLSession then urlSessionDidFinishEvents are called. This is one-off event. When the user put the app in foreground to resume download, then put it again in background, no handleEventsForBackgroundURLSession/urlSessionDidFinishEvents will come anymore. What's unclear to me is the definition of session's start and end. It seems the session starts at first URLSessionTask.resume(), then ends w/ timeout, which seems to be determined by URLSessionConfiguration.timeoutIntervalForRequest. However, setting large number here (1000 sec) doesn't affect anything, it's always 4-5 seconds.
Guess: no idea
Workaround: don't relay on urlSessionDidFinishEvents while the app is alive. Relay only when app relaunched by OS and at initial handleEventsForBackgroundURLSession/urlSessionDidFinishEvents.
===============
Below, I listed about the sample project (downLoader.zip). You can verify all of above with the sample.
The app has a list of download files. The number of files is 1921, and 56MB in total. They are 256x256 PNG map tile files that are located in a server managed by Geo Spatial Information Authority of Japan (GSI). After downloaded, they are moved to Library/Cache/download. If your device is jail-broken, you can view them w/ Filza.
crash itself to test relaunch
emulate background task expiration
logging to file since debugger doesn't work after relaunch by OS. The file is in Documents, can be moved to PC.
Do play with the real device. Simulator doesn't relaunch the app.
Project built w/ Xcode 8.3.3 and tested w/ iphone6+/9.3.3 and iphone7+/10.3.1
To see if app relaunched w/ xcode, go to Debug/Attach to Process menu and see if downLoader is listed.
===============
I think URL session background download behaves trickily, especially at relaunch. We need to consider at least the observations I listed above, or the app users will get confused.
I found same error code 257 from online users feedback.In the error scene, the location always refers to a strange bundle identifier:com.sdyd.SDMobileMixSmart. And I guess this's an apple system bug.

How to check application state under swift UI Test

Some background
I am currently writing a UI Test for a settings pane, and click on buttons to enable certain permissions such as push notifications and location services.
However, if the alert for the permission has been displayed before (regardless of the user allowing or denying access to the permission), the alert will not display again, and will just take the user to the settings app. Unfortunately, these settings do not reset, meaning the first time I run the UI tests, alerts will show; and on all subsequent UI test runs, the buttons will take me to the settings app unless I reset the device before the tests begin.
My issue
Thus, my test needs to know if the app went into the background, and attempt to foreground it to continue the testing:
if app.state == background {
foregroundApp()
}
// continue with other tests
Is there any way to determine if the app is in the background?
What I tried
I researched methods to determine the state of the application (running/background/etc) from a UI test, and was not able to find much. I tried to check whether certain elements exist:
if (app.navigationBars.element.exists) ...
but this gives me runtime errors[1] if the user is taken to the settings page because the app under test is in the background, and the test cannot lookup the navigationBars (or other elements).
I tried using some of the methods from Facebook's private headers for XCUIApplication() and XCUIElement().
XCUIApplication().state always returns 3 no matter what state the app is currently in, and any attempts to call XCUIApplication().resolve() to foreground the app give me the same errors as before[1]
I tried to rewrite the logic to foreground the app before resuming the tests, but methods such as XCUIApplication().launch() kill the app before restarting, which I cannot do. Only siri service seems to work for me, but I cannot access the siri service through the corporate proxy, and modifying proxy permissions is not possible.
Is there any other way to check the app state?
Errors
[1] This error is printed every time I try to do something involving state. I do not call snapshotView anywhere, and thus the suggestion to use afterScreenUpdates is useless.
Failure to get snapshot within 15.0s
Cannot snapshot view (<UIKeyboardImpl: 0x7febcc75d000; frame = (0 0;
414 226); layer = <CALayer: 0x608000625720>>) with
afterScreenUpdates:NO, because the view is not in a window. Use
afterScreenUpdates:YES.`
tl;dr
I need to check whether the app I am UI testing has entered the background (i.e. user pressed the home button). Checking for existence of particular elements such as navigation bars doesn't work, neither do most methods from Facebook's private headers for XCUIApplication/XCUIElement. Foregrounding the app also causes issues, and relaunching the app is not an option; neither is siri service.
You can do this in Swift 4, using XCUIApplication.state, which will give you information about the state of the app - whether it's in the foreground or background etc. however, it's not possible to find this information in Swift 3 and below. Essentially, UI testing in Swift 3 doesn't support leaving the app.

MobileFirst Platform Operational Analytics - Log Screen Visit Times and Custom Crash Details

I'm developing an iOS app using MFP 7.0.
Each screen (i.e., view controller) has a unique ID, and I am supposed to use Operational Analytics to send the following info to the server:
How long the user spent on each screen
On which screen the app crashed
Regarding #1, I guess I am supposed to use WLAnalytics's
- (void) log:(NSString*)message withMetadata:(NSDictionary*)metadata;
(right?)
How can I manage #2? Should I just log the screen ID (using the method above) every time a transition occurs, and expect the last logged id to be passed when the crash log is sent? Or is there any other way to add custom information to crash logs?
Correct you can follow Custom Data, Custom Charts here https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/7.0/moving-production/operational-analytics/
Crash log is detected and sent automatically post crash next time app is started. There is no way to add custom data to that report. Usually the place where the error happen could be deduced form the crash data stack, if this is not sufficient, you can apply the technique you are describing.

Resources