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

Pinpoint notifications: Deep link doesn't work #2814

Open
1 task done
Andrew0000 opened this issue May 9, 2024 · 8 comments
Open
1 task done

Pinpoint notifications: Deep link doesn't work #2814

Andrew0000 opened this issue May 9, 2024 · 8 comments
Labels
documentation Documentation improvements feature-request Request a new feature Push Notifications Related to the push notifications category

Comments

@Andrew0000
Copy link

Andrew0000 commented May 9, 2024

Before opening, please confirm:

Language and Async Model

Kotlin, Kotlin - Coroutines, RxJava

Amplify Categories

Notifications

Gradle script dependencies

amplify = "2.14.12"

amplify = { module = "com.amplifyframework:core-kotlin", version.ref = "amplify" }
amplifyCognito = { module = "com.amplifyframework:aws-auth-cognito", version.ref = "amplify" }
amplifyPushPinpoint = { module = "com.amplifyframework:aws-push-notifications-pinpoint", version.ref = "amplify" }
amplifyAnalyticsPinpoint = { module = "com.amplifyframework:aws-analytics-pinpoint", version.ref = "amplify" }
amplifyRx = { module = "com.amplifyframework:rxbindings", version.ref = "amplify" }

implementation(libs.amplify)
implementation(libs.amplifyCognito)
implementation(libs.amplifyPushPinpoint)
implementation(libs.amplifyAnalyticsPinpoint)
implementation(libs.amplifyRx)

Environment information

# Put output below this line
------------------------------------------------------------
Gradle 8.4
------------------------------------------------------------

Build time:   2023-10-04 20:52:13 UTC
Revision:     e9251e572c9bd1d01e503a0dfdf43aedaeecdc3f

Kotlin:       1.9.10
Groovy:       3.0.17
Ant:          Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM:          11.0.10 (JetBrains s.r.o. 11.0.10+0-b96-7281165)
OS:           Mac OS X 14.4.1 x86_64

Please include any relevant guides or documentation you're referencing

https://docs.aws.amazon.com/pinpoint/latest/apireference/apps-application-id-messages.html#apps-application-id-messages-prop-apnsmessage-action

Describe the bug

I'm trying to use deep link in my android app. Seems like Amplify doesn't support it.

What I send from web Pinpoint:

{
"APNSMessage": {
"aps": {
"alert": ""
}
},
"GCMMessage": {
"notification": {
"title": "Merry Christmas",
"body": "Ho ho ho"
},
"Action": "DEEP_LINK",
"url": "link here",
"data": {
"url": "link here",
"screenTitle": "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
"screenDescription": "Lorem ipsum dolor sit amet",
},
"ADMMessage": {
"data": {
"message": ""
}
},
"BaiduMessage": {
"title": "",
"description": ""
}
}
}

As you can see, I specified Action DEEP_LINK as it's described here: https://docs.aws.amazon.com/pinpoint/latest/apireference/apps-application-id-messages.html#apps-application-id-messages-prop-apnsmessage-action

Bu on the client side I receive a notification with no deep link.
It means that app gets android.intent.action.MAIN as the intent action by tap.
Intent's data is null.

I believe I've done everything correctly according:
https://docs.amplify.aws/gen1/android/build-a-backend/push-notifications/set-up-push-notifications/
https://docs.amplify.aws/gen1/android/build-a-backend/push-notifications/register-device/
https://docs.amplify.aws/gen1/android/build-a-backend/push-notifications/record-notifications/

What could be the problem?

Reproduction steps (if applicable)

  1. Send a FCM push with a deep link
  2. Receive it on a device
  3. Tap on the notification
    Result: App is opened with no deep link. Intent: android.intent.action.MAIN, data: null

Code Snippet

// Put your code below this line.

Log output

// Put your logs below this line


amplifyconfiguration.json

{
  "UserAgent": "aws-amplify-cli/2.0",
  "Version": "1.0",
  "auth": {
    "plugins": {
      "awsCognitoAuthPlugin": {
        "IdentityManager": {
          "Default": {}
        },
        "CredentialsProvider": {
          "CognitoIdentity": {
            "Default": {
              "PoolId": "hidden",
              "Region": "eu-west-1"
            }
          }
        },
        "CognitoUserPool": {
          "Default": {
            "PoolId": "hidden",
            "AppClientId": "hidden",
            "Region": "eu-west-1"
          }
        },
        "PinpointAnalytics": {
          "Default": {
            "AppId": "hidden",
            "Region": "eu-west-1"
          }
        },
        "PinpointTargeting": {
          "Default": {
            "Region": "eu-west-1"
          }
        }
      }
    }
  },
  "analytics": {
    "plugins": {
      "awsPinpointAnalyticsPlugin": {
        "pinpointAnalytics": {
          "appId": "hidden",
          "region": "eu-west-1"
        },
        "pinpointTargeting": {
          "region": "eu-west-1"
        }
      },
      "awsPinpointPushNotificationsPlugin": {
        "pinpointAnalytics": {
          "appId": "hidden",
          "region": "eu-west-1"
        },
        "pinpointTargeting": {
          "region": "eu-west-1"
        }
      }
    }
  },
  "notifications": {
    "appId": "hidden",
    "region": "eu-west-1",
    "plugins": {
      "awsPinpointAnalyticsPlugin": {
        "pinpointAnalytics": {
          "appId": "hidden",
          "region": "eu-west-1"
        },
        "pinpointTargeting": {
          "region": "eu-west-1"
        }
      },
      "awsPinpointPushNotificationsPlugin": {
        "appId": "hidden",
        "region": "eu-west-1",
        "pinpointAnalytics": {
          "appId": "hidden",
          "region": "eu-west-1"
        },
        "pinpointTargeting": {
          "region": "eu-west-1"
        }
      }
    }
  },
  "IdentityManager": {
    "Default": {}
  },

  "CredentialsProvider": {
    "CognitoIdentity": {
      "Default": {
        "PoolId": "hidden",
        "AppClientId": "hidden",
        "AppId": "hidden",
        "Region": "eu-west-1"
      }
    }
  },
  "CognitoUserPool": {
    "Default": {
      "PoolId": "hidden",
      "AppClientId": "hidden",
      "AppId": "hidden",
      "Region": "eu-west-1"
    }
  },
  "PinpointAnalytics": {
    "Default": {
      "PoolId": "hidden",
      "AppClientId": "hidden",
      "AppId": "hidden",
      "Region": "eu-west-1"
    }
  }
}

GraphQL Schema

// Put your schema below this line

Additional information and screenshots

No response

@github-actions github-actions bot added the pending-triage Issue is pending triage label May 9, 2024
@yuhengshs yuhengshs added Push Notifications Related to the push notifications category and removed pending-triage Issue is pending triage labels May 9, 2024
@yuhengshs
Copy link
Contributor

Hi @Andrew0000 ,

Thanks for reporting the issue, one of our team members will take a look and post updates here.

@yuhengshs yuhengshs added the bug Something isn't working label May 9, 2024
@yuhengshs
Copy link
Contributor

Hi @Andrew0000 ,

I was not able to reproduce the issue. Have you also followed the steps in our Amplify doc and additionally followed the guide on how to enable DEEP linking in your project?

Let me know if there any additional steps that I missed. Meanwhile, I'll retry to replicate your issue.

@Andrew0000
Copy link
Author

Andrew0000 commented May 10, 2024

additionally followed the guide on how to enable DEEP linking in your project?

Yes, we use deep links. It works with other notifications. As I understand, the problem happens even before this. The app is launched from the Amplify's notification with android.intent.action.MAIN action and null data in its intent. I logged the intent in my Activity's onCreate() as the earliest point before every in-app navigation. So there is just no data that the app can get a link from.

Have you also followed the steps in our Amplify doc

I believe so. But let me copy the code:

AndroidManifest:

        <service
            android:name=".PushNotificationService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>

App:

        Amplify.addPlugin(AWSCognitoAuthPlugin())
        Amplify.addPlugin(AWSPinpointAnalyticsPlugin())
        Amplify.addPlugin(AWSPinpointPushNotificationsPlugin())
        Amplify.configure(applicationContext)

PushNotificationService:

typealias AmplifyKt = com.amplifyframework.kotlin.core.Amplify

import com.amplifyframework.core.Amplify
import com.amplifyframework.notifications.pushnotifications.NotificationContentProvider
import com.amplifyframework.notifications.pushnotifications.NotificationPayload
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import timber.log.Timber

class PushNotificationService : FirebaseMessagingService() {

    private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())

    override fun onNewToken(token: String) {
        super.onNewToken(token)
        Amplify.Notifications.Push.registerDevice(
            token,
            { Timber.i("[PushNotificationService][Push][Auth][Amplify] Successfully registered device") },
            { Timber.e(it, "[PushNotificationService][Push][Auth][Amplify] Error registering device") },
        )
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        scope.launch {
            tryProcessWithPinpoint(remoteMessage)
        }
    }

    private suspend fun tryProcessWithPinpoint(remoteMessage: RemoteMessage) {
        val notificationPayload = NotificationPayload(NotificationContentProvider.FCM(remoteMessage.data))
        val isAmplifyMessage = Amplify.Notifications.Push.shouldHandleNotification(notificationPayload)
        if (isAmplifyMessage) {
            AmplifyKt.Notifications.Push.handleNotificationReceived(notificationPayload)
        }
    }
}

@Andrew0000
Copy link
Author

Andrew0000 commented May 10, 2024

It's a little none of my business, but I'm looking at com.amplifyframework.pushnotifications.pinpoint.PushNotificationsUtils and see nothing related to any link. Where is a link supposed to be put into the Intent?

fun showNotification(
        notificationId: Int,
        payload: PinpointNotificationPayload,
        targetClass: Class<*>?
    ) {
        CoroutineScope(Dispatchers.IO).launch {
            val largeImageIcon = payload.imageUrl?.let { downloadImage(it) }
            val notificationIntent = Intent(context, payload.targetClass ?: targetClass)
            notificationIntent.putExtra("amplifyNotificationPayload", payload)
            notificationIntent.putExtra("notificationId", notificationId)
            val pendingIntent = PendingIntent.getActivity(
                context,
                notificationId,
                notificationIntent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
            val notificationChannel = retrieveNotificationChannel()
            val builder = if (isNotificationChannelSupported() && notificationChannel != null) {
                NotificationCompat.Builder(context, payload.channelId ?: notificationChannel.id)
            } else {
                NotificationCompat.Builder(context)
            }

            builder.apply {
                setContentTitle(payload.title)
                setContentText(payload.body)
                setSmallIcon(R.drawable.ic_launcher_foreground)
                setContentIntent(pendingIntent)
                setPriority(NotificationCompat.PRIORITY_DEFAULT)
                setLargeIcon(largeImageIcon)
                setAutoCancel(true)
            }

            with(NotificationManagerCompat.from(context)) {
                notify(notificationId, builder.build())
            }
        }
    }

UPD: I went deeper into AWSPinpointPushNotificationsActivity -> getIntentAction -> PinpointNotificationPayload.fromNotificationPayload ->

action?.get(PushNotificationsConstants.DEEPLINK) != null -> {
                // Action is open deeplink
                val deepLink = action[PushNotificationsConstants.DEEPLINK]
                Intent(Intent.ACTION_VIEW, Uri.parse(deepLink))
            }
data[PushNotificationsConstants.PINPOINT_DEEPLINK]?.let {
                action.put(PushNotificationsConstants.DEEPLINK, it)
            }

const val PINPOINT_DEEPLINK = "$PINPOINT_PREFIX.$DEEPLINK" // pinpoint.deeplink

So maybe I should use pinpoint.deeplink field in my pushes? Just a guess.

@Andrew0000
Copy link
Author

Andrew0000 commented May 10, 2024

Yes, this formatting make deeplinks work:

{
"GCMMessage":{
"data":{
"Action": "DEEP_LINK",
"pinpoint.deeplink": "my url here (deeplink)",
"title": "A title",
"message":"A message"
}
}
}

Could you please confirm that a consumer/developer should use pinpoint.deeplink key in the message in order to make deeplinks work? I literally see no documentation regarding pinpoint.deeplink parameter and I found it only by looking at the Amplify's source code.

@yuhengshs yuhengshs added documentation Documentation improvements and removed bug Something isn't working labels May 10, 2024
@yuhengshs
Copy link
Contributor

Hi @Andrew0000 ,

Glad that you found the solution to it. We will make sure to document these properly so that we can mitigate as many misunderstandings as possible.

@Andrew0000
Copy link
Author

Hi @yuhengshs ,

Although my finding works, it would be great if someone could confirm its correctness or provide a code snippet that worked as you mentioned in the first reply. Just to make sure there are no hidden pitfalls in my finding.

@tylerjroach
Copy link
Member

@Andrew0000 That looks correct. Amplify is coded to handle templates from using the "Standard message" with "Open a deep link" Action on the Pinpoint console. Using these parameters appears to send as "pinpoint.deeplink".

If you are using the "Raw message" format, then you would still have to follow the same spec as the deep link standard message behavior.

This looks like missing documentation on the Pinpoint site to clarify how the template actions translate into the resulting raw message.

@tylerjroach tylerjroach added the feature-request Request a new feature label Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Documentation improvements feature-request Request a new feature Push Notifications Related to the push notifications category
Projects
None yet
Development

No branches or pull requests

3 participants