urbanairship / android-library

Urban Airship Android SDK
Other
109 stars 123 forks source link

App opens on top of browser for Web Page push notification #219

Closed sergiucc closed 1 year ago

sergiucc commented 1 year ago

Preliminary Info

What Airship dependencies are you using?

What are the versions of any relevant development tools you are using?

Report

What unexpected behavior are you seeing?

When opening a notification with Web Page URL content, if the app is closed, the browser is opened first and the app on top of it

What is the expected behavior?

The browser should open after the app being visible on top as the relevant content from the push notification

What are the steps to reproduce the unexpected behavior?

Do you have logging for the issue?

No

laura-turo commented 1 year ago

This is happening in 16.8.0 too

Same steps as described above 🔝

rlepinski commented 1 year ago

@laura-turo @sergiucc Actions are run after the app is launched.

How are you launching the app from a notification? Allowing Airship to handle it? Do you have a splash screen activity that is launching an activity on top?

sergiucc commented 1 year ago

@rlepinski Airship handles the notification, and yes, the launcher activity triggers navigation to another activity in my case.

rlepinski commented 1 year ago

@sergiucc My guess is that what is happening is notification -> launcher activity -> web page --> another activity

Usually when this happens the launcher activity does not stop during onPause, and will still launch the intent for the another activity after that.

laura-turo commented 1 year ago

yes, that's our case too, we are launching an activity on the Splash.

I have tried to override the notificationListener#onNotificationOpened but looks like Airship still opens the browser on the background (inside OpenExternalUrlAction), looking at the source code there's no way I can avoid that behaviour, is it?

So I'd like to manually create my Task Stack as shown below

override fun onNotificationOpened(notificationInfo: NotificationInfo): Boolean {
    val url =
        notificationInfo.message.actions[OpenExternalUrlAction.DEFAULT_REGISTRY_SHORT_NAME]?.string

    if (url == null || uAirship.urlAllowList.isAllowed(
            url,
            UrlAllowList.SCOPE_OPEN_URL
        ).not()
    ) return false

    TaskStackBuilder.create(application)
        .addNextIntent(HomeNavigation.newIntentForHomeActivity())
        .addNextIntent(WebViewNavigation.newCustomTab(url = url))
        .startActivities()

    return true
}

So this code works as expected, but Airship still opens an independent browser

rlepinski commented 1 year ago

@laura-turo

The problem is most likely in the splash screen activity. Could you explain how it works? If it where to be launched and immediately backgrounded, does it still launch the next activity? Usually this can be addressed by using a livedata or some other mechanism that can check activity state before launching. If its paused or stopped, dont launch the next activity, wait til its foregrounded again.

What you are trying to achieve can be done, but you need to disable the standard web view action in that case. You can set a predicate on the action to disable it for notification open situation, however I would strongly advise you look into your splash screen activity first.

laura-turo commented 1 year ago

Our splash screen is defined as singleTask in manifest. It makes a BE call, depending on the response we launch diff activities. If I put the splash screen on background it does not launch the next activity.

rlepinski commented 1 year ago

Ok, could you gather verbose airship logs for me with added log lines for your splash screen activity when onPause, onResume, and when you launch your activity. We can start there to see if anything obvious stands out. Let me know if you need to email me the logs instead of sharing them on here.

rlepinski commented 1 year ago

That still wont let you show the webview in a webview tab though, if you want that you can disable the default action handling for the push open situation:

      airship.actionRegistry.getEntry(OpenExternalUrlAction.DEFAULT_REGISTRY_NAME)?.apply {
            this.predicate = ActionRegistry.Predicate { args ->
                args.situation != Action.SITUATION_PUSH_OPENED
            }
        }

Add that to your autopilot class during onAirshipReady.

laura-turo commented 1 year ago

Thanks so much for your prompt replies, I will gather some logs by tomorrow

sergiucc commented 1 year ago

After further investigation based on your suggestion @rlepinski, we indeed found an issue with navigation being triggered after onPause was called, we correctly blocked that and now everything is behaving as expected. Thank you! Unless @laura-turo has anything to add to this that might be an Airship issue, I will close this.

laura-turo commented 1 year ago

Same here, our splash screen was launching the next activity after onPause. Sorry I didn't pay more attention to it earlier. After making sure the next activity is not launched after onPause fixed the issue.

Although Airship opens an independent browser, I guess in order to open a browser inside our app we would have to use the overriding onNotificationOpened approach? not a big deal but just wondering if there's an alt option for that

Thanks!!

rlepinski commented 1 year ago

@laura-turo Thats an approach, might be better to just use the action framework though. You can override the open url action:

 airship.actionRegistry.getEntry(OpenExternalUrlAction.DEFAULT_REGISTRY_NAME)?.apply {
            this.defaultAction = object : OpenExternalUrlAction() {

                override fun perform(arguments: ActionArguments): ActionResult {
                    return if (URLUtil.isHttpsUrl(arguments.value.string)) {
                        val uri = UriUtils.parse(arguments.value.string)

                        // Handle the https url

                        ActionResult.newEmptyResult()
                    } else {
                        super.perform(arguments)
                    }
                }
            }
        }

Do that during takeOff