Search code examples
androidandroid-activityfirebase-cloud-messagingandroid-notificationsandroid-lifecycle

Launcher Activity's onStart() called before PendingIntent destination activity launched when Application is in Background State


I am showing notification when FCM message received in onMessageReceived. I am launching a intermediate UI less activity (PushTracker activity) to do preprocessing of the notification before navigating to destination activity.

I have MainActivity as default launcher activity.

Problem: When app is in foreground/killed state, and notification from FCM is clicked, PushTracker is getting called first before anything. Here I will do preprocessing and will navigate to destination screen.

When app goes to background(On pressing home button), and when FCM notification is clicked, First App's Default Launcher Activity(onStart()) is getting called. Then after this only , oncreate() of PushTracker Activity configured in PendingIntent.

Important thing here, it is happening only in Android 11 and below. In Andorid 12 and above, PushTracker activity is always called first as expected.

One WorkAround: If I made MainActivity launch mode as singleInstance in AndroidManifest, in Android 11 and below it calls PushTracker first as expected. But in my case I cannot make this change.

I need to figure out why Launcher Activity's onStart() is getting called.

I am using Data Payload in FCM and handle Navigation myself. Not using notification payload. Couldn't get much information about this issue.

In App Foreground / Killed state , PushTracker is called first before anything on PushClick in all android versions. So its having issue only in App Background state and that too in Android 11 and below.

Any leads / solution will be much appreciated.

Additional Context: The exact reason to fix is, I am using ApplicationLifecycleObserver. I need to check whether application is in Foreground/Background in PushTracker and do processing based on it. Since LauncherActvity's onStart() is getting called, the ApplicationLifecycleObserver onStart() and becomes foreground even when app is in background. In PushTracker application_foreground is always true in this case in Android 11 an below.
But when app is background in Andorid 12 and above, and PushTracker is launched first, application_foreground is false in that time as expected. (This is my expectation in other case also)

Notification:

    private fun sendNotification(remoteMessage: RemoteMessage) {
    Log.d(TAG, "Message:$remoteMessage")
    val notification = remoteMessage.notification
    val requestID = System.currentTimeMillis().toInt()
    val intent = Intent(this,PushTracker::class.java)
    intent.putExtra("remoteMessage",Gson().toJson(remoteMessage))
    intent.flags = Intent.FLAG_ACTIVTIY_NEW_TASK
    val pendingIntent = PendingIntent.getActivity(this, requestID, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
    val defaultSoundUri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
    val notificationBuilder: NotificationCompat.Builder =
        NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_1)
            .setLargeIcon(
                BitmapFactory.decodeResource(
                    resources,
                    android.R.drawable.ic_lock_idle_alarm
                )
            )
            .setSmallIcon(android.R.drawable.ic_lock_lock)
            .setContentTitle(notification?.title ?: "DEFAULT BODY")
            .setContentText(notification?.body ?: "DEFAULT TITLE")
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent)
    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
    notificationManager?.notify(0, notificationBuilder.build())
}

MainActivity

  class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)
    Log.d(TAG,"onStart()");
}

override fun onStart() {
    super.onStart()
    Log.d(TAG,"onStart()");
}
}

MainActivity Manifest:

    <activity
     android:name=".MainActivity"
        android:exported="true"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

PushLanding Activity:

public class PushTracker : FragmentActivity() {


override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //UI Less Activity for Notification Processing and redirection to destination will be handled here
}
}

PushTracker Manifest:

<activity
    android:name=".PushTracker"
    android:configChanges="orientation|screenSize"
    android:noHistory="true"
    android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />

Solution

  • I am able to solve this by making PushTracker activity as singleInstance in Manifest.

    Result:

    <activity
        android:name=".PushTracker"
        android:configChanges="orientation|screenSize"
        android:noHistory="true"
        android:launchMode="singleInstance"
        android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
    

    Root Cause: For standard and other launch modes, on clicking on notification,Pending intent is always routing to destination activity through launcher activity in Android 11 and below. So onStart() of Launcher Activity is getting called first.

    If we make destination activity as singleInstance, it will work independently work and so pending intent will not call Launcher Activity's onStart()