You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase推送通知无法打开URL问题排查求助

问题排查与解决方案

我仔细看了你的代码、推送Payload和Manifest配置,找到了几个导致点击通知无法打开URL的关键问题:

1. 核心疏漏:自定义通知逻辑完全没执行

你在onMessageReceived里正确获取了通知的标题、内容、click_action和URL,但从头到尾没有调用你写好的sendNotification方法!这直接导致:

  • 应用前台时,系统不会自动弹出通知,你的自定义跳转逻辑根本没机会运行;
  • 应用后台时,Firebase会直接用系统托盘处理notification字段的推送,完全走默认的click_action逻辑,完全忽略你的代码逻辑。

2. PendingIntent 适配问题

你的PendingIntent.getActivity使用的flag是0,在Android 12及以上版本,这种写法会导致PendingIntent无法正常生效,必须指定FLAG_IMMUTABLE或FLAG_UPDATE_CURRENT(根据业务需求选择)。

3. 后台推送的系统行为限制

当应用处于后台时,Firebase收到包含notification字段的推送时,会由系统直接展示通知,此时notification里的link会被click_action覆盖(系统优先处理click_action)。要解决这个问题,需要把URL放在data字段中,或者使用纯data推送,确保无论前台后台都能触发onMessageReceived。


修复后的完整代码

1. 修改MyFirebaseMessagingService

public class MyFirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
    private static final String TAG = "FirebaseMessagingServic";

    public MyFirebaseMessagingService() {}

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        String title = "";
        String message = "";
        String clickAction = "MAIN_PAGE"; // 默认跳转Activity
        Uri targetUri = null;

        // 优先处理data字段(兼容后台推送场景)
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
            try {
                JSONObject data = new JSONObject(remoteMessage.getData());
                // 从data里读取URL(后台推送时也能拿到)
                String url = data.optString("link");
                if (!TextUtils.isEmpty(url)) {
                    targetUri = Uri.parse(url);
                }
                // 从data里读取标题、内容、点击动作
                title = data.optString("title", title);
                message = data.optString("body", message);
                clickAction = data.optString("click_action", clickAction);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        // 处理notification字段(仅前台推送时生效)
        if (remoteMessage.getNotification() != null) {
            if (TextUtils.isEmpty(title)) {
                title = remoteMessage.getNotification().getTitle();
            }
            if (TextUtils.isEmpty(message)) {
                message = remoteMessage.getNotification().getBody();
            }
            if (targetUri == null) {
                targetUri = remoteMessage.getNotification().getLink();
            }
            if (TextUtils.isEmpty(clickAction)) {
                clickAction = remoteMessage.getNotification().getClickAction();
            }

            Log.d(TAG, "Message Notification Title: " + title);
            Log.d(TAG, "Message Notification Body: " + message);
            Log.d(TAG, "Message Notification click_action: " + clickAction);
            Log.d(TAG, "Message Notification url: " + targetUri);
        }

        // 关键:调用自定义通知方法!
        if (!TextUtils.isEmpty(title) || !TextUtils.isEmpty(message)) {
            sendNotification(title, message, clickAction, targetUri);
        }
    }

    @Override
    public void onDeletedMessages() {}

    private void sendNotification(String title, String messageBody, String click_action, Uri uri) {
        Intent intent;
        if (uri != null) {
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setData(uri);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 避免栈冲突
        } else {
            intent = new Intent(click_action);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }

        // 适配Android 12+的PendingIntent Flag
        int pendingIntentFlag;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            pendingIntentFlag = PendingIntent.FLAG_IMMUTABLE;
        } else {
            pendingIntentFlag = PendingIntent.FLAG_UPDATE_CURRENT;
        }
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, pendingIntentFlag);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.app_logo_final)
                .setContentTitle(TextUtils.isEmpty(title) ? "PushNotification" : title)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        // 用随机ID避免通知被覆盖(可选)
        notificationManager.notify((int) System.currentTimeMillis(), notificationBuilder.build());
    }
}

2. 修改推送Payload(推荐纯Data推送,兼容前后台)

{
  "to": "/topics/NEWS",
  "data": {
    "extra_information": "This is some extra information",
    "title": "Test title: http://www.google.com",
    "body": "Test body: http://www.google.com",
    "link": "http://www.google.com",
    "click_action": "MAIN_PAGE"
  }
}

如果一定要保留notification字段,也要确保data里包含link,这样后台推送时也能读取到URL。

3. Manifest配置无需修改(保持现有即可)


验证步骤

  1. 重新编译安装应用;
  2. 发送修改后的Payload;
  3. 分别测试应用前台、后台、杀死状态下的通知跳转:
    • 存在URL时,点击通知会打开浏览器加载对应链接;
    • 无URL时,会打开指定的MainScreen Activity。

内容的提问来源于stack exchange,提问作者CuriousPaul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:30:29