具有高优先级的 Firebase 消息不会从 Doze android 6+ 唤醒设备 [英] Firebase message with high priority not waking device from Doze android 6+

查看:13
本文介绍了具有高优先级的 Firebase 消息不会从 Doze android 6+ 唤醒设备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have migrated my project from using GCM to use Firebase. Push notification comes through ok when the device is awake or been asleep recently but if I leave the device for say an hour, no push is sent until I wakeup the device.

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

The Android docs say that if you need to wake a device to deliver a message, then use FireBase with priority set to high. It also says that device Admin apps are not subject to Doze restrictions, my app is a device admin app.

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

I thought I would mention that when I migrated the project from GCM to FCM, I only specified the package name in the firebase console and not the fingerprint.

我已经尝试过了.

  1. 将优先级设为高

  1. Set priority to high

{
  "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 将忽略此设置.

Time to live is set so the message will come through eventually. delay_while_idle is set to false, this is ignored by FCM after sept 2016.

设备管理应用不受 Doze 约束,我的是设备管理应用,但我也明确将该应用添加到设置 -> 电池 -> 优化中的 Doze 白名单中.这是通过设置应用手动完成的,而不是在代码中以编程方式完成.

Device admin apps are not subject to Doze, mine is a device admin app but I have also explicitly added the app to the Doze whitelist found in Setting -> Battery -> Optimization. This was done manually through the settings app and NOT programmatically in code.

我已经让我的设备进入睡眠状态 3 小时,并且没有任何推动.我还使用 adb 将设备放入 Doze.当 adb 将设备置于 Doze 时没有收到推送,当 adb 将设备从 Doze 中取出时,推送通过.

I have left my device to go to sleep for 3 hours and no push come through. I have also used adb to put the device into Doze. When adb puts the device in Doze no push is received, when adb takes the device out of Doze, the push comes through.

我没有尝试过的其他想法.

我的推送是数据消息.这是因为我不希望推送到达设备上的通知栏并让用户单击它来执行功能.用户与设备管理应用程序没有交互.所以一条数据消息由

My pushes are data messages. This is because I don't want the push to come to the notification bar on the device and have the user click it to execute the functionality. The user has no interaction with the device admin app. So a data message is handled by

onMessageReceived(RemoteMessage remoteMessage)

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

I believe notification messages do wake up the device, which is what I need but I want the app to handle the push, not the user. Could I have messages that are both notification and data but have onMessageRecievied handle the functionality?

有没有人遇到过类似的情况或有解决办法?

Has anybody experienced anything similar or have any solutions to this?

我发现下面的链接说您可以发送既是通知又是数据的消息,但是如果应用程序在后台,则会显示通知,但仅在用户单击通知时才会执行数据.这不是我想要的,因为我希望数据立即在 onMessageRecived 中执行.

I have found the following link below that says you can send a message which is both notification and data, but if the app is in the background, the notification is displayed but the data is only executed when the user clicks the notification. This is not what I want as I would like the data to execute in onMessageRecived straight away.

数据通知

我已向应用程序添加以下代码和权限.该应用程序现在要求用户将该应用程序列入 Doze 应用程序的白名单,因此我单击是".然后我通过 adb 将设备置于 Doze 状态并发送推送.直到我将设备退出打盹模式之前,什么都没有发生.所以,不幸的是,这不起作用.

I have added the following code and permission to the app. The app now asks the user to whitelist the app for Doze, so I clicked yes. I then via adb put the device in Doze and sent a push. Nothing came through until I took the device back out of doze mode. So, unfortunately, this does not work.

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" />

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

I have done further testing to try to isolate the problem and take my web application code out of the equation. I put the device into Doze via adb and the used FireBase console to send the push instead. The push came through correctly This tells me there is a problem with my web application code that sends all the push info to the fcm endpoint. I will get the code tonight and post later.

我刚刚做了一些测试.我将设备置于打盹状态,然后使用 FireBase 控制台发送带有 2 个键值对的数据消息.当设备处于打盹且应用程序处于前台(屏幕上)时,推送通过并执行 onMessageReceived.这很棒.但是,如果应用程序位于 BG 中,则只会显示通知.我从文档中了解到,数据消息通过 Intent 发送到启动器活动,但我的启动器应用程序不处理推送.处理推送的类称为 MyAndroidFirebaseMsgService 并扩展 FirebaseMessagingService.

i have just done some more testing. I placed the device into doze then used FireBase console to send a data message with 2 key-value pairs. When the device is in Doze and the app is in the foreground (on the screen), the push comes through and onMessageReceived executes. This is great. However, if the app is in the BG then only a notification is displayed. I understand that from the docs, the data messages are dispatched to the launcher activity via an Intent, but my launcher app does not handle the pushes.The class that handles the pushes is called MyAndroidFirebaseMsgService and extends FirebaseMessagingService.

如果应用程序位于 BG 中,我是否必须将意图路由到此类?似乎有点starnge必须这样做.在 GCM 中从未出现过这种情况.

Do i have to route the intent to this class in case the app is in the BG? Seems a bit starnge to have to do this. It was never the case in GCM.

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

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)
            {



            }

         }//

谢谢

推荐答案

在遇到类似问题后,我设法让它工作.

After struggling with a similar issue I managed to get it to work.

我通过邮递员发送以下json数据:

I send following json data through postman:

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

似乎最后一个 "priority":10 是为我解决它的问题.

It seems like the last "priority":10 is what's fixing it for me.

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

I could not find any reference to this in the Firebase documentation, but in the deprecated GCM documentation it's used. https://developers.google.com/cloud-messaging/concept-options

这篇关于具有高优先级的 Firebase 消息不会从 Doze android 6+ 唤醒设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆