所以处理这件事让我想起了为什么我非常讨厌远程推送通知。Xamarin Forms解决方案,特别是尝试让远程推送通知在一个特别的分布式.apk文件中工作。
这是相关代码:
Android原生项目中的FireBaseService:
using Android.App;
using Android.Content;
using Android.Util;
using AndroidX.Core.App;
using Firebase.Messaging;
using Newtonsoft.Json;
using Mobile.Client.Configuration;
using System;
using System.Linq;
using WindowsAzure.Messaging;
using Xamarin.Forms;
namespace Mobile.Client.Droid.Notifications
{
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class FirebaseService : FirebaseMessagingService
{
const string TAG = "FirebaseService";
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(TAG, "From: " + message.From);
if (message.GetNotification() != null)
{
//These is how most messages will be received
Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
SendNotification(message.GetNotification().Body);
}
else
{
//Only used for debugging payloads sent from the Azure portal
SendNotification(message.Data.Values.First());
}
}
public override async void OnNewToken(string token)
{
Log.Info(TAG, $"Registration Token: {token}");
App.Current.Properties["NotificationToken"] = token;
await App.Current.SavePropertiesAsync();
SendRegistrationToServer(token);
}
private void SendNotification(string messageBody)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.UpdateCurrent);
var notificationChannelName = AppSettingsManager.Settings["NotificationChannelName"];
var notificationBuilder = new NotificationCompat.Builder(this, notificationChannelName);
notificationBuilder.SetContentTitle("Notification")
.SetSmallIcon(Resource.Drawable.nndc_logo)
.SetContentText(messageBody)
.SetAutoCancel(true)
.SetAllowSystemGeneratedContextualActions(true)
.SetShowWhen(false)
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManager.FromContext(this);
notificationManager.Notify(0, notificationBuilder.Build());
MessagingCenter.Send(App.Current, "NotificationRecieved");
}
private void SendRegistrationToServer(string token)
{
try
{
var notificationHubName = AppSettingsManager.Settings["NotificationHubName"];
var listenConnectionString = AppSettingsManager.Settings["ListenConnectionString"];
var subscriptionTags = AppSettingsManager.Settings["SubscriptionTags"]?.Split(",");
var fCMTemplateBody = AppSettingsManager.Settings["FCMTemplateBody"];
NotificationHub hub = new NotificationHub(notificationHubName, listenConnectionString, this);
Log.Info(TAG, $"Created hub object: {hub.NotificationHubPath}");
// register device with Azure Notification Hub using the token from FCM
Registration registration = hub.Register(token, subscriptionTags);
Log.Info(TAG, $"Registered token and tags: {registration.PNSHandle}");
// subscribe to the SubscriptionTags list with a simple template.
string pnsHandle = registration.PNSHandle;
Log.Info(TAG, $"PNS Handle: {pnsHandle}");
TemplateRegistration templateReg = hub.RegisterTemplate(pnsHandle, "defaultTemplate", fCMTemplateBody, subscriptionTags);
Log.Info(TAG, $"Registered template: {templateReg.NotificationHubPath}");
}
catch (Exception e)
{
Log.Info(TAG, $"PNS REGISTRATION EXCEPTION: {JsonConvert.SerializeObject(e)}");
//Log.Error("DEBUG", $"Error registering device: {e.Message}");
}
}
}
}
Android清单:
<?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.android.mobile" android:installLocation="auto">
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28" />
<!--android:extractNativeLibs="true" had to be added below due to a VS/Xamarin Bug: https://github.com/xamarin/xamarin-android/issues/4990-->
<application android:label="APPNAME" android:icon="@mipmap/icon" android:extractNativeLibs="true" android:roundIcon="@mipmap/icon_round">
<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.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.BLUETOOTH" />
</manifest>
不管怎么说,正如标题所说,这在Debug中运行良好,它注册时没有问题,并从azure发送推送通知,这非常好。据我所知,FCM密钥与沙盒或生产的密钥相同,所以我不认为是这样,但如果我错了,请随时纠正我。
如果我在发行版中运行它,或者将其作为apk文件安装进行临时安装,我会得到以下错误:
{
"JniPeerMembers": {
"ManagedPeerType": "WindowsAzure.Messaging.NotificationHubException, Xamarin.Azure.NotificationHubs.Android, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"JniPeerTypeName": "com/microsoft/windowsazure/messaging/NotificationHubException",
"JniPeerType": {
"PeerReference": {
"Handle": {
"value": 15194
},
"Type": 2,
"IsValid": true
},
"Name": "com/microsoft/windowsazure/messaging/NotificationHubException"
},
"InstanceMethods": {},
"InstanceFields": {},
"StaticMethods": {},
"StaticFields": {}
},
"StatusCode": 400,
"StackTrace": "
at Java.Interop.JniEnvironment+InstanceMethods.CallObjectMethod (Java.Interop.JniObjectReference instance,
Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0006e] in <3f19c9fc57a34ac9a473579164f8755e>:0 n
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualObjectMethod (System.String encodedMember,
Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0002a] in <3f19c9fc57a34ac9a473579164f8755e>:0 n
at WindowsAzure.Messaging.NotificationHub.Register (System.String pnsHandle, System.String[] tags) [0x00043] in <15ee46979411457bb0abfed951cc2b1e>:0 n
at NorthNorfolk.Mobile.Client.Droid.Notifications.FirebaseService.SendRegistrationToServer (System.String token) [0x00078] in <f0d16bc144b04854b79558630f62c467>:0 n
--- End of managed WindowsAzure.Messaging.NotificationHubException stack trace
---ncom.microsoft.windowsazure.messaging.NotificationHubExceptionntat
com.microsoft.windowsazure.messaging.Connection.executeRequest(Connection.java:254)ntat
com.microsoft.windowsazure.messaging.Connection.executeRequest(Connection.java:170)ntat
com.microsoft.windowsazure.messaging.Connection.executeRequest(Connection.java:130)ntat
com.microsoft.windowsazure.messaging.NotificationHub.upsertRegistrationInternal(NotificationHub.java:446)ntat
com.microsoft.windowsazure.messaging.NotificationHub.registerInternal(NotificationHub.java:410)ntat
com.microsoft.windowsazure.messaging.NotificationHub.register(NotificationHub.java:148)ntat
com.northnorfolk.mobile.FirebaseService.n_onNewToken(Native Method)ntat
com.northnorfolk.mobile.FirebaseService.onNewToken(FirebaseService.java:38)ntat
com.google.firebase.messaging.FirebaseMessagingService.zzd(Unknown Source:86)ntat
com.google.firebase.iid.zzg.run(Unknown Source:4)ntat
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)ntat
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)ntat
com.google.android.gms.common.util.concurrent.zza.run(Unknown Source:6)ntat
java.lang.Thread.run(Thread.java:919)n",
"JniIdentityHashCode": 19017287,
"PeerReference": {
"Handle": {
"value": 19298
},
"Type": 2,
"IsValid": true
},
"Handle": {
"value": 19298
},
"Message": null,
"Data": {},
"InnerException": null,
"Source": "mscorlib",
"HResult": -2146233088
}
这是通过以下方法从FirebaseService类抛出的:
// register device with Azure Notification Hub using the token from FCM
Registration registration = hub.Register(token, subscriptionTags);
---更新---
我也在这个链接上针对github上的回购提出了这一点。他们建议在proguard或r8周围发信息。事实上,我没有设置这些,但因为我知道Xamarin和VS有时会做自己的事情,所以我设置了r8收缩器,现在当我运行它时,我得到了下面的错误,它看起来更具描述性,因为它可能显示400个错误。
{
"JniPeerMembers": {
"ManagedPeerType": "WindowsAzure.Messaging.NotificationHubException, Xamarin.Azure.NotificationHubs.Android, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"JniPeerTypeName": "com/microsoft/windowsazure/messaging/NotificationHubException",
"JniPeerType": {
"PeerReference": {
"Handle": {
"value": 17866
},
"Type": 2,
"IsValid": true
},
"Name": "com/microsoft/windowsazure/messaging/NotificationHubException"
},
"InstanceMethods": {},
"InstanceFields": {},
"StaticMethods": {},
"StaticFields": {}
},
"StatusCode": 400,
"StackTrace": " at Java.Interop.JniEnvironment+InstanceMethods.CallObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0006e] in <3f19c9fc57a34ac9a473579164f8755e>:0 n at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0002a] in <3f19c9fc57a34ac9a473579164f8755e>:0 n at WindowsAzure.Messaging.NotificationHub.Register (System.String pnsHandle, System.String[] tags) [0x00043] in <254d369ec5544bb1b606035994077f91>:0 n at NorthNorfolk.Mobile.Client.Droid.Notifications.FirebaseService.SendRegistrationToServer (System.String token) [0x00078] in <4b8b745c15df475a92a1855a0ba61d95>:0 n --- End of managed WindowsAzure.Messaging.NotificationHubException stack trace ---ncom.microsoft.windowsazure.messaging.NotificationHubExceptionntat com.microsoft.windowsazure.messaging.Connection.executeRequest(Unknown Source:146)ntat com.microsoft.windowsazure.messaging.Connection.executeRequest(Unknown Source:134)ntat com.microsoft.windowsazure.messaging.Connection.executeRequest(Unknown Source:7)ntat com.microsoft.windowsazure.messaging.NotificationHub.upsertRegistrationInternal(Unknown Source:22)ntat com.microsoft.windowsazure.messaging.NotificationHub.registerInternal(Unknown Source:48)ntat com.microsoft.windowsazure.messaging.NotificationHub.register(Unknown Source:27)ntat crc64d75b20eac0c397e9.FirebaseService.n_onNewToken(Native Method)ntat crc64d75b20eac0c397e9.FirebaseService.onNewToken(Unknown Source:0)ntat com.google.firebase.messaging.FirebaseMessagingService.handleIntent(Unknown Source:53)ntat com.google.firebase.messaging.EnhancedIntentService.lambda$processIntent$0$EnhancedIntentService(Unknown Source:1)ntat com.google.firebase.messaging.EnhancedIntentService$$Lambda$0.run(Unknown Source:6)ntat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)ntat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)ntat com.google.android.gms.common.util.concurrent.zza.run(Unknown Source:7)ntat java.lang.Thread.run(Thread.java:764)n",
"JniIdentityHashCode": 196544507,
"PeerReference": {
"Handle": {
"value": 18122
},
"Type": 2,
"IsValid": true
},
"Handle": {
"value": 18122
},
"Cause": null,
"Message": null,
"Data": {},
"InnerException": null,
"Source": "mscorlib",
"HResult": -2146233088
}
任何人对以上有任何想法,这让我有点抓狂。
通知中心客户端
我建议将Microsoft.Azure.NotificationHubs NuGet包与NotificationHubClient.CreateFcmNativeRegistrationAsync
一起使用以向通知中心注册。
以下是我在开源应用商店应用程序GitTrends中注册时使用的代码:https://github.com/brminnick/GitTrends/blob/c016825c792f655f3ad844908b54688aa38b3f26/GitTrends.Android/Services/NotificationService_Android.cs#L87-L98
var hubClient = NotificationHubClient.CreateClientFromConnectionString("Your Notification Hub Connection String", "Your Notification Hub Name");
await hubClient.CreateFcmNativeRegistrationAsync(token);
谷歌服务JSON
我还建议您确保在Android项目中包含google-services.json
文件。(这是我在GitTrends应用程序中使用的一个(。
您还需要将其作为GoogleServicesJson
项目添加到Android CSPROJ文件中:
https://github.com/brminnick/GitTrends/blob/c016825c792f655f3ad844908b54688aa38b3f26/GitTrends.Android/GitTrends.Android.csproj#L790
<ItemGroup>
<GoogleServicesJson Include="google-services.json" />
</ItemGroup>