Skip to content

Commit b88fedd

Browse files
committed
Notify Sessions when a fatal crash occurs
1 parent dc9e962 commit b88fedd

File tree

5 files changed

+64
-1
lines changed

5 files changed

+64
-1
lines changed

firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.google.firebase.crashlytics.internal.persistence.FileStore;
4444
import com.google.firebase.crashlytics.internal.settings.Settings;
4545
import com.google.firebase.crashlytics.internal.settings.SettingsProvider;
46+
import com.google.firebase.sessions.api.CrashEventReceiver;
4647
import java.io.ByteArrayOutputStream;
4748
import java.io.File;
4849
import java.io.FilenameFilter;
@@ -216,6 +217,11 @@ public Task<Void> call() throws Exception {
216217
doCloseSessions(settingsProvider);
217218
doOpenSession(new CLSUUID().getSessionId(), isOnDemand);
218219

220+
// Notify the Firebase Sessions SDK that a fatal crash has occurred.
221+
if (!isOnDemand) {
222+
CrashEventReceiver.notifyCrashOccurred();
223+
}
224+
219225
// If automatic data collection is disabled, we'll need to wait until the next run
220226
// of the app.
221227
if (!dataCollectionArbiter.isAutomaticDataCollectionEnabled()) {

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/FirebaseSessionsComponent.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ internal interface FirebaseSessionsComponent {
7070
val sessionFirelogPublisher: SessionFirelogPublisher
7171
val sessionGenerator: SessionGenerator
7272
val sessionsSettings: SessionsSettings
73+
val sharedSessionRepository: SharedSessionRepository
7374

7475
@Component.Builder
7576
interface Builder {

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/SharedSessionRepository.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ package com.google.firebase.sessions
1818

1919
import android.util.Log
2020
import androidx.datastore.core.DataStore
21+
import com.google.firebase.Firebase
2122
import com.google.firebase.annotations.concurrent.Background
23+
import com.google.firebase.app
2224
import com.google.firebase.sessions.FirebaseSessions.Companion.TAG
2325
import com.google.firebase.sessions.api.FirebaseSessionsDependencies
2426
import com.google.firebase.sessions.api.SessionSubscriber
@@ -35,6 +37,11 @@ internal interface SharedSessionRepository {
3537
fun appBackground()
3638

3739
fun appForeground()
40+
41+
companion object {
42+
val instance: SharedSessionRepository
43+
get() = Firebase.app[FirebaseSessionsComponent::class.java].sharedSessionRepository
44+
}
3845
}
3946

4047
@Singleton
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.sessions.api
18+
19+
import com.google.firebase.sessions.SharedSessionRepository
20+
21+
/**
22+
* Internal API used by Firebase Crashlytics to notify the Firebase Sessions SDK of fatal crashes.
23+
*
24+
* This object provides a static-like entry point that Crashlytics calls to inform Sessions a fatal
25+
* crash has occurred.
26+
*/
27+
object CrashEventReceiver {
28+
29+
/**
30+
* Notifies the Firebase Sessions SDK that a fatal crash has occurred.
31+
*
32+
* This method should be called by Firebase Crashlytics as soon as it detects a fatal crash. It
33+
* safely processes the crash notification, treating the crash as a background event, to ensure
34+
* that the session state is updated correctly.
35+
*
36+
* @see SharedSessionRepository.appBackground
37+
*/
38+
@JvmStatic
39+
fun notifyCrashOccurred() {
40+
try {
41+
// Treat the crash as if the app went to the background, and update session state.
42+
SharedSessionRepository.instance.appBackground()
43+
} catch (_: Exception) {
44+
// Catch and suppress any exception to avoid crashing during crash handling.
45+
// This can occur if Firebase or the SDK are in an unexpected state (e.g. FirebaseApp deleted)
46+
// No action needed, avoid interfering with the crash reporting process.
47+
}
48+
}
49+
}

firebase-sessions/test-app/src/main/kotlin/com/google/firebase/testing/sessions/MyServiceA.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class MyServiceA : Service() {
2929
Log.i(TAG, "Service A action: ${intent?.action} on process: $myProcessName")
3030

3131
// Send actions from adb shell this way, so it can start the process if needed:
32-
// am startservice -n com.google.firebase.testing.sessions/.MyServiceA -a PING
32+
// am startservice --user 0 -n com.google.firebase.testing.sessions/.MyServiceA -a PING
3333
when (intent?.action) {
3434
"PING" -> ping()
3535
"CRASH" -> crash()

0 commit comments

Comments
 (0)