Я следую учебному пособию https://docs.microsoft.com/en-gb/azure/app-service-mobile/app-service-mobile-xamarin-forms-get-started-push, (добавление push-уведомлений в проект Android)
Вот метод, который связывается с сервером:
async Task SendRegistrationToServerAsync(string token)
{
try
{
// Formats: https://firebase.google.com/docs/cloud-messaging/concept-options
// The "notification" format will automatically displayed in the notification center if the
// app is not in the foreground.
const string templateBodyFCM =
"{" +
"\"notification\" : {" +
"\"body\" : \"$(messageParam)\"," +
"\"title\" : \"Xamarin University\"," +
"\"icon\" : \"myicon\" }" +
"}";
var templates = new JObject();
templates["genericMessage"] = new JObject
{
{"body", templateBodyFCM}
};
var client = new MobileServiceClient(Organizer.App.MobileServiceUrl);
var push = client.GetPush();
await push.RegisterAsync(token, templates); // CRASH!!!
// Push object contains installation ID afterwards.
Console.WriteLine(push.InstallationId.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Debugger.Break();
}
}
Сбой при выполнении метода RegisterAsync:
{Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: запрос не может быть выполнен. (Несанкционированное)
в Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient + d__24.MoveNext () [0x001da] в <24dbefba60fd49f4b193cdf58abf3290>: 0
--- Конец стека трассировки от предыдущего местоположения, где было сгенерировано исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача System.Threading.Tasks.Task) [0x0003e] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (задача System.Threading.Tasks.Task) [0x00008] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient + d__26.MoveNext () [0x000fc] в <24dbefba60fd49f4b193cdf58abf3290>: 0
--- Конец стека трассировки от предыдущего местоположения, где было сгенерировано исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача System.Threading.Tasks.Task) [0x0003e] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (задача System.Threading.Tasks.Task) [0x00008] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
at System.Runtime.CompilerServices.TaskAwaiter`1 [TResult] .GetResult () [0x00000] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient + d__18.MoveNext () [0x000f0] в <24dbefba60fd49f4b193cdf58abf3290>: 0
--- Конец стека трассировки от предыдущего местоположения, где было сгенерировано исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача System.Threading.Tasks.Task) [0x0003e] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (задача System.Threading.Tasks.Task) [0x00008] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] в <4d6eb5dfe2ab4eee884ef920069afd5f>: 0
в Organizer.Droid.MyFirebaseIIDService + d__1.MoveNext () [0x00095] в /Users/mirad/mobileDevGit/OrganizerApp/Organizer.Android/MainActivity.cs:159}
Ответ от сервера:
{StatusCode: 401, ReasonPhrase: «Unauthorized», версия: 1.1, содержимое: System.Net.Http.StreamContent, заголовки:
{
Передача-кодировка: чанки
Сервер: Microsoft-HTTPAPI / 2.0
Дата: пт, 31 августа 2018 13:21:44 GMT
Content-Type: application / xml; кодировка = UTF-8
}}
Что необходимо настроить на сервере, чтобы мы не получили ошибку 401?
Или что еще может быть не так?
Вот полная MainActivity:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
private const string TAG = "ANDROID_PUSH_NOTIFICATION";
protected override void OnCreate(Bundle bundle)
{
System.Diagnostics.Debug.WriteLine("In OnCreate");
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
if (Intent.Extras != null)
{
foreach (var key in Intent.Extras.KeySet())
{
var value = Intent.Extras.GetString(key);
Log.Debug(TAG, "Key: {0} Value: {1}", key, value);
}
}
IsPlayServicesAvailable();
CreateNotificationChannel();
#if DEBUG
// Force refresh of the token. If we redeploy the app, no new token will be sent but the old one will
// be invalid.
Task.Run(() =>
{
// This may not be executed on the main thread.
FirebaseInstanceId.Instance.DeleteInstanceId();
Console.WriteLine("Forced token: " + FirebaseInstanceId.Instance.Token);
});
#endif
}
public bool IsPlayServicesAvailable()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
{
// In a real project you can give the user a chance to fix the issue.
Console.WriteLine($"Error: {GoogleApiAvailability.Instance.GetErrorString(resultCode)}");
}
else
{
Console.WriteLine("Error: Play services not supported!");
Finish();
}
return false;
}
else
{
Console.WriteLine("Play Services available.");
return true;
}
}
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var channel = new NotificationChannel(MyFirebaseMessagingService.CHANNEL_ID,
"FCM Notifications",
NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
};
var notificationManager = (NotificationManager)GetSystemService(Android.Content.Context.NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
// This service handles the device's registration with FCM.
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class MyFirebaseIIDService : FirebaseInstanceIdService
{
public override void OnTokenRefresh()
{
var refreshedToken = FirebaseInstanceId.Instance.Token;
Console.WriteLine($"Token received: {refreshedToken}");
SendRegistrationToServerAsync(refreshedToken);
//SendRegistrationTokenToAzureNotificationHub(refreshedToken);
}
async Task SendRegistrationToServerAsync(string token)
{
try
{
// Formats: https://firebase.google.com/docs/cloud-messaging/concept-options
// The "notification" format will automatically displayed in the notification center if the
// app is not in the foreground.
const string templateBodyFCM =
"{" +
"\"notification\" : {" +
"\"body\" : \"$(messageParam)\"," +
"\"title\" : \"Xamarin University\"," +
"\"icon\" : \"myicon\" }" +
"}";
var templates = new JObject();
templates["genericMessage"] = new JObject
{
{"body", templateBodyFCM}
};
var client = new MobileServiceClient(Organizer.App.MobileServiceUrl);
var push = client.GetPush();
await push.RegisterAsync(token, templates);
//await push.RegisterAsync(token);
// Push object contains installation ID afterwards.
Console.WriteLine(push.InstallationId.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Debugger.Break();
}
}
}
// This service is used if app is in the foreground and a message is received.
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
public const string CHANNEL_ID = "MY_CHANNEL_ID";
public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
Console.WriteLine("Received: " + message);
// Android supports different message payloads. To use the code below it must be something like this (you can paste this into Azure test send window):
// {
// "notification" : {
// "body" : "The body",
// "title" : "The title",
// "icon" : "myicon
// }
// }
try
{
var msg = message.GetNotification().Body;
MessagingCenter.Send<object, string>(this, Organizer.App.NotificationReceivedKey, msg);
}
catch (Exception ex)
{
Console.WriteLine("Error extracting message: " + ex);
}
}
}
Спасибо за помощь.