我一直在关注https://docs.microsoft.com/en-gb/azure/app-service-mobile/app-service-mobile-xamarin-forms-get-started-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] in <24dbefba60fd49f4b193cdf58abf3290>:0 ---从抛出异常的上一个位置的堆栈跟踪结束---在System.Runtime.CompilerServices.TaskAwaiter .ThrowForNonSuccess(System.Threading.Tasks.Task任务)[0x0003e]位于<4d6eb5dfe2ab4eee884ef920069afd5f>中的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task任务)[0x00028]中的<4d6eb5dfe2ab4eee884ef920069afd5f>:0处于<4d6eb5dfe2ab4eee884ef920069afd5f>中的System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(System.Threading.Tasks.Task任务)[0x00008],位于<4d6eb5dfe2ab4eee884ef920069afd5f>中的System.Runtime.CompilerServices.TaskAwaiter.GetResult()[0x00000]中:0在Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient d__26.MoveNext()[0x000fc] in <24dbefba60fd49f4b193cdf58abf3290>:0 ---来自先前位置的堆栈跟踪结束,其中异常是在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks . )的<4d6eb5dfe2ab4eee884ef920069afd5f>中的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task任务)[0x0003e]抛出---任务任务)[0x00028]在<4d6eb5dfe2ab4eee884ef920069afd5f>:0中System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(System.Threading.Tasks.Task任务)[0x00008]在<4d6eb5dfe2ab4eee884ef920069afd5f>:0在System.Runtime.CompilerServices.TaskAwaiter` 1 [TResult] .GetResult()[0x00000]在<4d6eb5dfe2ab4eee884ef920069afd5f>:0中的Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient d__18.MoveNext()[0x000f0] in <24dbefba60fd49f4b193cdf58abf3290>:0 ---从上一个位置开始的堆栈跟踪异常被抛出---在System.Runtime.CompilerServices.Task的<4d6eb5dfe2ab4eee884ef920069afd5f>中的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task任务)[0x0003e]:0 Awaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task任务)[0x00028]在<4d6eb5dfe2ab4eee884ef920069afd5f>中的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] in /Users/mirad/mobileDevGit/OrganizerApp/Organizer.Android/ MainActivity.cs:159}
来自服务器的响应是:
{StatusCode:401,ReasonPhrase:'Unauthorized',版本:1.1,内容:System.Net.Http.StreamContent, Headers :{Transfer-Encoding:chunked Server:Microsoft-HTTPAPI / 2 . 0日期:星期五,2018年8月31日13: 21:44 GMT Content-Type:application / xml; charset = 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);
}
}
}
谢谢你的帮助 .