J'ai migré mon projet de l'utilisation de GCM à l'utilisation de Firebase. Les notifications push sont bien envoyées lorsque l'appareil est éveillé ou a été endormi récemment, mais si je laisse l'appareil pendant une heure, aucun push n'est envoyé jusqu'à ce que je réveille l'appareil.
La documentation d'Android indique que si vous devez réveiller un appareil pour lui transmettre un message, utilisez FireBase avec une priorité élevée. Il est également indiqué que les applications d'administration d'appareil ne sont pas soumises aux restrictions de Doze, mon application est une application d'administration d'appareil.
Je pensais mentionner que lorsque j'ai migré le projet de GCM à FCM, j'ai seulement spécifié le nom du paquet dans la console firebase et non l'empreinte digitale.
Ce que j'ai essayé.
-
Définir la priorité à haute
{ "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........" ] }
La durée de vie est fixée de manière à ce que le message finisse par être transmis. delay_while_idle est fixé à false, ce qui est ignoré par le FCM après sept 2016.
-
Les applications d'administration de l'appareil ne sont pas soumises à Doze. La mienne est une application d'administration de l'appareil mais j'ai également ajouté explicitement l'application à la liste blanche de Doze qui se trouve dans Setting -> Battery -> Optimization. Cela a été fait manuellement par l'intermédiaire de l'application de paramètres et PAS de manière programmatique dans le code.
J'ai laissé mon appareil se mettre en veille pendant 3 heures et aucune poussée ne s'est produite. J'ai également utilisé adb pour mettre l'appareil en mode Doze. Lorsque adb met l'appareil en mode Doze, aucun signal n'est reçu, mais lorsque adb sort l'appareil du mode Doze, le signal est reçu.
d'autres pensées que je n'ai pas essayées.
Mes poussées sont des messages de données. En effet, je ne veux pas que le push arrive dans la barre de notification de l'appareil et que l'utilisateur clique dessus pour exécuter la fonctionnalité. L'utilisateur n'a aucune interaction avec l'application d'administration de l'appareil. Ainsi, un message de données est géré par
onMessageReceived(RemoteMessage remoteMessage)
Je crois que les messages de notification réveillent l'appareil, ce qui est ce dont j'ai besoin, mais je veux que l'application gère le push, pas l'utilisateur. Pourrais-je avoir des messages qui sont à la fois des notifications et des données, mais que onMessageRecievied gère la fonctionnalité ?
Quelqu'un a-t-il vécu une expérience similaire ou a-t-il une solution à proposer ?
[EDIT1] J'ai trouvé le lien suivant qui dit que vous pouvez envoyer un message qui est à la fois une notification et des données, mais si l'application est en arrière-plan, la notification est affichée mais les données ne sont exécutées que lorsque l'utilisateur clique sur la notification. Ce n'est pas ce que je veux, car je voudrais que les données soient exécutées directement dans onMessageRecived.
[EDIT2] J'ai ajouté le code et la permission suivants à l'application. L'application demande maintenant à l'utilisateur de mettre l'application sur une liste blanche pour Doze, j'ai donc cliqué sur oui. J'ai ensuite via adb mis l'appareil en Doze et envoyé un push. Rien n'est arrivé jusqu'à ce que je retire l'appareil du mode Doze. Donc, malheureusement, cela ne fonctionne pas.
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]
J'ai effectué d'autres tests pour essayer d'isoler le problème et de retirer le code de mon application web de l'équation. J'ai mis l'appareil en mode Doze via adb et j'ai utilisé la console FireBase pour envoyer le push à la place. Le coup de pouce a été donné correctement Cela me dit qu'il y a un problème avec le code de mon application web qui envoie toutes les informations de poussée au point de terminaison fcm. Je vais récupérer le code ce soir et le poster plus tard.
[EDIT4] Je viens de faire d'autres tests. J'ai placé l'appareil en mode doze puis j'ai utilisé la console FireBase pour envoyer un message de données avec 2 paires clé-valeur. Lorsque l'appareil est en mode Doze et que l'application est au premier plan (sur l'écran), le message est envoyé et onMessageReceived s'exécute. C'est très bien. Cependant, si l'application est au premier plan, seule une notification s'affiche. Je comprends que, d'après la documentation, les messages de données sont envoyés à l'activité du lanceur via un Intent, mais mon application de lanceur ne gère pas les pushs. La classe qui gère les pushs s'appelle MyAndroidFirebaseMsgService et étend FirebaseMessagingService.
Dois-je acheminer l'intention vers cette classe si l'application se trouve dans le BG ? Cela me semble un peu bizarre de devoir faire cela. Cela n'a jamais été le cas dans le GCM.
De plus, je ne veux pas que l'application soit lancée à partir d'un bouton poussoir, car cela est très invasif et l'utilisateur de l'appareil pourrait être en train d'utiliser une autre application. Mon application est également une application d'administration de périphérique, donc 99% du temps il n'y a pas d'interaction avec l'utilisateur, c'est juste un client qui exécute les politiques sur le périphérique.
[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)
{
}
}//
merci
0 votes
Est-ce que cela fonctionne dans les versions Android inférieures, et où ajoutez-vous la priorité et les données ?
0 votes
@PeterHaddad Bonjour, je ne l'ai pas testé sur les versions inférieures d'Android. Tous les téléphones que je vais acheter seront sous Android 6+. Je vais demander à mon partenaire commercial de me donner un extrait de code de la façon dont il envoie les données au point de terminaison FCM. Y a-t-il un endroit ou un ordre particulier où je dois définir la priorité et les données ?
0 votes
En ce qui concerne votre EDIT3, la console Firebase ne permet d'envoyer que des messages de type "push". notifications (pour autant que je m'en souvienne). Ceux-ci sont gérés par les services Google Play si votre application n'est pas en cours d'exécution qui publient la notification en votre nom. Il ne démarre pas votre application et vous ne recevez pas la notification.
onMessageReceived
le rappel. Avez-vous reçu ce rappel ?0 votes
@EugenPechanec ah, vous avez raison c'était juste un message de notification, aucun callback n'a été généré. Avez-vous d'autres idées sur ce que le problème pourrait être ?
0 votes
Je n'ai aucune idée de l'origine du problème, mais j'ai quelques idées pour le déboguer. Sur quel appareil cela se produit-il ? Avez-vous essayé d'autres appareils ou émulateurs ? (Vous devriez, pour la comparaison.) Avez-vous essayé d'envoyer un données FCM (qui devrait toujours déclencher le callback) via l'API HTTP du FCM ? (En laissant la logique de votre serveur en dehors de l'équation, comme vous l'avez suggéré).
0 votes
@EugenPechanec J'ai les mêmes résultats sur S6, S7 et Xcover3. Tous Android6+. Les messages que j'essaie d'envoyer sont toujours des messages de données. Dans le post original, j'ai donné un extrait de ce que l'application web envoie au point de terminaison FCM. Je crois que cela utilise l'api http de la FCM. Comment puis-je tester ce que vous suggérez ? La console Firebase peut-elle envoyer uniquement des messages de données ?
0 votes
@turtleboy Si vous envoyez une notification d'un téléphone à un autre, ceci : stackoverflow.com/questions/47505629/ Cela a fonctionné pour moi où même si le téléphone est endormi, il a reçu la notification. En ce qui concerne la console, je pense que vous avez raison. Je ne pense pas qu'elle passe par le serveur mais par le FCM.
0 votes
@PeterHaddad Bonjour, je viens de faire d'autres tests. J'ai placé l'appareil en doze puis utilisé la console FireBase pour envoyer un message de données avec 2 paires clé-valeur. Lorsque l'appareil est en mode Doze et au premier plan (sur l'écran), le push arrive et onMessageReceived s'exécute. C'est très bien. Cependant, si l'application est dans le BG, seule une notification s'affiche. Je comprends que, d'après la documentation, les messages de données sont envoyés à l'activité du lanceur via un Intent, mais mon application de lanceur ne gère pas les pushs.
0 votes
J'ai posté EDIT 4
0 votes
Que doit contenir la notification ? J'entends par là ce que doivent contenir le titre et le corps de la notification, qui doivent être spécifiés dans les données utiles comme le lien ci-dessus dans mon commentaire.
0 votes
@PeterHaddad Vous voulez dire quand j'envoie la notification depuis ma webapplication ou via la console firebase ? Si vous voulez dire par ma webapp, alors ces messages sont des messages de données pures qui ont une clé de message qui pourrait être "PING_DEVICE" et une autre clé appelée "pushguid" qui est définie à 123. Je ne fixe pas de titre ni de corps car il s'agit d'un message de données. Je vais poster le code du serveur qui envoie le push dans EDIT5. Désolé si je n'ai pas compris ce que vous vouliez dire.
0 votes
D'après ce que j'ai compris du problème, et sur la base de vos conclusions EDIT3, je vais essayer de récupérer le message http envoyé depuis la console Firabase Push. (Essayez d'inspecter le trafic si vous le pouvez) et voir s'ils envoient certains paramètres particuliers qui réveillent votre appareil. J'ai trouvé que vous devriez émuler le comportement dans votre application web.
0 votes
@turtleboy est-ce toujours un problème ou avez-vous trouvé une solution ? Cela peut être spécifique à un appareil. Sur nos appareils AOSP 6.0.1 de type vanille, nous utilisons Pushy avec une connexion permanente. Notre application hôte est sur liste blanche et nous n'avons rencontré aucun problème pour surmonter le mode sommeil. Je soupçonne des problèmes liés à l'équipementier, comme l'ont mentionné d'autres commentateurs.
0 votes
Essayez d'exécuter un service en arrière-plan et recevez les notifications avec JobIntentService. Seul JobIntentService fonctionne avec Oreo. medium.com/til-kotlin/
1 votes
Avez-vous trouvé une solution à ce problème ?
0 votes
Du nouveau sur ce problème ?
0 votes
@DominikK Non mon pote, j'ai dû sortir mon logiciel tel quel. Donc mes poussées n'arrivent que si l'appareil est éveillé ou est réveillé par l'utilisateur.
0 votes
@turtleboy J'ai résolu ce problème. Ce n'est pas une très bonne solution mais si vous laissez un service de premier plan fonctionner tout le temps en arrière-plan, peu importe combien de temps l'appareil est en mode sommeil, les messages de Pushy et Firebase arrivent toujours. Le seul inconvénient est une consommation de batterie un peu plus importante (dans une zone acceptable) et une notification persistante qui s'affiche toujours lorsque l'application attend un message. Cela dépend du type de votre application si ces inconvénients sont acceptables pour vous.
0 votes
@turtleboy - Avez-vous vu des restrictions puisque vous définissez la priorité comme élevée pour tous les autres messages. Les restrictions de l'App standby bucket ne s'appliqueraient-elles pas ici ?