在 Xamarin Forms Android 中处理通知 [英] Processing notifications in Xamarin Forms Android

查看:21
本文介绍了在 Xamarin Forms Android 中处理通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用图书馆 https://github.com/aritchie/notifications 并且我可以正确创建和安排通知.

I'm using the library https://github.com/aritchie/notifications and I can create and schedule notifications properly.

我希望在 Android 中处理它们,以便根据通知 - 当用户点击它时它会导航到特定页面.

I wish to process them in Android so that depending on the notification - it will navigate to a particular page when the user taps on it.

我发现当我点击通知时会触发以下事件(在我的 Android 项目中)

I've found that the below event is fired when I tap on a notification (in my Android Project)

 protected override void OnNewIntent(Intent intent)
    {

    }

但是,为了建立到特定页面的导航,我无法从通知中找到意图中的任何信息.

However, I can't find any info in the intent from my notification in order to build up navigation to a particular page.

如有任何建议,我们将不胜感激.

Any advice would be appreciated.

干杯!

编辑 #1(为相关问题添加额外代码):

Edit #1 (Adding additional code for a related issue):

如果我发出通知,并在收到通知之前关闭应用程序 - 我收到一条错误消息,指出应用程序已崩溃.如果我收到通知并关闭应用程序 - 我可以从通知中加载应用程序 OK.

If I fire off a notification, and close the app before the notification is received - I receive an error saying the app has crashed. If I receive the notification and close the app - I can load the app from the notification OK.

我有一个依赖服务,它命中以下方法.

I have a dependency service which hits the following methods.

public void Remind(DateTime dateTime, string msgtype, string usermedid)
    {
        DateTime now = DateTime.Now;
        var diffinseconds = (dateTime - now).TotalSeconds;
        Intent alarmIntent = new Intent(Forms.Context, typeof(AlarmBroadcastReceiver));
        alarmIntent.PutExtra("notificationtype", msgtype);
        alarmIntent.PutExtra("id", id);


        PendingIntent pendingIntent = PendingIntent.GetBroadcast(Forms.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
        AlarmManager alarmManager = (AlarmManager)Forms.Context.GetSystemService(Context.AlarmService);

        //TODO: For demo set after 5 seconds.
        alarmManager.Set(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime() + diffinseconds * 1000, pendingIntent);

    }

    [BroadcastReceiver(Enabled = true)]
    [IntentFilter(new string[]{"android.intent.action.BOOT_COMPLETED"}, Priority = (int) IntentFilterPriority.LowPriority)]
    public class AlarmBroadcastReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            string notificationtype = intent.GetStringExtra("notificationtype");

            PowerManager.WakeLock sWakeLock;
            var pm = PowerManager.FromContext(context);
            sWakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "GCM Broadcast Reciever Tag");
            sWakeLock.Acquire();

            intent = new Intent(Forms.Context, typeof(MainActivity));
            intent.PutExtra("notificationtype", notificationtype);
            intent.AddFlags(ActivityFlags.IncludeStoppedPackages);



            // Instantiate the builder and set notification elements, including pending intent:
            NotificationCompat.Builder builder = new NotificationCompat.Builder(Forms.Context)
                .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate)
                .SetAutoCancel(true)
                .SetContentIntent(PendingIntent.GetActivity(Forms.Context, 0, intent, 0)).SetContentTitle("Sample Notification")
                .SetContentText("Hello World! This is my first action notification!")
                .SetTicker("New Notification")

                .SetSmallIcon(Resource.Drawable.icon);


            // Build the notification:
            Android.App.Notification notification = builder.Build();

            notification.Flags = NotificationFlags.AutoCancel;

            // Get the notification manager:
            //NotificationManager notificationManager = Forms.Context.GetSystemService(Context.NotificationService) as NotificationManager;
            var manager = NotificationManagerCompat.From(context);

            // Publish the notification:
            const int notificationId = 0;
            manager.Notify(notificationId, notification);

            sWakeLock.Release();



        }
    }

如何在应用程序关闭时让我的广播接收器保持活动状态?

How do I keep my Broadcast Receiver alive when the app is closed?

推荐答案

好的,所以我花了一些时间来解决这个问题.OnNewIntent 在应用程序处于后台并点击通知时调用.每次最小化应用程序并重新启动时也会调用它...因此要区分这两个事件之间的区别,您需要检查传入的 Intent 以了解其中包含哪些额外数据.额外的数据将来自您第一次启动通知时所做的 Intent.

Ok so it took me some time to figure this one out. OnNewIntent is called when the app is in the background and the notification is clicked on. It is also called each time the app is minimized and the brought back up... so to tell the difference between the 2 events, you need to check the passed in Intent for what extra data is inside it. The extra data would have come from the Intent you made when you first initiated the notification.

还要确保将您的 MainActivityLaunchMode 设置为 LaunchMode.SingleTop 以便您的应用不会在每次收到通知时重新启动被点击.

Also make sure to set your MainActivity's LaunchMode to LaunchMode.SingleTop so that your app does not get restarted each time the notification is clicked on.

[Activity(LaunchMode = LaunchMode.SingleTop, ....)]
public class MainActivity : FormsApplicationActivity {

    ....

    /// <summary>
    /// Called when the app is in the background and a notification is clicked on (also called each time the app is minimized and the brought back up), a new <c>Intent</c> is created
    ///     and sent out, since we use <c>LaunchMode</c> set to <c>SingleTop</c> this method is called instead of the app being restarted.
    /// </summary>
    /// <param name="intent">The <c>Intent</c> that was set when the call was made. If started from a notification click, extra <c>string</c> values can be extracted.</param>
    protected override void OnNewIntent(Intent intent) {

        if(intent.HasExtra("Some special key you made up")) { //Here is where you check for special notification intent extras
            //Do something brilliant now that you know a notification was clicked on
        }
        base.OnNewIntent(intent);
    }

要了解如何将数据添加到 Intent,您可以查看 Xamarin Sport 应用程序,但不要像我一直倾向于做的那样陷入他们正在做的所有其他事情中.只需关注 PutExtra 部分.

To see how you can add data to the Intent you can check out the Xamarin Sport App, but do not get too bogged down in all the other stuff they are doing like I always tend to do. Just focus on the PutExtra part.

编辑 #1:

如果您的应用程序完全关闭,您需要从传递给 OnCreateIntent 中提取数据并将其传递给您的 App 类或者用它做其他事情:

If your app is completely closed, you need to pull the data from the Intent passed into OnCreate and pass it into your App class or do something else with it:

protected override async void OnCreate(Android.OS.Bundle bundle) {

    base.OnCreate(bundle);

    Forms.Init(this, bundle);

    string parameterValue = Intent.GetStringExtra("Some special key you made up"); //This would come in from the Push Notification being clicked on

    Console.WriteLine("
In MainActivity.OnCreate() - Param Intent Extras: {0}
", parameterValue);

    //MessagingCenter.Send("nothing", ConstantKeys.NewNotification); //Do something special with the notification data

    LoadApplication(parameterValue != null ? new App(parameterValue) : new App()); //Do something special with the notification data
}

编辑#2:

根据我当前的代码,我建议您对 OnReceive 方法进行一些更改(有些可能不是必需的,但这正是我正在做的):

Some changes I would recommend to your OnReceive method based on my current code (some may not be necessary, but it is just what I am doing):

  • 标记您的广播接收器
  • 添加愚蠢的 Xamarin 构造函数
  • 为 IntentFilter 使用常量属性而不是字符串
  • 删除 IntentFilter 优先级
  • 检查空意图(可能没有必要)
  • 使用 Application.Context 而不是 Forms.Context(我在应用程序的其他部分使用 Forms.Context,所以不确定这个,但是伤不起)
  • 不要覆盖传入的 Intent
  • 创建启动意图而不是常规
  • 在提取额外内容之前添加 IncludeStoppedPackages 标志
  • 检查启动完成事件
  • 使用 Notification.Builder 而不是 NotificationCompat.Builder(尽管您可能需要将其改回)
  • 将以下标志添加到pendingintent:PendingIntentFlags.UpdateCurrent |PendingIntentFlags.OneShot-- 使用 NotificationManager(除非您有特定的原因将其注释掉)

[assembly: UsesPermission(Android.Manifest.Permission.Vibrate)]  
[assembly: UsesPermission(Android.Manifest.Permission.WakeLock)]                //Optional, keeps the processor from sleeping when a message is received
[assembly: UsesPermission(Android.Manifest.Permission.ReceiveBootCompleted)]                        //Allows our app to be opened and to process notifications even when the app is closed

namespace Your.App.Namespace {

[BroadcastReceiver(Enabled = true, Label = "GCM Alarm Notifications Broadcast Receiver")]
[IntentFilter(new []{ Intent.ActionBootCompleted })]
public class AlarmBroadcastReceiver : BroadcastReceiver {
    #region Constructors

    // ReSharper disable UnusedMember.Global
    public AlarmBroadcastReceiver() { }

    public AlarmBroadcastReceiver(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer) { }
    // ReSharper restore UnusedMember.Global

    #endregion

    public void Remind(DateTime dateTime, string msgtype, string usermedid) {
        DateTime now = DateTime.Now;
        var diffinseconds = (dateTime - now).TotalSeconds;

        Intent alarmIntent = new Intent(Application.Context, typeof(AlarmBroadcastReceiver));
        alarmIntent.PutExtra("notificationtype", msgtype);
        alarmIntent.PutExtra("id", id);

        PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
        AlarmManager alarmManager = (AlarmManager)Application.Context.GetSystemService(Context.AlarmService);

        //TODO: For demo set after 5 seconds.
        alarmManager.Set(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime() + diffinseconds * 1000, pendingIntent);
    }

    public override void OnReceive(Context context, Intent intent) {
        #region Null Check

        if(intent == null) {
            Console.WriteLine("
In AlarmBroadcastReceiver.OnReceive() - Intent is null
");
            return;
        }

        #endregion

        intent.AddFlags(ActivityFlags.IncludeStoppedPackages);

        string action = intent.Action;
        Console.WriteLine("
In AlarmBroadcastReceiver.OnReceive() - Action: {0}
", action);

        #region Boot Completed Check

        if(action.Equals("android.intent.action.BOOT_COMPLETED")) {

            PowerManager pm = PowerManager.FromContext(context);
            PowerManager.WakeLock sWakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "GCM Broadcast Receiver Tag");
            sWakeLock.Acquire();

            Console.WriteLine("
In AlarmBroadcastReceiver.OnReceive() - Process Shared Preferences Notifications
");

            #region Process Saved Scheduled Notifications

            //Get list of saved scheduled notifications that did not fire off before the device was turned off (I store them in SharedPreferences and delete them after they are fired off)

            //Go through the list and reschedule them

            #endregion

            sWakeLock.Release();
            return;
        }

        #endregion

        string notificationtype = intent.GetStringExtra("notificationtype");

        Intent startupIntent = Application.Context.PackageManager.GetLaunchIntentForPackage(Application.Context.PackageName);
        startupIntent.PutExtra("notificationtype", notificationtype);

        // Instantiate the builder and set notification elements, including pending intent:
        Notification.Builder builder = new Notification.Builder(Application.Context)
            .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate)
            .SetAutoCancel(true)
            .SetContentIntent(PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.OneShot))
            .SetContentTitle("Sample Notification")
            .SetContentText("Hello World! This is my first action notification!")
            .SetTicker("New Notification")
            .SetSmallIcon(Resource.Drawable.icon);

        // Build the notification:
        Android.App.Notification notification = builder.Build();

        // Get the notification manager:
        NotificationManager notificationManager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;

        // Publish the notification:
        int notificationId = ??;//This should be a real unique number, otherwise it can cause problems if there are ever multiple scheduled notifications
        notificationManager.Notify(notificationId, notification);
    }
}
}

这篇关于在 Xamarin Forms Android 中处理通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆