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

Android Studio中应用后台时如何从通知打开URI

解决FCM后台通知点击打开URI无效的问题

问题根源

当应用在后台时,FCM的通知类型消息会直接交给系统通知栏处理,不会触发FirebaseMessagingService的onMessageReceived方法——这就导致你当前在这个方法里构建的PendingIntent完全没用。只有纯数据类型消息才会在后台时也触发onMessageReceived,或者得靠配置通知payload的click_action配合Manifest来搞定。

两种可行解决方案

方案1:统一前台/后台逻辑(推荐)

这个方案让所有消息都走你自己的通知构建逻辑,不管前台后台都能生效:

  1. 修改PendingIntent的启动标记
    后台启动Activity必须加FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_CLEAR_TOP(按需调整),不然系统不让你从后台拉起Activity。另外Android 12及以上对PendingIntent的标记有强制要求,得加上FLAG_IMMUTABLE:

    Intent notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(commingUrl));
    // 加标记让后台能正常启动Activity
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    
    // 适配Android 12+的PendingIntent要求
    int pendingFlags = PendingIntent.FLAG_ONE_SHOT;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        pendingFlags |= PendingIntent.FLAG_IMMUTABLE;
    }
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, pendingFlags);
    
  2. 让推送端发纯数据消息
    告诉推送的同事,别发带notification字段的消息,只发data字段的。这样不管应用在前台还是后台,都会触发onMessageReceived,执行你写的构建通知代码。示例payload:

    {
      "to": "设备的FCM_TOKEN",
      "data": {
        "title": "你的通知标题",
        "body": "你的通知内容",
        "commingUrl": "https://目标网址.com"
      }
    }
    

方案2:适配系统自动展示的通知

如果没法改推送消息类型,只能用通知类型消息,那就这么搞:

  1. 推送payload里加click_action字段
    在通知的payload里加个click_action,值设成你自定义的action,比如OPEN_MY_URI:

    {
      "to": "设备的FCM_TOKEN",
      "notification": {
        "title": "通知标题",
        "body": "通知内容",
        "click_action": "OPEN_MY_URI"
      },
      "data": {
        "commingUrl": "https://目标网址.com"
      }
    }
    
  2. Manifest里给Activity加Intent Filter
    找个用来处理跳转的Activity(或者新建个中转Activity),在Manifest里加对应的intent-filter:

    <activity
        android:name=".YourActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="OPEN_MY_URI" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    
  3. 在Activity里获取URI并跳转
    在这个Activity的onCreate或者onNewIntent里,从Intent的extra里拿到commingUrl然后跳转:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handleUri(getIntent());
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleUri(intent);
    }
    
    private void handleUri(Intent intent) {
        if (intent != null && intent.getExtras() != null) {
            String url = intent.getExtras().getString("commingUrl");
            if (url != null && !url.isEmpty()) {
                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
                finish(); // 中转Activity用完就关
            }
        }
    }
    

修改后的完整openAnotherApp方法(方案1)

void openAnotherApp(@NonNull RemoteMessage remoteMessage, Context context, String title, String body, String commingUrl) {
    Intent notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(commingUrl));
    // 添加后台启动Activity的必要标记
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    
    // 适配Android 12及以上的PendingIntent标记要求
    int pendingFlags = PendingIntent.FLAG_ONE_SHOT;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        pendingFlags |= PendingIntent.FLAG_IMMUTABLE;
    }
    
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, pendingFlags);
    
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification)
            .setContentTitle(title)
            .setContentText(body)
            .setAutoCancel(true)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT);
            
    notificationBuilder.setContentIntent(pendingIntent);
    
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notificationBuilder.build());
}

注意:别忘了提前创建好CHANNEL_ID对应的通知渠道,不然通知可能显示不出来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:09:18