仅当应用程序在前台时才会收到 Android 通知

Posted

技术标签:

【中文标题】仅当应用程序在前台时才会收到 Android 通知【英文标题】:Android notifications only received if app is in foreground 【发布时间】:2017-07-01 21:34:21 【问题描述】:

我正在尝试使用 FCM 向我的应用程序实施通知,但遇到了一些问题。当应用程序处于前台时,没有问题,并且通知按预期显示。但是,如果应用程序在后台,则不会显示通知。

我的清单如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<uses-sdk android:minSdkVersion="19" />

<application
    android:allowBackup="true"
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <service
        android:name=".NotificationService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>

    <service
        android:name=".FirebaseInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
        </intent-filter>
    </service>

    <activity android:name=".MainActivity" android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

    <meta-data android:name="com.google.android.gms.games.APP_ID"
        android:value="@string/app_id" />


    <meta-data
        android:name="io.fabric.ApiKey"
        android:value="xxx" />
     </application>
   </manifest>

还有我的服务等级:

 package pw.ckies.snakegame;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

import java.util.Random;

public class NotificationService extends FirebaseMessagingService 

    private static final String TAG = "MyFirebaseMsgService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) 

        String title = "Empty";
        String message = "Emptyyy";
        if(remoteMessage.getNotification() != null) 
            if (remoteMessage.getNotification().getTitle() != null) 
                title = remoteMessage.getNotification().getTitle();
            


            if (remoteMessage.getNotification().getBody() != null) 
                message = remoteMessage.getNotification().getBody();
            
        

        Log.e("notification","recieved");


        sendNotification(title, message);
    

    private void sendNotification(String title, String message) 

        Intent intent = new Intent(this, MainActivity.class);

        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_people_black_24dp)
                .setLargeIcon(BitmapFactory.decodeResource(this.getResources(),
                        R.mipmap.ic_launcher))
                .setContentTitle(title)
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(getRequestCode(), notificationBuilder.build());
    

    private static int getRequestCode() 
        Random rnd = new Random();
        return 100 + rnd.nextInt(900000);
    


另外,当收到通知时,logcat 会说:

07-01 23:09:14.050 ? W/GCM-DMM:广播意图回调:result=CANCELLED forIntent act=com.google.android.c2dm.intent.RECEIVE flg=0x10000000 pkg=xxx(有附加功能)

我不知道它是什么意思,所以我搜索了一下,发现很多人都有同样的问题。有人说重新安装 Android Studio 会解决这个问题,所以我这样做了,并没有任何运气地更新到最新版本 2.3.3。 我一直在 android 7.1.1 上测试 OnePlus 3。

我的 build.grade(应用模块):

 ...
    dependencies 
        compile fileTree(include: ['*.jar'], dir: 'libs')
        testCompile 'junit:junit:4.12'
        compile "com.google.android.gms:play-services-games:$gms_library_version"
        compile project(':BaseGameUtils')
        compile 'com.android.support:appcompat-v7:24.0.0'

        compile 'com.android.support:design:24.0.0'
        compile 'com.android.support:support-annotations:24.0.0'
        compile 'com.google.firebase:firebase-ads:11.0.1'
        compile 'com.google.firebase:firebase-core:11.0.1'
        compile 'com.google.firebase:firebase-messaging:11.0.1'
        compile('com.crashlytics.sdk.android:crashlytics:2.6.6@aar') 
            transitive = true;
        
    

    apply plugin: 'com.google.gms.google-services'

我的后端是使用以下数据的 python 发布请求:


    "notification": "title": "Title goes here", "body": "Body goes here" ,
    "to": token

我也尝试过从 firebase 仪表板发送通知。

有人还建议未签名的 APK 不允许我不确定的后台通知?但由于我的应用在 Play 商店中,所以这不会有任何问题。

我已经测试了我能想到的所有东西,但我找不到解决方案!这可能是我的手机,也可能只是一个愚蠢的错误。任何帮助表示赞赏!

【问题讨论】:

当应用程序在后台时,通知由系统托盘处理 @Shubham 这是什么意思?不应该还显示吗? 只有在通知负载包含标题和正文(可选)数据键时才会显示 在这里查看文档firebase.google.com/docs/cloud-messaging/concept-options 【参考方案1】:

From the firebase docs

在后台时,应用会在 通知托盘,仅在用户点击时处理数据负载 在通知上。

有人还建议未签名的 APK 不允许我不确定的后台通知?但由于我的应用在 Play 商店中,这不会有任何问题。

您的应用程序默认使用默认密钥库进行签名。一切都取决于在 Firebase 控制台中添加到您的项目设置中的 SHA1。

对于生产或调试密钥库,您可以从 here

我已经测试了我能想到的所有东西,但我找不到解决方案! 尝试发送包含标题和正文(可选)数据键的通知负载

  
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification" : 
      "body" : "great match!",
      "title" : "Portugal vs. Denmark",
      "icon" : "myicon"
    
  

【讨论】:

无论我发送什么 JSON,我都会得到相同的结果...有通知,有数据,等等。 尝试在 Firebase 控制台的项目设置中为您的应用调试版本添加 SHA1 没有区别,因为我一直在尝试使用 Play 商店的发布版本...【参考方案2】:

当您的应用处于后台或关闭时,不会调用 FirebaseMessagingService 的“onMessageReceived()”方法。当您没有在通知中发送任何数据时,就会发生这种情况。您需要通过服务器上的数据有效负载通过通知发送一些您想要的值。之后,即使应用程序关闭或在后台,它也会在各种情况下工作。

注意:要在通知中发送数据,您需要自己的服务器,Firebase 无法提供帮助。

查看此链接了解更多详情:

How to handle notification when app in background in Firebase

【讨论】:

发送数据值没有任何区别。 请确保您的服务器正确发送数据负载,因为我告诉您的问题是上述问题中最常见的原因。一定少了点什么。严格按照本教程操作应用程序和服务器。它就像魅力一样。 androidhive.info/2012/10/…

以上是关于仅当应用程序在前台时才会收到 Android 通知的主要内容,如果未能解决你的问题,请参考以下文章

Android:通知动作点击非统一行为

仅当应用程序在后台请求位置后进入前台时才调用 didUpdateLocations

应用程序在前台时无法处理 FCM 通知

如何在前台(顶部)活动(应用程序)更改时收到通知

仅当我将包裹提交给 CRAN 时才会出错

斯威夫特 |后台线程中的网络调用立即超时