Azure 通知中心推送通知失败或传递无效或不完整的数据

Posted

技术标签:

【中文标题】Azure 通知中心推送通知失败或传递无效或不完整的数据【英文标题】:Azure notifications hub push notification failing or delivering invalid or incomplete data 【发布时间】:2017-04-02 05:12:06 【问题描述】:

我正在使用以下 php 代码通过 Azure 通知中心向 android 应用程序发送推送通知。

$hub = new NotificationHub("Endpoint=sb://ServiceName.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SharedAccessKey", "ServiceNameNotification");

        $message = '"data":"message":"This is a sample notification","title":"Sample Notification","action":"Test","action_id":"60"';
        $notification = new AzureNotification("gcm", $message);
        $hub->sendNotification($notification, null);

但不幸的是,尽管我收到了201 作为回复,但大多数时候通知都没有送达。无论何时发送,结果都是不可预测的,有时旧通知的内容最终会显示出来。

以下代码用于在 Android 应用 (Xamarin.Android) 中显示通知:

using System;
using Android.App;
using Android.Content;
using Gcm.Client;
using Microsoft.WindowsAzure.MobileServices;
using Newtonsoft.Json.Linq;
using ServiceName.Helpers;

[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
//GET_ACCOUNTS is needed only for Android versions 4.0.3 and below
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
namespace ServiceName.Droid

    [BroadcastReceiver(Permission = Gcm.Client.Constants.PERMISSION_GCM_INTENTS)]
    [IntentFilter(new string[]  Gcm.Client.Constants.INTENT_FROM_GCM_MESSAGE ,
        Categories = new string[]  "@PACKAGE_NAME@" )]
    [IntentFilter(new string[]  Gcm.Client.Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK ,
        Categories = new string[]  "@PACKAGE_NAME@" )]
    [IntentFilter(new string[]  Gcm.Client.Constants.INTENT_FROM_GCM_LIBRARY_RETRY ,
        Categories = new string[]  "@PACKAGE_NAME@" )]
    public class ServiceNameBroadcastReceiver : GcmBroadcastReceiverBase<PushHandlerService>
    
        public static string[] senderIDs = new string[]  Constants.SenderID ;

        public const string TAG = "MyBroadcastReceiver-GCM";
    
    // The ServiceAttribute must be applied to the class.
    [Service]
    public class PushHandlerService : GcmServiceBase
    

        public static string RegistrationID  get; private set; 

        public PushHandlerService() : base(ServiceNameBroadcastReceiver.senderIDs)  
        protected override void OnMessage(Context context, Intent intent)
        
            string message = string.Empty;
            string title = string.Empty;
            string action = string.Empty;
            string action_id = string.Empty;
            if (intent.Extras.ContainsKey("title"))
            
                title = intent.Extras.Get("title").ToString();
            
            if (intent.Extras.ContainsKey("message"))
            
                message = intent.Extras.Get("message").ToString();
            
            if (intent.Extras.ContainsKey("action"))
            
                action = intent.Extras.Get("action").ToString();
            
            if (intent.Extras.ContainsKey("action_id"))
            
                action_id = intent.Extras.Get("action_id").ToString();
            

            // Extract the push notification message from the intent.
            if (!string.IsNullOrWhiteSpace(message) || !string.IsNullOrWhiteSpace(title))
            
                // Create a notification manager to send the notification.
                var notificationManager =
                    GetSystemService(Context.NotificationService) as NotificationManager;

                // Create a new intent to show the notification in the UI. 
                PendingIntent contentIntent =
                    PendingIntent.GetActivity(context, 0,
                                              new Intent(this, typeof(MainActivity)), 0);

                // Create the notification using the builder.
                var builder = new Notification.Builder(context);
                builder.SetAutoCancel(false);
                if (!string.IsNullOrWhiteSpace(title))
                
                    builder.SetContentTitle(title);
                
                else
                
                    builder.SetContentTitle("Notification from ServiceName");
                
                if (!string.IsNullOrWhiteSpace(message))
                
                    builder.SetContentText(message);
                
                else
                
                    builder.SetContentText("Hello ServiceName User");
                
                builder.SetSmallIcon(Resource.Drawable.ic_stat_icon);
                builder.SetContentIntent(contentIntent);
                var notification = builder.Build();

                // Display the notification in the Notifications Area.
                notificationManager.Notify(1, notification);

            
        
        protected override void OnError(Context context, string errorId)
        
            System.Diagnostics.Debug.WriteLine(
                string.Format("Error occurred in the notification: 0.", errorId));
        
        protected override async void OnRegistered(Context context, string registrationId)
        
            System.Diagnostics.Debug.WriteLine("The device has been registered with GCM.", "Success!");

            // Get the MobileServiceClient from the current activity instance.
            MobileServiceClient client = MainActivity.CurrentActivity.CurrentClient;
            var push = client.GetPush();

            // Define a message body for GCM.
            const string templateBodyGCM = "\"data\":\"message\":\"$(messageParam)\", \"title\": \"$(titleParam)\", \"action\":\"$(actionParam)\",\"action_id\":\"$(action_idParam)\"";

            // Define the template registration as JSON.
            JObject templates = new JObject();
            templates["genericMessage"] = new JObject
            
                "body", templateBodyGCM 
            ;

            try
            
                // Make sure we run the registration on the same thread as the activity, 
                // to avoid threading errors.
                MainActivity.CurrentActivity.RunOnUiThread(
                    // Register the template with Notification Hubs.
                    async () => 

                        try
                        
                        await push.RegisterAsync(registrationId, templates);

                        System.Diagnostics.Debug.WriteLine(
                    string.Format("Push Installation Id " + push.InstallationId.ToString()));


                var res = await MiscServices.RegisterDevice(Settings.UserID, Settings.AccessToken, push.InstallationId.ToString(), "gcm");
                if ((bool)res.data)
                
                    System.Diagnostics.Debug.WriteLine("Registered InstallationId in Server");
                
                else
                
                    System.Diagnostics.Debug.WriteLine("Cannot register with Server" + " " + res.status.StatusCode);
                

            
                        catch (Exception e)
                        
                        

                );


            
            catch (Exception ex)
            
                System.Diagnostics.Debug.WriteLine(
                    string.Format("Error with Azure push registration: 0", ex.Message));
            
        

        protected override void OnUnRegistered(Context context, string registrationId)
        
            System.Diagnostics.Debug.WriteLine("Unregistered with Azure push registration");
            
    


有时甚至测试通知也无法发送,但大多数测试通知都可以正常工作。我们无法真正弄清楚问题出在哪里,非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

当您成功向 Azure NH 发送消息时,收到了 201 个响应。当您通过通知中心发送通知时,最初它只是排队等待 NH 进行处理以确定其所有目标,然后最终 NH 将其发送到 PNS。

这意味着当您使用 REST API 或任何客户端 SDK 时,发送调用的成功返回仅意味着消息已成功在 Notification Hub 排队。

它没有深入了解当 NH 最终将消息发送到 PNS 时发生了什么。如果您的通知未到达客户端设备,则可能是当 NH 尝试将消息传递到 PNS 时,出现错误,例如负载大小超过了 PNS 允许的最大值或在 NH 中配置的凭据无效等。

为了深入了解 PNS 错误,我们引入了一个名为 EnableTestSend 的属性。当您从门户或 Visual Studio 客户端发送测试消息时,此属性会自动启用,因此您可以查看详细的调试信息。

或者您可以尝试通过 RESTful API 调用进行故障排除: https://mynamespace.servicebus.windows.net/mynotificationhub/messages?api-version=2013-10&amp;test

更多信息请参考Azure Notification Hubs - Diagnosis guidelines。

【讨论】:

我尝试了EnableTestSend并成功发送消息到PNS,仍然有几个开发设备没有收到通知。如果这确实是 PNS 方面的问题,有没有一种方法可以用来检查 GCM 中的状态? 由于 GCM 不受我们控制,也许您可​​以参考 support.google.com/googleplay/android-developer/answer/… 了解有关如何在 Firebase 中进行故障排除的更多详细信息。

以上是关于Azure 通知中心推送通知失败或传递无效或不完整的数据的主要内容,如果未能解决你的问题,请参考以下文章

是否可以从Azure通知中心获取通知的状态?

通过新门户中的 Azure 通知中心发送通知

通过 Azure 从 node.js 发送推送通知

Azure 通知中心不会发送苹果推送通知

Windows Azure 中的推送通知标签无效

Xamarin android:天蓝色推送通知的连接字符串无效