Skip to content

TransparentActivity crashes with NullPointerException on null intent action (TransparentActivity.kt:35) #1255

Description

@solkennedy

Bug

TransparentActivity.onCreate crashes with a NullPointerException when the activity is created with a null intent action. The offending line uses a Kotlin non-null assertion:

https://github.com/GetStream/stream-video-flutter/blob/main/packages/stream_video_push_notification/android/src/main/kotlin/io/getstream/video/flutter/stream_video_push_notification/TransparentActivity.kt#L35

val broadcastIntent = IncomingCallBroadcastReceiver.getIntent(this, intent.action!!, data)

When the plugin launches TransparentActivity itself, getIntent(...) always sets intent.action, so the happy path is fine. But the Android framework can recreate the activity with no action set — e.g. after process death / restore from recents, or a system relaunch (the activity carries FLAG_ACTIVITY_NO_HISTORY). In that case intent.action is null and !! throws before the Flutter engine is involved, so it cannot be caught from Dart.

Stack trace (production Crashlytics, stream_video_push_notification 1.4.0)

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{<app>/io.getstream.video.flutter.stream_video_push_notification.TransparentActivity}: java.lang.NullPointerException
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3433)
       ...
Caused by java.lang.NullPointerException:
       at io.getstream.video.flutter.stream_video_push_notification.TransparentActivity.onCreate(TransparentActivity.kt:35)
       at android.app.Activity.performCreate(Activity.java:7994)

Versions

  • stream_video_push_notification: 1.4.0 (also present in 1.3.1 — code is byte-identical)
  • Reproduces on the current main.

Suggested fix

Guard the null action instead of asserting. If there's no action there is nothing to dispatch, so just finish:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val data = intent.getBundleExtra("data")
    val action = intent.action ?: run {
        // System can recreate this activity (process death, relaunch from
        // recents) with a null action; nothing to dispatch, so finish instead
        // of crashing on a non-null assertion.
        finish()
        overridePendingTransition(0, 0)
        return
    }

    val broadcastIntent = IncomingCallBroadcastReceiver.getIntent(this, action, data)
    broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
    sendBroadcast(broadcastIntent)

    val activityIntent = AppUtils.getAppIntent(this, action, data)
    startActivity(activityIntent)

    finish()
    overridePendingTransition(0, 0)
}

Happy to open a PR (will link it here).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions