我一直在尝试在VS2019中的xamarin.forms应用程序中实现FCM,但我已经在一个问题上停留了一个星期。有人可以帮我吗?这可能是我错过的明显的东西......
问题:当我将 microsoft xamarin 代码(请参阅下面的链接(移植到我的 xamarin.forms 应用中时,FCM 通知将仅显示在 android 模拟器中,而不会显示在 android 物理设备上。
我尝试将其剥离回基本的xamarin.forms应用程序,并且遇到了完全相同的问题。该代码类似于在以下位置找到的 Microsoft 示例解决方案: https://learn.microsoft.com/en-us/samples/xamarin/monodroid-samples/firebase-fcmnotifications/
我会注意到,编译 microsoft 示例实际上确实适用于模拟设备和物理设备,当应用程序最小化时,两者都接收和显示通知。
我已经在多个物理设备上尝试过这个,结果都相同 - 我永远不会在物理设备上收到 FCM 消息,编译完全相同的代码并在模拟环境中运行 - 没有概率!我每次都收到 FCM 消息。 在物理设备(其中 4 个(上是运行三星、MIUI、华为和库存安卓的选择。我已经确保通常的事情,例如启用自动启动、禁用电池优化、确保我的应用允许通知,并确保在应用中 - 它已注册 FCM 通知并允许它们。(都无济于事(。
我添加了相应的 NuGet 包 (Xamarin.Essentials, Xamarin.Firebase.Common, Xamarin.FirebaseIid, Xamarin.Firebase.Messaging, Xamarin.GooglePlayServices.Base+Basement+Tasks(. 我没有收到任何编译器错误或其他警告。
我注意到 OnCreate 方法中存在一些差异,我正在为 savedInstanceState 传递数据,看起来好像在 MS 示例中他们正在传递一个新的捆绑包,但我不清楚这是否会有任何区别,并且不会解释这种行为。
安卓清单.xml
<?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.corp.my-fcm-test" android:installLocation="auto">
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28" />
<application android:label="my-fcm-test">
<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" />
<uses-permission android:name="android.permission.INTERNET" />
主要活动.cs:
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using myappname.Droid;
using Android.Gms.Common;
using Firebase.Iid;
using Firebase.Messaging;
using Xamarin.Forms;
using System.Runtime.CompilerServices;
namespace my_fcm_test.Droid
{
[Activity(Label = "my_fcm_test", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
const string TAG = "*** *** *** MainActivity";
internal static readonly string CHANNEL_ID = "my_notification_channel";
internal static readonly int NOTIFICATION_ID = 100;
TextView msgText;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
// go through each of the keys in inten.extras and log what they are.
if (Intent.Extras != null)
{
foreach (var key in Intent.Extras.KeySet())
{
var value = Intent.Extras.GetString(key);
Console.WriteLine(TAG, "Key: {0} Value: {1}", key, value);
}
}
CreateNotificationChannel();
IsPlayServicesAvailable();
Console.WriteLine(TAG, "InstanceID token: " + FirebaseInstanceId.Instance.Token);
FirebaseMessaging.Instance.SubscribeToTopic("news");
Console.WriteLine(TAG, "Subscribed to remote notifications");
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
public bool IsPlayServicesAvailable()
{
var resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
{
msgText.Text = GoogleApiAvailability.Instance.GetErrorString(resultCode);
}
else
{
Console.WriteLine("*** *** *** This device is not supported");
Finish();
}
return false;
}
Console.WriteLine("*** *** *** Google Play Services is 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(CHANNEL_ID, "FCM Notifications", NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
}
MyFirebaseMessagingServices.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V4.App;
using Android.Views;
using Android.Widget;
using Firebase.Messaging;
using my_fcm_test.Droid;
namespace my-fcm-test.Droid
{
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string TAG = "MyFirebaseMsgService";
public override void OnMessageReceived(RemoteMessage message)
{
Console.WriteLine(TAG, "From: " + message.From);
var body = message.GetNotification().Body;
Console.WriteLine(TAG, "Notification Message Body: " + body);
SendNotification(body, message.Data);
}
void SendNotification(string messageBody, IDictionary<string, string> data)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
foreach (var key in data.Keys)
{
intent.PutExtra(key, data[key]);
}
var pendingIntent = PendingIntent.GetActivity(this, MainActivity.NOTIFICATION_ID, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID)
.SetContentTitle("FCM Message")
.SetContentText(messageBody)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(MainActivity.NOTIFICATION_ID, notificationBuilder.Build());
}
}
}
MyFirebaseIIDService.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Firebase.Iid;
namespace my-fcm-test.Droid
{
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class MyFirebaseIIDService : FirebaseInstanceIdService
{
const string TAG = "MyFirebaseIIDService";
public override void OnTokenRefresh()
{
var refreshedToken = FirebaseInstanceId.Instance.Token;
Console.WriteLine(TAG, "Refreshed token: " + refreshedToken);
SendRegistrationToServer(refreshedToken);
}
void SendRegistrationToServer(string token)
{
// Add custom implementation, as needed.
}
}
}
当然,我已经包含了我的google-services.json,我将不得不假设该文件是正确的,因为:
a( 我生成了一个 google-services.json 文件以与 Microsoft xamarin 示例一起使用,它在所有设备上都运行良好。
b( 我不会在执行调试版本和发布版本之间更改 google-services.json 文件。
- 注意,我已经更改了这篇文章的命名空间。
任何帮助感谢...
打开 Android项目属性,在 Android 选项(打包属性(代码缩减器中将其留空。它会工作