Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a crash that happens when the application changes states. #14102

Merged
merged 7 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions FirebasePerformance/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Unreleased
- [fixed] Fix a crash related to registering for notifications when the app is between foreground or background states. (#13174)

# 11.5.0
- [fixed] Replaced usage of the deprecated `UIApplication.keyWindow` property
with `UIWindow.isKeyWindow`; this API is also available on visionOS. Note that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,17 @@ - (instancetype)init {
} else {
_traceBackgroundState = FPRTraceStateForegroundOnly;
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
});
}
return self;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,27 @@ - (void)testForegroundTracking {

/** Validates if the foreground & background state is captured correctly. */
- (void)testBackgroundTracking {
XCTestExpectation *expectation = [self expectationWithDescription:@"Application state change"];

FPRTraceBackgroundActivityTracker *tracker = [[FPRTraceBackgroundActivityTracker alloc] init];
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[defaultCenter postNotificationName:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
XCTAssertEqual(tracker.traceBackgroundState, FPRTraceStateBackgroundAndForeground);
dispatch_async(dispatch_get_main_queue(), ^{
[defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[defaultCenter postNotificationName:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
[expectation fulfill];
});

[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *_Nullable error) {
if (error) {
XCTFail(@"Expectation failed with error: %@", error);
} else {
XCTAssertEqual(tracker.traceBackgroundState,
FPRTraceStateBackgroundAndForeground);
}
}];
}

@end
51 changes: 39 additions & 12 deletions FirebasePerformance/Tests/Unit/Timer/FIRTraceTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -427,15 +427,28 @@ - (void)testValidTraceWithStageAndMetrics {

/** Validates the value of background state when the app is backgrounded. */
- (void)testValidTraceWithBackgrounding {
XCTestExpectation *expectation = [self expectationWithDescription:@"Application state change"];
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
[trace start];
[defaultCenter postNotificationName:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
[defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
XCTAssertEqual(trace.backgroundTraceState, FPRTraceStateBackgroundAndForeground);
[trace stop];
dispatch_async(dispatch_get_main_queue(), ^{
[defaultCenter postNotificationName:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
[defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[expectation fulfill];
});

[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *_Nullable error) {
if (error) {
XCTFail(@"Expectation failed with error: %@", error);
} else {
XCTAssertEqual(trace.backgroundTraceState,
FPRTraceStateBackgroundAndForeground);
[trace stop];
}
}];
}

/** Validates the value of background state when trace is not started. */
Expand All @@ -452,15 +465,29 @@ - (void)testValidTraceWithoutStart {

/** Validates the value of background state is available after trace is stopped. */
- (void)testBackgroundStateAfterTraceStop {
XCTestExpectation *expectation = [self expectationWithDescription:@"Application state change"];

NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
[trace start];
[defaultCenter postNotificationName:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
[defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[trace stop];
XCTAssertEqual(trace.backgroundTraceState, FPRTraceStateBackgroundAndForeground);
dispatch_async(dispatch_get_main_queue(), ^{
[defaultCenter postNotificationName:UIApplicationDidEnterBackgroundNotification
object:[UIApplication sharedApplication]];
[defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[expectation fulfill];
});

[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *_Nullable error) {
if (error) {
XCTFail(@"Expectation failed with error: %@", error);
} else {
[trace stop];
XCTAssertEqual(trace.backgroundTraceState,
FPRTraceStateBackgroundAndForeground);
}
}];
}

/** Validates that stages do not have any valid background state. */
Expand Down
Loading