Я перенес свой проект из GCM в Firebase. Push-уведомление приходит нормально, когда устройство не спит или недавно спит, но если я оставляю устройство, скажем, на час, push-уведомление не отправляется, пока я не активирую устройство.
Документы Android говорят, что если вам нужно разбудить устройство для доставки сообщения, используйте FireBase с высоким приоритетом. В нем также говорится, что на приложения администратора устройства не распространяются ограничения Doze, мое приложение является приложением администратора устройства.
Я подумал, что упомяну, что когда я перенес проект из GCM в FCM, я указал только имя пакета в консоли Firebase, а не fingerprint.
Что я пробовал
-
Установить приоритет на высокий
{ "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, FCM игнорирует его после сентября 2016 года.
-
Приложения для администрирования устройства не подлежат Doze, мое приложение является приложением для администрирования устройства, но я также явно добавил приложение в белый список Doze, который можно найти в разделе "Настройка" → "Аккумулятор" → "Оптимизация". Это было сделано вручную через приложение настроек, а НЕ программно в коде.
Я оставил свое устройство, чтобы ложиться спать в течение 3 часов, и никакого толчка не прошло. Я также использовал ADB, чтобы поместить устройство в Doze. Когда adb переводит устройство в режим Doze, push не принимается, а когда adb выводит устройство из Doze, push проходит.
дальнейших мыслей я не пробовал.
Мои толчки - это сообщения с данными. Это потому, что я не хочу, чтобы нажатие приходило на панель уведомлений на устройстве и чтобы пользователь щелкнул ее, чтобы выполнить функцию. Пользователь не взаимодействует с приложением администратора устройства. Таким образом, сообщение с данными обрабатывается
onMessageReceived(RemoteMessage remoteMessage)
Я верю, что уведомления вызывают пробуждение устройства, а это то, что мне нужно, но я хочу, чтобы приложение обрабатывало толчок, а не пользователя. Могу ли я иметь сообщения, которые являются одновременно уведомлением и данными, но onMessageRecievied обрабатывают эту функциональность?
Кто-нибудь испытывал что-то подобное или есть какие-то решения для этого?
[EDIT1] Ниже я обнаружил следующую ссылку, в которой говорится, что вы можете отправить сообщение, содержащее как уведомление, так и данные, но если приложение находится в фоновом режиме, уведомление отображается, но данные выполняются только тогда, когда пользователь щелкает уведомление. Это не то, что я хочу, так как я хотел бы, чтобы данные выполнялись в onMessageRecived сразу.
[EDIT2] Я добавил следующий код и разрешение для приложения. Теперь приложение просит пользователя внести в белый список приложение для Doze, поэтому я нажал "да". Я тогда через 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" />
[EDIT3]
Я провел дополнительное тестирование, чтобы попытаться изолировать проблему и вывести код моего веб-приложения из уравнения. Я помещаю устройство в Doze через adb и используемую консоль FireBase для отправки push. Push- код прошел правильно. Это говорит о том, что существует проблема с кодом моего веб-приложения, который отправляет всю push-информацию в конечную точку fcm. Я получу код сегодня вечером и опубликую позже.
[EDIT4] Я только что провел еще несколько испытаний. Я поместил устройство в дрему, а затем использовал консоль FireBase для отправки сообщения с двумя парами ключ-значение. Когда устройство находится в режиме Doze, а приложение находится на переднем плане (на экране), выполняется нажатие и выполняется OnMessageReceived. Это замечательно. Однако, если приложение находится в BG, отображается только уведомление. Я понимаю, что из документов сообщения данных отправляются в модуль запуска через Intent, но мое приложение запуска не обрабатывает нажатия. Класс, который обрабатывает нажатия, называется MyAndroidFirebaseMsgService и расширяет FirebaseMessagingService.
Должен ли я направить намерение в этот класс в случае, если приложение находится в BG? Кажется, немного обременительно, чтобы сделать это. Такого никогда не было в GCM.
Кроме того, я не хочу, чтобы приложение запускалось с толчка, поскольку это очень агрессивно, поскольку пользователь устройства может использовать другое приложение. Мое приложение также является приложением администратора устройства, поэтому в 99% случаев отсутствует взаимодействие с пользователем, это просто клиент, который выполняет политики на устройстве.
[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)
{
}
}//
Спасибо