Xamarin Android应用停止后如何接收推送通知?

问题描述 投票:2回答:1

我已经看到许多过去可能有用的不同类型的解决方案,但是没有什么对我自己有用。这是人们所说的行之有效,什么行不通,什么已更改等的雷区。但是,我不仅试图找到解决方案,而且希望找到一种谅解-因为现在我很困惑。


[我现在可以做什么-如果该Xamarin Forms应用程序位于前景/背景中,则我的Xamarin Forms应用程序(Android)可以接收推送通知,当用户点击它们时,我也可以拦截这些通知,以便我可以告诉我app该怎么做。

我想做的事情-本质上是上面的,但是处于应用程序已完全停止的状态。


我有连接到Azure Notification Hub的Firebase Messaging设置-不幸的是,我不会离开Azure(以防万一有人建议放弃它)。我目前拥有的大部分信息是我已设法从各种Microsoft文档中整理而成的信息(here我不使用AppCenter-只是用来交叉引用任何有用的代码,hereherehere),其他StackOverflow问题(例如hereherehere-链接太多)和Xamarin论坛-因此,如果有任何过时的代码正在使用,请您道歉(请让我知道-我已尽力使用最新方法,等等。

我正在发送的推送通知的类型是数据消息 which I read up on here,我在通知中使用自定义数据,因此,我理解这是我要发送的正确推送类型,如下所示下面。

{
    "data": {
        "title": "Title Test",
        "body": "Push notification body test",
        "area": "SelectedPage"
    }
}

下面是我目前在我的项目中设置的当前代码,用于处理推送通知。

清单

<?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.companyname.pushtesting" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
    <application android:label="Push Testing">

        <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" />
</manifest>

MainActivity.cs

我有LaunchMode = LaunchMode.SingleTop,我的理解是正确的,因为这是为了确保仍然使用当前的Activity,而不是创建一个新的Activity(例如,当用户点击通知时,它会执行并加上其他代码(如下) )似乎暗示这是真的。

protected override void OnNewIntent(Intent intent) {
    base.OnNewIntent(intent);

    String area = String.Empty;
    String extraInfo = String.Empty;

    if (intent.Extras != null) {
        foreach (String key in intent.Extras.KeySet()) {
            String value = intent.Extras.GetString(key);
            if (key == "Area" && !String.IsNullOrEmpty(value)) {
                area = value;
            } else if (key == "ExtraInfo" && !String.IsNullOrEmpty(value)) {
                extraInfo = value;
            }
        }
    }
    NavigationExtension.HandlePushNotificationNavigation(area, extraInfo);
}

当用户与其交互时,使用OnNewIntent拦截推送通知。

MyFirebaseMessaging.cs

using System;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Support.V4.App;
using Android.Util;
using Firebase.Messaging;
using PushTesting.Models;
using WindowsAzure.Messaging;

namespace PushTesting.Droid.Services {

    [Service]
    [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
    public class OcsFirebaseMessaging : FirebaseMessagingService {

        private const String NotificationChannelId = "1152";
        private const String NotificationChannelName = "Push Notifications";
        private const String NotificationChannelDescription = "Receive notifications";
        private NotificationManager notificationManager;

        public override void OnNewToken(String token) => SendTokenToAzure(token);

        /// <summary>
        /// Sends the token to Azure for registration against the device
        /// </summary>
        private void SendTokenToAzure(String token) {
            try {
                NotificationHub hub = new NotificationHub(Constants.AzureConstants.NotificationHub, Constants.AzureConstants.ListenConnectionString, Android.App.Application.Context);

                Task.Run(() => hub.Register(token, new String[] { }));
            } catch (Exception ex) {
                Log.Error("ERROR", $"Error registering device: {ex.Message}");
            }
        }

        /// <summary>
        /// When the app receives a notification, this method is called
        /// </summary>
        public override void OnMessageReceived(RemoteMessage remoteMessage) {
            Boolean hasTitle = remoteMessage.Data.TryGetValue("title", out String title);
            Boolean hasBody = remoteMessage.Data.TryGetValue("body", out String body);
            Boolean hasArea = remoteMessage.Data.TryGetValue("area", out String area);
            Boolean hasExtraInfo = remoteMessage.Data.TryGetValue("extraInfo", out String extraInfo);

            PushNotificationModel push = new PushNotificationModel {
                Title = hasTitle ? title : String.Empty,
                Body = hasBody ? body : String.Empty,
                Area = hasArea ? area : String.Empty,
                ExtraInfo = hasExtraInfo ? extraInfo : String.Empty
            };

            SendNotification(push);
        }

        /// <summary>
        /// Handles the notification to ensure the Notification manager is updated to alert the user
        /// </summary>
        private void SendNotification(PushNotificationModel push) {
            // Create relevant non-repeatable Id to allow multiple notifications to be displayed in the Notification Manager
            Int32 notificationId = Int32.Parse(DateTime.Now.ToString("MMddHHmmsss"));

            Intent intent = new Intent(this, typeof(MainActivity));
            intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
            intent.PutExtra("Area", push.Area);
            intent.PutExtra("ExtraInfo", push.ExtraInfo);

            PendingIntent pendingIntent = PendingIntent.GetActivity(this, notificationId, intent, PendingIntentFlags.UpdateCurrent);
            notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);

            // Creates Notification Channel for Android devices running Oreo (8.0.0) or later
            if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O) {
                NotificationChannel notificationChannel = new NotificationChannel(NotificationChannelId, NotificationChannelName, NotificationImportance.High) {
                    Description = NotificationChannelDescription
                };

                notificationManager.CreateNotificationChannel(notificationChannel);
            }

            // Builds notification for Notification Manager
            Notification notification = new NotificationCompat.Builder(this, NotificationChannelId)
            .SetSmallIcon(Resource.Drawable.ic_launcher)
            .SetContentTitle(push.Title)
            .SetContentText(push.Body)
            .SetContentIntent(pendingIntent)
            .SetAutoCancel(true)
            .SetShowWhen(false)
            .Build();

            notificationManager.Notify(notificationId, notification);
        }
    }
}

然后最后是我使用OnNewToken()注册到Azure的Firebase类,OnMessageReceived()被覆盖,因此我可以处理收到的推送通知,然后处理用来构建和显示通知的SendNotification()。] >

任何帮助,我们将不胜感激!

Added Sample Project to GitHub

我已经看到了过去可能有用的许多不同类型的解决方案,但是没有什么对我自己有用。这是人们所说的行之有效的雷区,什么不行的有雷区,...

c# android firebase xamarin.forms firebase-cloud-messaging
1个回答
0
投票

对我来说有很多问题(更多详细信息here:]]

  • 不熟悉Android应用程序架构以及与FirebaseMessagingService生命周期的关系如何:这里有应用程序,服务和接收器。当关闭“应用程序”(从用户角度来看)时,通过从最近记录中刷卡,服务/接收者可以对“意图”(传入的通知消息)做出反应。当应用程序“强制停止”时,不会运行任何ui,服务或接收器。
© www.soinside.com 2019 - 2024. All rights reserved.