【问题标题】:Can't get FCM Remote Notifications to display when Xamarin.Forms Android app is closed, stopped or not running当 Xamarin.Forms Android 应用程序关闭、停止或未运行时,无法显示 FCM 远程通知
【发布时间】:2019-02-02 08:27:15
【问题描述】:

我使用这些说明将基于 Azure 通知中心 FCM 的远程通知添加到我的 Xamarin.Forms Android 应用程序。

https://docs.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-xamarin-forms-get-started-push

当应用程序打开或在后台运行时,我可以接收远程通知,但是当我关闭应用程序或停止应用程序时,我不再收到远程通知。

我的测试设备运行 API 级别 22,因此我使用以下方法在设备上构建通知。

Android.Support.V4.App.NotificationCompat.Builder builder = new Android.Support.V4.App.NotificationCompat.Builder(this)

对于 API 级别 26+,我使用 follow 方法和通道在设备上构建通知。

var builder = new Android.App.Notification.Builder(this)

我在想我必须使用 BroadcastReceiver 来实现这一点,但在阅读了这么多关于这个主题的 cmets 之后,我真的不知道。我的应用是使用 API 27 编译的,并以 API 27 为目标。

方法一

我正在尝试创建一个 BroadcastReceiver,它将在通知到达时使用显式 Intent 启动 MyService。不幸的是,这不适用于我的 API Level 22 测试设备。

//[BroadcastReceiver]
//[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
[BroadcastReceiver(Enabled = true, Exported = true)]
    [IntentFilter(new[] { "com.xamarin.example.TEST" })]
    public class MyBroadcastReceiver : BroadcastReceiver
    {

        public override void OnReceive(Context context, Intent intent)
        {
            string message = intent.GetStringExtra("message");
            string title = intent.GetStringExtra("title");
            string id = intent.GetStringExtra("id");

            //Explicit Intent to launch MyService
            Intent intent2 = new Intent(Application.Context, typeof(MyService));
            intent2.PutExtra("message", message);
            intent2.PutExtra("title", title);
            intent2.PutExtra("id", id);

            Application.Context.StartService(intent2);
        }

     }


// Service is exported and given a name so other applications can use it
    [Service(Exported = true, Name = "com.mycompany.myapp.MyService")]
    // Intent filter only needed for Implicit Intents
    //[IntentFilter(new string[] { "com.xamarin.example.TEST" })]
    public class MyService : Service
    {

        public static string PRIMARY_NOTIF_CHANNEL = "default";

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

        [return: GeneratedEnum]
        public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
        {
            var pm = PowerManager.FromContext(this);
            var wakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "Notification");
            wakeLock.Acquire();

            string message = intent.GetStringExtra("message");
            string title = intent.GetStringExtra("title");
            string id = intent.GetStringExtra("id");

            var intent2 = new Intent(this, typeof(MainActivity));
            intent2.PutExtra("id", id);
            intent2.AddFlags(ActivityFlags.ClearTop);

            var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);

            NotificationManager notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);

            Android.Support.V4.App.NotificationCompat.Builder builder = new Android.Support.V4.App.NotificationCompat.Builder(this)
                   .SetAutoCancel(true)
                   .SetContentIntent(pendingIntent)
                   .SetContentTitle(title)
                   .SetContentText(message)
                   .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification))
                   .SetVibrate(new long[1])
                   //1 is Hi
                   .SetPriority(1)
                   .SetLargeIcon(BitmapFactory.DecodeResource(Resources, SalesFlash.Droid.Resource.Drawable.Icon_lg))
                   .SetSmallIcon(MyApp.Droid.Resource.Drawable.icon)
                   .SetChannelId(PRIMARY_NOTIF_CHANNEL);

            notificationManager = NotificationManager.FromContext(this);
            notificationManager.Notify(0, builder.Build());

            wakeLock.Release();

            //return StartCommandResult.Sticky;

            return base.OnStartCommand(intent, flags, startId);
        }

        public override void OnDestroy()
        {
            base.OnDestroy();
        }
    }

根据这篇文章,BroadCastReceiver 不适用于 FCM 通知。 https://stackoverflow.com/a/44287962/5360237

这篇文章似乎显示了一个 BroadcastReceiver 接受通知。 https://stackoverflow.com/a/45616014/5360237

非常感谢任何帮助。提前致谢!

【问题讨论】:

  • @G.hakim 感谢您的评论。您是否建议在 MainActivity 的 OnCreate 方法中放置以下代码 sn-p 将允许应用程序在关闭、停止或未运行时接收通知? if (Intent.Extras != null) {foreach (var key in Intent.Extras.KeySet()) { var value = Intent.Extras.GetString(key)} } 如果是这样,这对我不起作用。根据我的阅读,我需要创建一个 BroadcastReceiver、一个 StartService 或使用 Firebase Job Dispatcher 在应用关闭时处理通知。
  • 如果您收到来自 firebase android 的推送,您无需执行任何此类操作,默认情况下会发送一个推送,您只需在打开应用程序时处理它
  • @G.hakim 正如我原来的帖子中所指出的,当我的应用程序处于前台和后台时,我可以收到通知。当应用程序停止时,关闭而不运行是我遇到的问题。当应用关闭时,您知道如何处理似乎已停止 FirebaseMessagingService 的设备上的通知吗?
  • 即使应用程序关闭,firebase 也会对其进行管理,您不必编写任何类型的任何额外代码

标签: firebase xamarin.forms xamarin.android firebase-cloud-messaging azure-notificationhub


【解决方案1】:

这是我读过的最好的解释问题的帖子。它还为受影响的设备提供了手动解决方案。 https://medium.freecodecamp.org/why-your-push-notifications-never-see-the-light-of-day-3fa297520793 通过导航到设置 - 应用程序,然后滑动到受限选项卡,我能够在我的阿尔卡特 One Touch Pop 上让通知工作(当应用程序关闭、停止或未运行时)。从这里,我可以取消选中我的应用。

注意:使用数据负载将消息传递到我的 Android 应用程序。即使我在前台和后台收到通知,我还是继续在我的 AndroidManifest 中添加了以下权限。

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  

此权限用于自动启动。我还使用 Azure App Center 将签名的 APK 分发到我的测试设备。希望这对其他人有帮助。

更新:我删除了RECEIVE_BOOT_COMPLETE 权限并进行了调试构建。我通过将应用程序从屏幕上滑出,将应用程序从 Debug(连接到 Visual Studio)中关闭。然后我发送了一个通知,它没有显示。然后我重新打开了应用程序(没有被 Visual Studio 调试)并通过将其从屏幕上滑下来关闭它,发送了一个通知并且它工作了。因此,它与 RECEIVE_BOOT_COMPLETE 权限无关,它不必是发布版本/签名的 APK。

【讨论】:

    猜你喜欢
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    • 2017-04-11
    • 2018-08-01
    • 2016-11-28
    相关资源
    最近更新 更多