Android文档指出,如果需要唤醒设备以传递消息,则应使用优先级设置为高的FireBase。它还表示设备管理应用程序不受Doze限制的影响,而我的应用程序正是设备管理应用程序。
我想提一下当我将项目从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)
我相信通知消息可以唤醒设备,这正是我所需要的,但我希望应用程序处理推送,而不是用户。那么,我能否拥有既是通知又是数据的消息,但由onMessageRecieved来处理功能?
是否有人遇到过类似的情况或有任何解决方案?
[EDIT1]我找到了下面的链接,它说您可以发送既是通知又是数据的消息,但如果应用程序在后台运行,则会显示通知,但只有在用户点击通知后才执行数据。这不是我想要的,因为我希望数据立即在onMessageRecived中执行。
[EDIT2]我已将以下代码和权限添加到应用程序中。应用现在会要求用户将应用程序加入Doze白名单,所以我选择了是。然后,我通过adb将设备放入Doze并发送了一条推送。直到我把设备从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]
我进行了进一步的测试,试图排除我的网络应用程序代码对问题的影响。我通过adb将设备置于Doze状态,然后使用FireBase控制台发送推送。推送成功地传递了这告诉我,存在一个问题,即我的网络应用程序代码向fcm终端发送所有推送信息。我今晚会拿到代码并晚些时候发布。
[EDIT4] 我刚刚进行了更多的测试。我将设备置于Doze状态,然后使用Firebase控制台发送包含2个键值对的数据消息。当设备处于Doze状态且应用程序在前台(在屏幕上)时,推送消息会生效,执行onMessageReceived操作。这很好。但是,如果应用程序在后台,则仅显示通知。我从文档中了解到,数据消息通过Intent分派到启动器活动,但我的启动器应用程序不处理推送。处理推送的类称为MyAndroidFirebaseMsgService,它扩展了FirebaseMessagingService。
如果应用程序在后台,我是否必须将Intent路由到此类?这似乎有些奇怪。在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)
{
}
}//
谢谢
onMessageReceived
回调。您收到了那个回调吗? - Eugen Pechanec