#android #xamarin #mono #azure-notificationhub
#Android #xamarin #моно #azure-notificationhub
Вопрос:
Я следую этому руководству, чтобы протестировать notification hub для Android, и он работает https://learn.microsoft.com/en-us/azure/notification-hubs/xamarin-notification-hubs-push-notifications-android-gcm
но мне нужно завершить процесс регистрации пользователя и получить идентификатор пользователя, чтобы я мог использовать идентификатор пользователя как тег для регистрации в Azure Notification hub. Поэтому вместо того, чтобы сразу регистрироваться MainAcitivty.cs
, я просто сохраняю токен в базе данных.
поэтому вместо того, чтобы иметь это
public override void OnNewToken(string token)
{
Log.Debug(TAG, "FCM token: " token);
SendRegistrationToServer(token);
}
я просто вставляю токен в локальную базу данных
public override void OnNewToken(string token)
{
Log.Debug(TAG, "FCM token: " token);
LocalDb.InsertDeviceToken(token);
}
когда весь процесс регистрации завершен, у меня есть следующее в RegistrationAcitivty.cs
var notificationUtil = new NotificationUtil();
notificationUtil.SendRegistrationToServer(this.ApplicationContext);
ниже приведен код для NotificationUtil.cs
using System;
using System.Collections.Generic;
using Android.Util;
using PantAppLib.source.dbaccess;
using PantAppLib.source.models;
using WindowsAzure.Messaging;
namespace PantAppAndroid.Utils
{
public class NotificationUtil
{
public void SendRegistrationToServer(Android.Content.Context context)
{
try
{
// Register with Notification Hubs
NotificationHub hub = new NotificationHub(Constants.NotificationHubName,
Constants.ListenConnectionString, context);
var userProfile = LocalDb.GetUserProfile();
if (userProfile != null)
{
var tags = new List<string>() { userProfile.Id };
var token = LocalDb.GetDeviceToken().TokenValue;
Registration registration = hub.Register(token, tags.ToArray());
var regID = registration.RegistrationId;
Log.Debug("MyFirebaseMsgService", $"Successful registration of ID {regID}");
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
Я могу только догадываться, что я использую здесь правильный контекстный объект, и когда я запускаю код, я нажимаю на следующее исключение
{Android.OS.NetworkOnMainThreadException: Exception of type 'Android.OS.NetworkOnMainThreadException' was thrown.
at Java.Interop.JniEnvironment InstanceMethods.CallObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0006e] in <42748fcc36b74733af2d9940a8f3cc8e>:0
at Java.Interop.JniPeerMembers JniInstanceMethods.InvokeVirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0002a] in <42748fcc36b74733af2d9940a8f3cc8e>:0
at WindowsAzure.Messaging.NotificationHub.Register (System.String pnsHandle, System.String[] tags) [0x00043] in <7ef3a358b177460dacd73e56198bd8f2>:0
at PantAppAndroid.Utils.NotificationUtil.SendRegistrationToServer (Android.Content.Context context) [0x00041] in C:UsersweihasourcereposApp2PantAppAndroidUtilsNotificationUtil.cs:36
--- End of managed Android.OS.NetworkOnMainThreadException stack trace ---
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:117)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:105)
at java.net.InetAddress.getAllByName(InetAddress.java:1154)
at com.android.okhttp.Dns$1.lookup(Dns.java:39)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:175)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:141)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:83)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:26)
at com.microsoft.windowsazure.messaging.Connection.executeRequest(Connection.java:213)
at com.microsoft.windowsazure.messaging.Connection.executeRequest(Connection.java:170)
at com.microsoft.windowsazure.messaging.Connection.executeRequest(Connection.java:130)
at com.microsoft.windowsazure.messaging.NotificationHub.refreshRegistrationInformation(NotificationHub.java:301)
at com.microsoft.windowsazure.messaging.NotificationHub.registerInternal(NotificationHub.java:399)
at com.microsoft.windowsazure.messaging.NotificationHub.register(NotificationHub.java:148)
at mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
at mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:30)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
}
последующее руководство — отправка уведомлений на определенные устройства не для xamarin Android, поэтому я не уверен, как это сделать правильно.
Ответ №1:
Это NetworkOnMainThreadException
ключ, глядя на стек исключений, NotificationHub.Register
это ваша проблема, поскольку она не может быть выполнена в потоке пользовательского интерфейса из-за происходящих вызовов нижележащих сетей, просто выполните ее в фоновом потоке.
Пример:
~~~
Registration registration;
await Task.Run(() => registration = hub.Register(token, tags.ToArray()));
~~~