如何在Xamarin表单中使用推送通知

我是一个使用Xamarin的应用程序>面向IOS,Android和WP 8的表单。

我需要在我的应用程序推送通知function。

我看到了pushsharp的演示,看起来很有希望。 但是我所看到的所有代码都是针对每个平台单独完成的。

我希望在Xamarin.Forms项目中,在App.cs中的某个地方完成,这样我就不需要重复注册设备的代码,并处理推送通知应该如何处理。

任何帮助将不胜感激。 示例代码或教程引用是受欢迎的。

编辑 :我基于Idot的答案实施它。 这是我的答案的链接

我刚刚在几天前实现了推送通知,我将在这里分享我的解决scheme(基于PushSharp )

一步一步的指导:

1)在你的共享项目中,创build一个名为IPushNotificationRegister的接口

 public interface IPushNotificationRegister { void ExtractTokenAndRegister(); } 

该接口用于获取推送令牌,然后将其发送到服务器。 这个令牌每个设备都是唯一的。

2)在您的共享项目中,您应该调用ExtractTokenAndRegister (使用您最喜爱的IOC,我在login后立即调用它)。

Android实现:

3)添加接收器以收听Google GCM服务收到的事件:

一个)

 [BroadcastReceiver] [IntentFilter(new[] { Intent.ActionBootCompleted })] public class GCMBootReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { MyIntentService.RunIntentInService(context, intent); SetResult(Result.Ok, null, null); } } 

b)

 [assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")] [assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] [assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")] [assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")] [assembly: UsesPermission(Name = "android.permission.INTERNET")] namespace Consumer.Mobile.Droid.PushNotification { [BroadcastReceiver(Permission = "com.google.android.c2dm.permission.SEND")] [IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" }, Categories = new string[] { "@PACKAGE_NAME@" })] [IntentFilter(new string[] { "com.google.android.c2dm.intent.REGISTRATION" }, Categories = new string[] { "@PACKAGE_NAME@" })] [IntentFilter(new string[] { "com.google.android.gcm.intent.RETRY" }, Categories = new string[] { "@PACKAGE_NAME@" })] [IntentFilter (new[]{ Intent.ActionBootCompleted }, Categories = new[]{ Intent.CategoryDefault })] public class GCMBroadcastReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { MyIntentService.RunIntentInService(context, intent); SetResult(Result.Ok, null, null); } } } 

c)添加意图服务来处理通知

 using Android.App; using Android.Content; using Android.Graphics; using Android.Media; using Android.OS; using Android.Support.V4.App; using Consumer.Mobile.Infra; using Consumer.Mobile.Services.PushNotification; using Java.Lang; using XLabs.Ioc; using TaskStackBuilder = Android.Support.V4.App.TaskStackBuilder; namespace Consumer.Mobile.Droid.PushNotification { [Service] public class MyIntentService : IntentService { private readonly ILogger _logger; private readonly IPushNotificationService _notificationService; private readonly IPushNotificationRegister _pushNotificationRegister; public MyIntentService() { _logger = Resolver.Resolve<ILogger>(); _notificationService = Resolver.Resolve<IPushNotificationService>(); _pushNotificationRegister = Resolver.Resolve<IPushNotificationRegister>(); } static PowerManager.WakeLock _sWakeLock; static readonly object Lock = new object(); public static void RunIntentInService(Context context, Intent intent) { lock (Lock) { if (_sWakeLock == null) { // This is called from BroadcastReceiver, there is no init. var pm = PowerManager.FromContext(context); _sWakeLock = pm.NewWakeLock( WakeLockFlags.Partial, "My WakeLock Tag"); } } _sWakeLock.Acquire(); intent.SetClass(context, typeof(MyIntentService)); context.StartService(intent); } protected override void OnHandleIntent(Intent intent) { try { Context context = this.ApplicationContext; string action = intent.Action; if (action.Equals("com.google.android.c2dm.intent.REGISTRATION")) { HandleRegistration(context, intent); } else if (action.Equals("com.google.android.c2dm.intent.RECEIVE")) { HandleMessage(context, intent); } } finally { lock (Lock) { //Sanity check for null as this is a public method if (_sWakeLock != null) _sWakeLock.Release(); } } } private void HandleMessage(Context context, Intent intent) { Intent resultIntent = new Intent(this, typeof(MainActivity)); TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this); var c = Class.FromType(typeof(MainActivity)); stackBuilder.AddParentStack(c); stackBuilder.AddNextIntent(resultIntent); string alert = intent.GetStringExtra("Alert"); int number = intent.GetIntExtra("Badge", 0); var imageUrl = intent.GetStringExtra("ImageUrl"); var title = intent.GetStringExtra("Title"); Bitmap bitmap = GetBitmap(imageUrl); PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, (int)PendingIntentFlags.UpdateCurrent); NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .SetAutoCancel(true) // dismiss the notification from the notification area when the user clicks on it .SetContentIntent(resultPendingIntent) // start up this activity when the user clicks the intent. .SetContentTitle(title) // Set the title .SetNumber(number) // Display the count in the Content Info .SetSmallIcon(Resource.Drawable.Icon) // This is the icon to display .SetLargeIcon(bitmap) .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification)) .SetContentText(alert); // the message to display. // Build the notification: Notification notification = builder.Build(); // Get the notification manager: NotificationManager notificationManager = GetSystemService(Context.NotificationService) as NotificationManager; // Publish the notification: const int notificationId = 0; notificationManager.Notify(notificationId, notification); } private void HandleRegistration(Context context, Intent intent) { var token = intent.GetStringExtra("registration_id"); _logger.Info(this.Class.SimpleName, "Received Token : " + token); if (_pushNotificationRegister.ShouldSendToken(token)) { var uid = Android.Provider.Settings.Secure.GetString(MainActivity.Context.ContentResolver, Android.Provider.Settings.Secure.AndroidId); _notificationService.AddPushToken(token, DeviceUtils.GetDeviceType(), uid); } } private Bitmap GetBitmap(string url) { try { System.Net.WebRequest request = System.Net.WebRequest.Create(url); System.Net.WebResponse response = request.GetResponse(); System.IO.Stream responseStream = response.GetResponseStream(); return BitmapFactory.DecodeStream(responseStream); } catch (System.Net.WebException) { return null; } } } } 

d)实现接口IPushNotificationRegister

 using Android.App; using Android.Content; using Consumer.Mobile.Services; using Consumer.Mobile.Services.PushNotification; [assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] [assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")] // Gives the app permission to register and receive messages. [assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")] // Needed to keep the processor from sleeping when a message arrives [assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")] [assembly: UsesPermission(Name = "android.permission.RECEIVE_BOOT_COMPLETED")] namespace Consumer.Mobile.Droid.PushNotification { public class PushNotificationRegister : IPushNotificationRegister { public override void ExtractTokenAndRegister() { string senders = AndroidConfig.GCMSenderId; Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER"); intent.SetPackage("com.google.android.gsf"); intent.PutExtra("app", PendingIntent.GetBroadcast(MainActivity.Context, 0, new Intent(), 0)); intent.PutExtra("sender", senders); MainActivity.Context.StartService(intent); } } } 

iOS实现:

4)在你的AppDelegate ,添加下面的方法:

一个)

 public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { var deviceTokenString = deviceToken.ToString().Replace("<","").Replace(">", "").Replace(" ", ""); var notificationService = Resolver.Resolve<IPushNotificationService>(); var pushNotificationRegister = Resolver.Resolve<IPushNotificationRegister>(); if (pushNotificationRegister.ShouldSendToken(deviceTokenString)) { var uid = UIDevice.CurrentDevice.IdentifierForVendor.AsString(); notificationService.AddPushToken(deviceTokenString, DeviceUtils.GetDeviceType(), uid); } } 

b)实施IPushNotificationRegister

 using Consumer.Mobile.Services; using Consumer.Mobile.Services.PushNotification; using UIKit; namespace Consumer.Mobile.iOS.PushNotification { public class iOSPushNotificationRegister : IPushNotificationRegister { public override void ExtractTokenAndRegister() { const UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound; UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes); } } } 

关于WP,我没有实现。

如果您需要使用PushSharp在服务器端的代码,请告诉我。

您可以在这里查看我的解决scheme的客户端示例

我已经build议通过xamarin支持和表单使用下面的插件。

这个插件运作良好

https://github.com/rdelrosario/xamarin-plugins/tree/master/PushNotification

一旦我开始工作,将更新答案。

更新:

我推送通知适用于iOS和Android。

我使用了Google云消息传递客户端 ,这是一个非常棒的Android组件,不需要像这个答案中提到的那样写很多代码。

我的iOS实现与此类似,不需要太多的代码。

并从服务器推送通知我使用了PushSharp的nuget包。

我没有在WP中实现,因为在我的项目中这不是必需的。

这个推送通知的Xamarin帮助值得一读,如果你要实现推送通知。

在Xamarin Forms中,你也可以使用像Donky这样的通知SDK(这是欧洲相当于美国的城市飞艇)。 您可以在一天之内轻松制作可伸缩的通知项目,而且我每次使用此SDK在35分钟内创build了两次WhatsApp克隆shell。 请参阅http://docs.mobiledonky.com

这在纯Xamarin.Forms中是不可能的,但是实现一个可以在App.cs中处理它们的解决scheme是相当简单的(尽pipe这需要特定于平台的实现)。

查看Xamarin.Forms.Labs项目中的IXForms实现,其中通知被引导回Forms项目:

https://github.com/XLabs/Xamarin-Forms-Labs

更具体地说:

https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/src/Platform/XLabs.Platform/Mvvm

最近有一篇关于在Xamarin表单上实现推送通知的博客post(以及每个单独的平台,因为没有基于表单的实现),使用Azure移动服务。

http://www.xamarinhelp.com/push-notifications/

你可能会看看这个开箱即用的Appboy组件。 https://components.xamarin.com/view/appboy-sdk-bindings

正如其他人所说,没有一些特定于平台的组件,就无法做到这一点。