[英]Xamarin.Android push notification is breaking the app when App is Not Running
[英]How can I receive a Push Notification when my Xamarin Android app is stopped?
我见过许多不同类型的解决方案,这些解决方案在过去可能有效,但没有一个对我自己有效。 这是人们所说的有效的、无效的、改变的等等的雷区。但我不仅试图找到解决方案,而且希望找到一种理解——因为现在我很困惑。
我现在可以做什么- 如果应用程序位于前台/后台,我的 Xamarin Forms 应用程序 (Android) 可以接收推送通知,我还可以在用户点击这些通知时拦截它们,以便我可以告诉我的应用程序要做什么。
我正在尝试做什么- 基本上是上述但在应用程序已完全停止的状态下。
我有我的 Firebase 消息设置,它连接到 Azure 通知中心 - 不幸的是,我不会离开 Azure(以防万一有人建议放弃它)。 我目前拥有的大部分信息是我设法从各种 Microsoft 文档中拼接在一起的信息( 这里我不使用 AppCenter - 只是用它来交叉引用任何有用的代码, 这里, 这里和这里),其他 StackOverflow 问题(例如这里, 这里和这里- 链接太多了)和 Xamarin 论坛 - 如果有任何过时的代码被使用,再次道歉(请告诉我 - 我已尽力使用-日期方法等)。
我发送的推送通知类型是我在此处阅读的数据消息,我在通知中使用自定义数据,因此我理解这是我想要发送的正确推送类型,如下所示。
{
"data": {
"title": "Title Test",
"body": "Push notification body test",
"area": "SelectedPage"
}
}
以下是我在项目中设置的当前代码,用于处理迄今为止的推送通知。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.pushtesting" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="Push Testing">
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
我有LaunchMode = LaunchMode.SingleTop
,我的理解是否正确,因为这是为了确保仍然使用当前的 Activity 而不是创建一个新的 - 例如,当用户点击通知时 - 实现它加上附加代码(下面) 似乎表明这是真的。
protected override void OnNewIntent(Intent intent) {
base.OnNewIntent(intent);
String area = String.Empty;
String extraInfo = String.Empty;
if (intent.Extras != null) {
foreach (String key in intent.Extras.KeySet()) {
String value = intent.Extras.GetString(key);
if (key == "Area" && !String.IsNullOrEmpty(value)) {
area = value;
} else if (key == "ExtraInfo" && !String.IsNullOrEmpty(value)) {
extraInfo = value;
}
}
}
NavigationExtension.HandlePushNotificationNavigation(area, extraInfo);
}
当用户与之交互时,使用OnNewIntent
拦截推送通知。
using System;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Support.V4.App;
using Android.Util;
using Firebase.Messaging;
using PushTesting.Models;
using WindowsAzure.Messaging;
namespace PushTesting.Droid.Services {
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class OcsFirebaseMessaging : FirebaseMessagingService {
private const String NotificationChannelId = "1152";
private const String NotificationChannelName = "Push Notifications";
private const String NotificationChannelDescription = "Receive notifications";
private NotificationManager notificationManager;
public override void OnNewToken(String token) => SendTokenToAzure(token);
/// <summary>
/// Sends the token to Azure for registration against the device
/// </summary>
private void SendTokenToAzure(String token) {
try {
NotificationHub hub = new NotificationHub(Constants.AzureConstants.NotificationHub, Constants.AzureConstants.ListenConnectionString, Android.App.Application.Context);
Task.Run(() => hub.Register(token, new String[] { }));
} catch (Exception ex) {
Log.Error("ERROR", $"Error registering device: {ex.Message}");
}
}
/// <summary>
/// When the app receives a notification, this method is called
/// </summary>
public override void OnMessageReceived(RemoteMessage remoteMessage) {
Boolean hasTitle = remoteMessage.Data.TryGetValue("title", out String title);
Boolean hasBody = remoteMessage.Data.TryGetValue("body", out String body);
Boolean hasArea = remoteMessage.Data.TryGetValue("area", out String area);
Boolean hasExtraInfo = remoteMessage.Data.TryGetValue("extraInfo", out String extraInfo);
PushNotificationModel push = new PushNotificationModel {
Title = hasTitle ? title : String.Empty,
Body = hasBody ? body : String.Empty,
Area = hasArea ? area : String.Empty,
ExtraInfo = hasExtraInfo ? extraInfo : String.Empty
};
SendNotification(push);
}
/// <summary>
/// Handles the notification to ensure the Notification manager is updated to alert the user
/// </summary>
private void SendNotification(PushNotificationModel push) {
// Create relevant non-repeatable Id to allow multiple notifications to be displayed in the Notification Manager
Int32 notificationId = Int32.Parse(DateTime.Now.ToString("MMddHHmmsss"));
Intent intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
intent.PutExtra("Area", push.Area);
intent.PutExtra("ExtraInfo", push.ExtraInfo);
PendingIntent pendingIntent = PendingIntent.GetActivity(this, notificationId, intent, PendingIntentFlags.UpdateCurrent);
notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
// Creates Notification Channel for Android devices running Oreo (8.0.0) or later
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O) {
NotificationChannel notificationChannel = new NotificationChannel(NotificationChannelId, NotificationChannelName, NotificationImportance.High) {
Description = NotificationChannelDescription
};
notificationManager.CreateNotificationChannel(notificationChannel);
}
// Builds notification for Notification Manager
Notification notification = new NotificationCompat.Builder(this, NotificationChannelId)
.SetSmallIcon(Resource.Drawable.ic_launcher)
.SetContentTitle(push.Title)
.SetContentText(push.Body)
.SetContentIntent(pendingIntent)
.SetAutoCancel(true)
.SetShowWhen(false)
.Build();
notificationManager.Notify(notificationId, notification);
}
}
}
最后是我的 Firebase 类,我使用OnNewToken()
注册到 Azure, OnMessageReceived()
被覆盖,因此我可以处理收到的推送通知,然后SendNotification()
用于构建和显示通知。
任何和所有帮助将不胜感激!
对我来说有很多问题(更多细节在这里):
最后,解决方案是查看-> 其他 Windows -> 设备日志并再次运行该应用程序以避免强制停止状态,以发现 ctor 生命周期问题,我必须通过移出触及来自 FirebaseMessagingService 的共享应用程序库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.