android - 具有高优先级的 Firebase 消息不会从 Doze android 6+ 唤醒设备

标签 android firebase-cloud-messaging device-admin

我已将我的项目从使用 GCM 迁移到使用 Firebase。当设备最近处于唤醒状态或 sleep 状态时,推送通知可以正常发送,但如果我离开设备一个小时,则在我唤醒设备之前不会发送推送。

Android 文档说,如果您需要唤醒设备以传递消息,请使用优先级设置为高的 FireBase。它还说设备管理应用程序不受打盹限制,我的应用程序是设备管理应用程序。

我想我会提到,当我将项目从 GCM 迁移到 FCM 时,我只在 firebase 控制台中指定了包名称,而不是指纹。

我尝试过的。

  • 将优先级设置为高
    {
      "time_to_live": 300000,
      "delay_while_idle": false,
      "android": {
        "priority": "high"
      },
      "data": {
        "message": "PING_DEVICE",
        "time": "21/01/2018 16:20:28",
        "pushguid": "10062"
      },
      "registration_ids": [
        "eOMT........"
      ]
    }
    

    生存时间是设定的,因此信息最终会通过。 delay_while_idle 设置为 false,这在 2016 年 9 月之后被 FCM 忽略。
  • 设备管理应用程序不受 Doze 影响,我的是一个设备管理应用程序,但我也明确地将该应用程序添加到设置 -> 电池 -> 优化中的 Doze 白名单中。这是通过设置应用程序手动完成的,而不是在代码中以编程方式完成。

  • 我已经让我的设备进入休眠状态 3 个小时,但没有推送通过。我还使用 adb 将设备放入 Doze。当 adb 将设备置于 Doze 时不会收到推送,当 adb 将设备从 Doze 中取出时,推送会通过。

    进一步的想法我还没有尝试过。

    我的推送是数据消息。这是因为我不希望推送到达设备上的通知栏并让用户单击它来执行功能。用户与设备管理应用程序没有交互。因此,数据消息由
    onMessageReceived(RemoteMessage remoteMessage)
    

    我相信通知消息确实会唤醒设备,这正是我所需要的,但我希望应用程序来处理推送,而不是用户。我可以让消息既是通知又是数据,但有 onMessageRecievied 处理功能吗?

    有没有人遇到过类似的事情或对此有任何解决方案?

    [编辑1]
    我发现下面的链接说你可以发送一条消息,它既是通知又是数据,但如果应用程序在后台,则显示通知但只有在用户单击通知时才会执行数据。这不是我想要的,因为我希望数据立即在 onMessageRecived 中执行。

    notification with data

    [编辑2]
    我已向该应用程序添加了以下代码和权限。该应用程序现在要求用户将该应用程序列入 Doze 白名单,因此我单击了"is"。然后我通过 adb 将设备放入 Doze 并发送推送。在我将设备从打盹模式中取出之前,什么都没有发生。所以,不幸的是,这行不通。
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                Intent intent = new Intent();
                String packageName = getPackageName();
                PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
                if (!pm.isIgnoringBatteryOptimizations(packageName)) {
                    intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                    intent.setData(Uri.parse("package:" + packageName));
                    startActivity(intent);
                }
            }
    
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
    

    [编辑3]

    我已经做了进一步的测试,试图找出问题并将我的 Web 应用程序代码排除在外。我通过 adb 将设备放入 Doze 并使用 FireBase 控制台发送推送。 推送正确通过 这告诉我将所有推送信息发送到 fcm 端点的 Web 应用程序代码存在问题。我今晚会得到代码,稍后发布。

    [编辑4]
    我刚刚做了一些更多的测试。我将设备置于休眠状态,然后使用 FireBase 控制台发送带有 2 个键值对的数据消息。当设备处于 Doze 并且应用程序处于前台(在屏幕上)时,推送通过并执行 onMessageReceived。这很棒。但是,如果应用程序在 BG 中,则仅显示通知。我从文档中了解到,数据消息通过 Intent 分派(dispatch)到启动器 Activity ,但我的启动器应用程序不处理推送。处理推送的类称为 MyAndroidFirebaseMsgService 并扩展 FirebaseMessagingService。

    如果应用程序在 BG 中,我是否必须将 Intent 路由到此类?必须这样做似乎有点奇怪。在 GCM 中从来没有这种情况。

    此外,我不希望通过推送启动应用程序,因为这是非常具有侵入性的,因为设备用户可能正在使用不同的应用程序。我的应用程序也是一个设备管理应用程序,所以 99% 的时间没有用户交互,它只是一个在设备上执行策略的客户端。

    [编辑5]
    internal static void SendNotification (  Dictionary<string, string> nameValues ,  List<string> theregIDs , string sPushName)
             {     
                string stringregIds =  string.Join("\",\"", theregIDs) ;
    
                 JavaScriptSerializer js = new JavaScriptSerializer();
                string keyValueJson = js.Serialize(nameValues);
    
                string TIME_TO_LIVE = "604800";
    
                string DELAY_WHILE_IDLE = "false";
    
                string ENDPOINTADDRESS = @"https://fcm.googleapis.com/fcm/send";
    
    
                postData = String.Concat("{\"time_to_live\":", TIME_TO_LIVE,  ",\"delay_while_idle\": ", DELAY_WHILE_IDLE,  ",  \"android\":{\"priority\":\"high\" } ,\"data\": { \"message\" : " + "\"" + sPushName + "\",\"time\": " + "\"" + System.DateTime.Now.ToString() + "\""
                    , keyValueJson
                   , "},\"registration_ids\":[\"" + stringregIds + "\"]}");
    
    
                WebRequest myWebRequest = null;
                WebResponse myWebResponse = null;
                try
                {
                    myWebRequest = WebRequest.Create(ENDPOINTADDRESS);                         
                    myWebRequest.Method = "post";
                    myWebRequest.ContentType = "application/json";
                    //  myWebRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
                    myWebRequest.Headers.Add("Authorization: key=" + Our_Api_Key);
                    myWebRequest.Headers.Add("Sender:id=" + Our_Sender_Id);
    
                    Byte[] BA = Encoding.UTF8.GetBytes(postData);
                    myWebRequest.ContentLength = BA.Length;
    
                    using (Stream dataStreamOut = myWebRequest.GetRequestStream())
                    {
                        dataStreamOut.Write(BA, 0, BA.Length);
    
                    }
    
                    using (myWebResponse = myWebRequest.GetResponse())
                    {
                        using (Stream dataStream = myWebResponse.GetResponseStream())
                        {
                            using (StreamReader tReader = new StreamReader(dataStream))
                            {
                                strServerResponse = tReader.ReadToEnd(); 
                            }
    
                        }
                    }
    
    
                }
                catch (WebException ex)
                {
    
    
    
                }
    
             }//
    

    谢谢

    最佳答案

    在遇到类似问题后,我设法让它发挥作用。

    我通过 postman 发送以下json数据:

    {
      "data": {
        "body": "Test body from curl"
      },
      "registration_ids": ["Token"],
      "webpush": {
        "headers": {
          "Urgency": "high"
        }
      },
      "android": {
        "priority": "high"
      },
      "priority": 10
    }
    

    似乎最后一个 "priority":10 是为我修复它的原因。

    我在 Firebase 文档中找不到对此的任何引用,但在已弃用的 GCM 文档中使用了它。 https://developers.google.com/cloud-messaging/concept-options

    关于android - 具有高优先级的 Firebase 消息不会从 Doze android 6+ 唤醒设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48451761/

    相关文章:

    ios - 来自 FCM 的通知有时会显示在 iOS 通知托盘中

    ios - didReceiveLocalNotification、didReceiveRemoteNotification 和 willPresentNotification 从未在通知出现时触发,React Native App

    django - 如何在 Django 中发送 Firebase 推送通知

    android - android如何进行密码验证?

    java - 在 Android 中从 BroadcastReceiver 的 onReceive() 启动应用程序

    android - 获取 Traffic Jam Google Maps API

    android - Facebook 在 Android 上的 React

    java - 如何从 android 中的 arraylist 获取 null

    android - 锁定安卓手机

    android - 手机重启时禁用设备管理员权限