High priority Firebase post not awake device from Doze android 6+

I migrated my project from GCM to Firebase. A push notification arrives normally when the device is not sleeping or has recently been sleeping, but if I leave the device for, say, an hour, a push notification is not sent until I activate the device.

Android docs say that if you need to wake your device to deliver a message, use FireBase with high priority. It also says that device administration applications are not subject to Doze restrictions; my application is a device administrator application.

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

What i tried

  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........" ] } 

    The lifetime is set, so the message will come in the end. The delay_ while_idle parameter is false, FCM ignores it after September 2016.

  2. Device administration applications are not subject to Doze, my application is a device administration application, but I also explicitly added the application to the Doze whitelist, which can be found in the section "Settings" → "Battery" → "Optimization". This was done manually through the settings application, NOT programmatically in the code.

I left my device to go to bed for 3 hours, and no jolt passed. I also used ADB to put the device in Doze. When adb puts the device into Doze mode, push is not accepted, and when adb takes the device out of Doze, push passes.

I have not tried further thoughts.

My shocks are data messages. This is because I do not want the click to come to the notification panel on the device and that the user clicks it to execute the function. The user does not interact with the device administrator application. Thus, the data message is processed

 onMessageReceived(RemoteMessage remoteMessage) 

I believe that notifications cause the device to wake up, which is what I need, but I want the application to handle the push, not the user. Can I have messages that are both notification and data, but onMessageRecievied handle this functionality?

Has anyone experienced something similar or are there any solutions for this?

[EDIT1] Below I find the following link that says you can send a message containing both a notification and data, but if the application is in the background, a notification is displayed, but the data is executed only when the user clicks the notification. This is not what I want, since I would like the data to be executed in onMessageRecived right away.

data notification

[EDIT2] I added the following code and permission for the application. Now the application asks the user to whitelist the application for Doze, so I clicked "yes". I then put the device in Doze through adb and sent a push. Nothing worked until I woke the device from standby. 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" /> 

[EDIT3]

I conducted additional testing to try to isolate the problem and deduce the code of my web application from the equation. I put the device in Doze through adb and use the FireBase console to send push. The push code went right. This suggests that there is a problem with the code of my web application that sends all push information to the fcm endpoint. I will receive the code tonight and publish it later.

[EDIT4] I just did some more testing. I put the device into a nap and then used the FireBase console to send a message with two key-value pairs. When the device is in Doze mode and the application is in the foreground (on the screen), a click is performed and OnMessageReceived is executed. It is wonderful. However, if the application is in BG, only a notification is displayed. I understand that from documents, data messages are sent to the launcher via Intent, but my launcher application does not handle clicks. The class that handles clicks is called MyAndroidFirebaseMsgService and extends FirebaseMessagingService.

Should I forward the intention to this class in case the application is in BG? It seems a bit burdensome to do this. This has never happened in GCM.

In addition, I do not want the application to start with a push, because it is very aggressive, because the device user can use another application. My application is also a device administrator’s application, so in 99% of cases there is no user interaction, it’s just a client that runs policies on the device.

[Edit5]

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

thanks

+28
android firebase-cloud-messaging device-admin
source share
6 answers

You cannot do anything.

This is a known issue caused by battery optimization implemented by some OEMs (e.g. Meizu or Asus). When the application switches in the switch application, the application is processed as if it were forcibly stopped, which is not the default behavior of Android. The unfortunate side effect of this is that it can cause the FCM service for your application to stop working. A similar effect can be caused by high priority messages in dose mode.

The Firebase team is working to improve this behavior from the end, but the actual fix should come from the OEM side.

One way to check if your application affects any OEM battery management feature is as follows:

1) Attach OEM device to adb

2) Run the application on the device

3) Swipe the application from the last screen on the device

4) Run command: adb shell dumpsys package MY-PACKAGE | grep stopped

If it shows stop = true, you can safely assume that OEM has such a mechanism and that the same thing affects your application.

+5
source share

After struggling with a similar problem, I managed to get this to work.

I send the following JSON data through the postman:

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

It seems that the last "priority":10 is what I need.

I could not find links to this in the Firebase documentation, but in the outdated GCM documentation it used. https://developers.google.com/cloud-messaging/concept-options

+5
source share

While working on the application, I got stuck too. Then I found a question about this on Github that solved my problem. I.e

On devices running Android 6.0+, Doze mode completes the entire background when the phone is idle and not charging, including a background connection with Pushy.

As soon as the device moves or wakes up by the user, the background is restored, and any pending notifications will be in a few seconds if they have not expired.

To send notifications to devices in Dose mode, your application can declare REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission in its AndroidManifest.xml and display a system dialog in which users configure their application using battery optimization without leaving the application.

This will effectively support a background connection with Pushy active and devices will be able to receive notifications even in Dose mode.

You can check this problem here https://github.com/ToothlessGear/node-gcm/issues/231

Hope this helps you!

+2
source share

It seems that it is not possible to make high priority when sending only data fields without notification. Here is a quote from the documentation :

High priority messages should usually result in user interaction with your application or its notifications. If FCM detects a template in which they do not, your messages may be prioritized.

+1
source share

Setting time_to_live to 0 solved the problem for me.

I think because a very small time_to_live will tell FCM that this message is only right now. Thus, in an attempt to deliver it as soon as possible, he will ignore battery optimization, like the Android P "application wait basket." Be careful, as setting a small time_to_live may mean that in some cases a notification is not delivered at all. I don’t think you should apply it to all kinds of push notifications.

Learn more about time_to_live: https://firebase.google.com/docs/cloud-messaging/concept-options#setting-the-priority-of-a-message

0
source share

Instead of using "android": {"priority": "high"} use like this

  { "time_to_live": 300000, "delay_while_idle": false, "data": { "message": "PING_DEVICE", "time": "21/01/2018 16:20:28", "pushguid": "10062" }, "priority": "high" } 
0
source share

All Articles