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

Where does gcm.n.link handling take place? #6703

Open
ColtonIdle opened this issue Feb 14, 2025 · 13 comments
Open

Where does gcm.n.link handling take place? #6703

ColtonIdle opened this issue Feb 14, 2025 · 13 comments

Comments

@ColtonIdle
Copy link

We're using fcm's built in mechanism for displaying notifications when the app is in the background. This works well, but we stumbled upon a feature that I can't find a trace of. According to https://stackoverflow.com/questions/63378233/how-to-send-firebase-notifications-with-uris-to-implement-deep-linking you can send gcm.n.link in order to send a deeplink that's triggered when you click a notification. Though we I search this codebase I don't see any trace of it pulling that key in order to get the value to set for the deep link. If it's not doing that... then how is it setting up the deep link properly?

@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@lehcar09 lehcar09 added api: messaging type: question Further information is requested and removed needs-triage labels Feb 14, 2025
@lehcar09
Copy link
Contributor

Hi @ColtonIdle, thank you for reaching out. Please note, gcm.n.link is a reserved key and should not be used in the data payload.

public static final String LINK = NOTIFICATION_PREFIX + "link";
.

As per our documentation for data message,

Set the appropriate key with your custom key-value pairs to send a data payload to the client app.

In Android, if the click_action is not set and the link exists, it is used in the Notification intent (When the app is in the background).

private static Intent createTargetIntent(
String pkgName, NotificationParams params, PackageManager pm) {
String action = params.getString(MessageNotificationKeys.CLICK_ACTION);
if (!TextUtils.isEmpty(action)) {
// Use the specified action
Intent intent = new Intent(action);
intent.setPackage(pkgName);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
Uri link = params.getLink();
if (link != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(pkgName);
intent.setData(link);
return intent;
}
// Query the package manager for the best launch intent for the app
Intent intent = pm.getLaunchIntentForPackage(pkgName);
if (intent == null) {
Log.w(TAG, "No activity found to launch app");
}
return intent;
}

I tried reproducing the behavior from the Stack Overflow post you shared, and I was able to confirm that using the gcm.n.link in data payload works to set the deep link, only when using HTTP v1 API. In the Firebase Console, the notification composer prompts error when reserved key words are used.

I believe this is a bug. I'll raise this to our engineers and see what we can do here. Thanks a lot!

@lehcar09 lehcar09 removed the type: question Further information is requested label Feb 17, 2025
@ColtonIdle
Copy link
Author

@lehcar09 thanks for the thorough response. So my issue right now is that my backend is sending programatic firebase cloud messages. we want them to be of type Notification so that the android fcm library does all of the heavy lifting of posting the notification. but we can't get deep links to work unless we send gcm.n.link. then everything works. are you saying we should not do that? nothing else seems to work, so please let me know if not. there are a bunch of 5-10 year old stack overflow questions on this topic and the only ones that people claims to work is gcm.n.link

@ColtonIdle
Copy link
Author

ColtonIdle commented Feb 18, 2025

@lehcar09 to be clear. please dont remove gcm.n.link support from HTTP v1 API 😅
my team depends on that since click_action or link don't work (as well as like 100 different things we tried). The only thing that has worked is gcm.n.link

@lehcar09
Copy link
Contributor

Data payload should be set with your custom key-value pairs. Reserved keys or prefixes should not be used in the data bundle.

I have raised this issue to our engineers for clarification and ask if there's a way to set the deep link URI for notification. Alternatively, we can file a feature request to support the link or link_android field. I’ll get back to you once I hear back from them.

@ColtonIdle
Copy link
Author

ColtonIdle commented Feb 18, 2025

Thanks! In the meantime... we'll continue to use gcm.n.link. I hope it doesn't get removed since that would break functionality for us (+ a bunch of others on stackoverflow that had the same issue of "How do i send a deep link in android using fcm?")

Edit: I'll also grab some server code to paste in here to show what we tried exactly.

@ColtonIdle
Copy link
Author

Just following up with a small snippet of what we've tried

As per

https://firebase.google.com/docs/cloud-messaging/send-message

we use the java sdk

Message message = Message.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .putData("link", "myApp://companyName/tab2")
    .setToken(registrationToken)
    .build();

and this didn't work.

we also tried

Message message = Message.builder()
    .setNotification(Notification.builder()
        .setTitle("$GOOG up 1.43% on the day")
        .setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
        .build())
    .setAndroidConfig(AndroidConfig.builder()
        .setTtl(3600 * 1000)
        .setNotification(AndroidNotification.builder()
            .setIcon("stock_ticker_update")
            .setColor("#f45342")
            .setClickAction("myApp://companyName/tab2")
            .build())
        .build())
    .setToken(registrationToken)
    .build();

and we tried a bunch more different combinations in the putData field.

Bonus question: As a sanity check (maybe im going crazy) How does the sdk decide whether this is a notification message or a data message? Does doing setNotification mean this is automatically a notification fcm message? what if I do putData? what if i do both? which one wins?

@lehcar09
Copy link
Contributor

Notification messages contain a predefined set of user-visible keys. Data messages, by contrast, contain only your user-defined custom key-value pairs.

public static ArrayMap<String, String> extractDeveloperDefinedPayload(Bundle bundle) {
ArrayMap<String, String> data = new ArrayMap<>();
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
if (value instanceof String) {
String stringValue = (String) value;
// Add all bundle members except those with a reserved prefix and non
// data values typically exposed through other messages.
if (!key.startsWith(MessagePayloadKeys.RESERVED_PREFIX)
&& !key.startsWith(MessageNotificationKeys.RESERVED_PREFIX)
&& !key.equals(MessagePayloadKeys.FROM)
&& !key.equals(MessagePayloadKeys.MESSAGE_TYPE)
&& !key.equals(MessagePayloadKeys.COLLAPSE_KEY)) {
data.put(key, stringValue);
}
}
}
return data;
}

FCM allows users to send notification messages that contain an optional payload of custom key-value pairs. However, please note that app behavior depends on whether the app is in the background or the foreground. You can check this documentation for more details.

@ColtonIdle
Copy link
Author

ColtonIdle commented Feb 21, 2025

Yep. I'm aware of the difference of background vs foreground behavior for data vs notification messages. i once hit a wild issue regarding that like 3 years ago that made me go way deeper into FCM than I would have liked 😂

FCM allows users to send notification messages that contain an optional payload of custom key-value pairs

SO am i understanding correctly that once you add an optional payload of custom key/value pairs then the message is a "data" message? or if i omit any notification properties and only have custom key/value then that considers it a data message?

@ColtonIdle
Copy link
Author

we're still investigating issues at our org. some of the android devs are convinced that "click_action" is the way forward... but click_action seems to not be for deep links, but instead for the name of which activity to launch. at least from what i understand from https://firebase.google.com/docs/cloud-messaging/migrate-v1

can anyone chime in on that? Or i guess a better question is... is there not some property that we're "supposed" to use for deep links from FCM notification messages?

@gsakakihara
Copy link
Contributor

gsakakihara commented Feb 25, 2025

"gcm.n.link" (and "gcm.n.link_android") is not officially supported and uses a reserved key, so "click_action" would be recommended.

"click_action" sets the action of the Intent sent to your app to open an Activity when the notification is clicked. To use this for deep linking, you can set the click_action to an action that your deep link Activity handles and include whatever deep link data you want in the FCM message data. Then in the deep link Activity, you can extract the deep link data from the FCM data payload in the Activity's Intent, if it exists (because it was started from an FCM notification click).

@ColtonIdle
Copy link
Author

@gsakakihara thanks for the response! Unfortunately it looks like that's not compatible with navigation-compose's deep linking support though (which we have been using since compose is recommended by Android team since 2022) https://developer.android.com/develop/ui/compose/navigation#deeplinks

Would definitely be nice to have first class support for actual deep links for notification messages that is compatible with native android ui toolkit and native navigation-compose library.

@gsakakihara
Copy link
Contributor

I'm not sure whether it would work, but NavDeepLink.Builder has setAction() or https://developer.android.com/reference/kotlin/androidx/navigation/NavDeepLinkDslBuilder#action() that should allow registering for a deep link based on action?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants