我正在我的Xamarin Forms
应用中为我的Android
项目设置推送通知。我一直在关注在线文档(https://developer.xamarin.com/guides/xamarin-forms/cloud-services/push-notifications/azure/)以使其正常运行,但我遇到了一些问题
1 - 当我从Azure Notification Hub
发送测试时,通知无法到达。
2 - 在Register
方法中经过一段时间后,应用程序在调试期间崩溃。
我认为问题是由注册引起的,我不认为注册正在运行,因此应用超时导致崩溃,Azure通知中心也成功发送消息但没有设备捡起来(可能是因为它没有注册)
首先,这是我到目前为止所做的事情。
以下是我的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);
有谁知道我做错了什么?我是否认为它没有正确注册?
答案 0 :(得分:0)
我能够在Xamarin.Forms(包括Android和iOS)中集成Firebase云消息传递,遵循官方Xamarin指南,该解释得到了很好的解释:
查看您的代码,在我看来,您使用旧的Gcm服务(已弃用)而不是新的Fcm。 你应该有一个 google-services.json 文件和一个 FirebaseMessagingService 类
然后......
请注意
截至目前,Xamarin Forms在开发时不能很好地处理应用程序的部署,进行脏重新安装,似乎使以前获得的 Notification Token 无效调用Fcm库的方法时,有时会引发 IllegalStateException 。
这是一个已知的错误,可以通过清理解决方案来解决 重新发起