Как использовать Push-уведомления в формах Xamarin
Я приложение, использующее Xamarin.Формы, ориентированные на IOS, Android и WP 8.
Мне нужна функция push-уведомлений в моем приложении.
Я видел pushsharp Демос и кажется перспективным. Но все коды, которые я видел, выполняются отдельно для каждой платформы.
Я хотел бы, чтобы это было сделано в Xamarin.Формы проекта, где-то в приложении.cs, чтобы мне не нужно было повторять код для регистрации устройства и обрабатывать, как должны обрабатываться push-уведомления.
любая помощь была бы весьма признательна. Примеры кодов или ссылки на учебник приветствуются.
редактировать : я реализовал его на основе ответ. Вот это ссылке на мой ответ.
6 ответов
я только что реализовал push-уведомление несколько дней назад ,и я поделюсь своим решением здесь (на основе PushSharp)
шаг за шагом руководство:
1) в вашем общем проекте создайте интерфейс под названием IPushNotificationRegister
public interface IPushNotificationRegister
{
void ExtractTokenAndRegister();
}
этот интерфейс используется для извлечения маркера push и отправки его на сервер. этот токен уникален для каждого устройства.
2) в вашем общем проекте вы должны вызвать ExtractTokenAndRegister
(используя ваш любимый IOC, я назвал его сразу после входа в систему).
Android Реализация:
3) Добавить приемники для прослушивания событий, полученных службой Google GCM:
a)
[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
добавьте следующий метод:
a)
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, дайте мне знать.
вы можете проверить образцы клиента я основывал свое решение здесь
Мне было предложено использовать следующий плагин с помощью поддержки xamarin и форм.
этот плагин работает хорошо
https://github.com/rdelrosario/xamarin-plugins/tree/master/PushNotification
обновит ответ, как только я заставлю его работать.
обновление :
я получил push-уведомления, работающие как для iOS, так и для Android.
Я Клиент Обмена Сообщениями Google Cloud, отличный компонент для Android, и не нужно было писать большую часть кода, как указано в ответ.
моя реализация iOS была похожа на этой, много кода не требуется.
и для нажатия уведомлений с сервера я использовал пакет nuget из PushSharp.
Я не реализовал в WP, так как это не требовалось в моем проект.
этой Xamarin справка по Push-уведомлениям стоит прочитать, если вы собираетесь реализовать Push-уведомления.
Update (июнь 2018) - используйте следующий плагин для FCM на iOS и Android, ti поддерживает Xamarin.Формы -FirebasePushNotificationPlugin
в формах Xamarin вы также можете использовать SDK уведомлений, такой как Donky (который является европейским эквивалентом американского городского дирижабля); вы можете легко сделать масштабируемый проект уведомлений за один день, я дважды построил оболочки клонов WhatsApp менее чем за 35 минут каждый раз, используя этот SDK. См.http://docs.mobiledonky.com
Это невозможно сделать в чистом Xamarin.Формы, но относительно тривиальны для реализации решения, посредством которого их можно обрабатывать в приложении.cs (хотя для этого потребуются конкретные реализации Платформы).
взгляните на реализацию IXForms в Xamarin.Формы.Проект Labs, в котором уведомления направляются обратно в проект Forms:
https://github.com/XLabs/Xamarin-Forms-Labs
и многое другое в частности:
https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/src/Platform/XLabs.Platform/Mvvm
недавно здесь появилось сообщение в блоге о реализации Push-уведомлений на формах Xamarin (ну, на каждой отдельной платформе, потому что нет реализации на основе форм), используя мобильные службы Azure.
вы можете посмотреть на компонент Appboy, который поддерживает это из коробки. https://components.xamarin.com/view/appboy-sdk-bindings
Как говорили другие, вы не можете обойтись вообще без некоторых компонентов, специфичных для платформы.