我是否正确设置了Android推送通知?

时间:2017-07-24 11:07:47

标签: c# android azure firebase notifications

我正在我的Xamarin Forms应用中为我的Android项目设置推送通知。我一直在关注在线文档(https://developer.xamarin.com/guides/xamarin-forms/cloud-services/push-notifications/azure/)以使其正常运行,但我遇到了一些问题

1 - 当我从Azure Notification Hub发送测试时,通知无法到达。 2 - 在Register方法中经过一段时间后,应用程序在调试期间崩溃。

我认为问题是由注册引起的,我不认为注册正在运行,因此应用超时导致崩溃,Azure通知中心也成功发送消息但没有设备捡起来(可能是因为它没有注册)

首先,这是我到目前为止所做的事情。

  1. 我在console.firebase.google.com中设置了一个项目,并按照说明记录了发件人ID和服务器密钥。我已经将项目ID命名为myapp-android-app。
  2. 我已将documtation中的所有代码添加到我的Android项目中。
  3. 我已向Azure中的通知中心添加了GCM通知服务,并为其提供了我的Firebase应用注册中记录的服务器密钥。
  4. 我已将我的Google帐户添加到我的Andoird模拟器
  5. 以下是我的Android项目的源代码。

    MainActivity.cs

    using System;
    using Android.App;
    using Android.Content.PM;
    using Android.OS;
    using Gcm.Client;
    
    namespace MyApp.Droid
    {
        [Activity(Label = "@string/app_name", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
        public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
        {
            //public static MainActivity CurrentActivity { get; private set; }
    
            // Create a new instance field for this activity.
            static MainActivity instance = null;
    
            // Return the current activity instance.
            public static MainActivity CurrentActivity
            {
                get
                {
                    return instance;
                }
            }
            protected override void OnCreate(Bundle bundle)
            {
                instance = this;
                base.OnCreate(bundle);
    
                global::Xamarin.Forms.Forms.Init(this, bundle);
                Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();
                LoadApplication(new App());
    
                try
                {
                    // Check to ensure everything's setup right
                    GcmClient.CheckDevice(this);
                    GcmClient.CheckManifest(this);
    
                    // Register for push notifications
                    System.Diagnostics.Debug.WriteLine("Registering...");
                    GcmClient.Register(this, PushHandlerBroadcastReceiver.SENDER_IDS);
                }
                catch (Java.Net.MalformedURLException)
                {
                    CreateAndShowDialog("There was an error creating the client. Verify the URL.", "Error");
                }
                catch (Exception e)
                {
                    CreateAndShowDialog(e.Message, "Error");
                }
    
                TabLayoutResource = Resource.Layout.Tabbar;
                ToolbarResource = Resource.Layout.Toolbar;
    
            }
            void CreateAndShowDialog(String message, String title)
            {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
    
                builder.SetMessage(message);
                builder.SetTitle(title);
                builder.Create().Show();
            }
        }
    }
    

    GcmService.cs

    using Android.App;
    using Android.Content;
    using Android.Media;
    using Android.Support.V4.App;
    using Android.Util;
    using Gcm.Client;
    using Microsoft.WindowsAzure.MobileServices;
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Text;
    
    [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")]
    [assembly: UsesPermission(Name = "android.permission.INTERNET")]
    [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
    //GET_ACCOUNTS is only needed for android versions 4.0.3 and below
    [assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
    namespace MyApp.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 PushHandlerBroadcastReceiver : GcmBroadcastReceiverBase<GcmService>
        {
            public static string[] SENDER_IDS = new string[] { "xxxxxxxxxx" };
        }
    
        [Service]
        public class GcmService : GcmServiceBase
        {
            public static string RegistrationToken { get; private set; }
    
            public GcmService()
                : base(PushHandlerBroadcastReceiver.SENDER_IDS) { }
    
            protected override void OnRegistered(Context context, string registrationToken)
            {
                Log.Verbose("PushHandlerBroadcastReceiver", "GCM Registered: " + registrationToken);
                RegistrationToken = registrationToken;
    
                var push = AzureService.DefaultManager.CurrentClient.GetPush();
                MainActivity.CurrentActivity.RunOnUiThread(() => Register(push, null));
            }
    
            protected override void OnUnRegistered(Context context, string registrationToken)
            {
                Log.Error("PushHandlerBroadcastReceiver", "Unregistered RegisterationToken: " + registrationToken);
            }
    
            protected override void OnError(Context context, string errorId)
            {
                Log.Error("PushHandlerBroadcastReceiver", "GCM Error: " + errorId);
            }
    
            public async void Register(Microsoft.WindowsAzure.MobileServices.Push push, IEnumerable<string> tags)
            {
                try
                {
                    const string templateBodyGCM = "{\"data\":{\"message\":\"$(messageParam)\"}}";
    
                    JObject templates = new JObject();
                    templates["genericMessage"] = new JObject
                    {
                        {"body", templateBodyGCM}
                    };
    
                    await push.RegisterAsync(RegistrationToken, templates);
                    Log.Info("Push Installation Id", push.InstallationId.ToString());
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message + ex.StackTrace);
                    Debugger.Break();
                }
            }
    
            protected override void OnMessage(Context context, Intent intent)
            {
                Log.Info("PushHandlerBroadcastReceiver", "GCM Message Received!");
    
                var msg = new StringBuilder();
    
                if (intent != null && intent.Extras != null)
                {
                    foreach (var key in intent.Extras.KeySet())
                        msg.AppendLine(key + "=" + intent.Extras.Get(key).ToString());
                }
    
                // Retrieve the message
                var prefs = GetSharedPreferences(context.PackageName, FileCreationMode.Private);
                var edit = prefs.Edit();
                edit.PutString("last_msg", msg.ToString());
                edit.Commit();
    
                string message = intent.Extras.GetString("message");
                if (!string.IsNullOrEmpty(message))
                {
                    CreateNotification("New todo item!", "Todo item: " + message);
                }
    
                string msg2 = intent.Extras.GetString("msg");
                if (!string.IsNullOrEmpty(msg2))
                {
                    CreateNotification("New hub message!", msg2);
                    return;
                }
    
                CreateNotification("Unknown message details", msg.ToString());
            }
    
            void CreateNotification(string title, string desc)
            {
                // Create notification
                var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
    
                // Create an intent to show the UI
                var uiIntent = new Intent(this, typeof(MainActivity));
    
                // Create the notification
                // we use the pending intent, passing our ui intent over which will get called
                // when the notification is tapped.
                NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
                var notification = builder.SetContentIntent(PendingIntent.GetActivity(this, 0, uiIntent, 0))
                        .SetSmallIcon(Android.Resource.Drawable.SymActionEmail)
                        .SetTicker(title)
                        .SetContentTitle(title)
                        .SetContentText(desc)
                        .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification)) // set the sound
                        .SetAutoCancel(true).Build(); // remove the notification once the user touches it
    
                // Show the notification
                notificationManager.Notify(1, notification);
            }
        }
    }
    

    我使用我在Firebase控制台应用中记录的public static string[] SENDER_IDS = new string[] { "xxxxxxxx" }; ID替换了Sender中的字符串。

    当我通过Android模拟器运行应用程序时,我在大约3分钟后收到以下错误。

    GcmService.cs 中的错误:

    Exception: System.Threading.Tasks.TaskCanceledException: A task was canceled.
    

    见于第71行:

    await push.RegisterAsync(RegisteToken, templates);
    

    有谁知道我做错了什么?我是否认为它没有正确注册?

1 个答案:

答案 0 :(得分:0)

我能够在Xamarin.Forms(包括Android和iOS)中集成Firebase云消息传递,遵循官方Xamarin指南,该解释得到了很好的解释:

https://developer.xamarin.com/guides/android/application_fundamentals/notifications/remote-notifications-with-fcm/

查看您的代码,在我看来,您使用旧的Gcm服务(已弃用)而不是新的Fcm。 你应该有一个 google-services.json 文件和一个 FirebaseMessagingService

然后......

  

请注意

     

截至目前,Xamarin Forms在开发时不能很好地处理应用程序的部署,进行脏重新安装,似乎使以前获得的 Notification Token 无效调用Fcm库的方法时,有时会引发 IllegalStateException

     

这是一个已知的错误,可以通过清理解决方案来解决   重新发起