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

查看:119
本文介绍了在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.

任何建议将不胜感激.

干杯!

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

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

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

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中添加数据,可以检出

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("\nIn MainActivity.OnCreate() - Param Intent Extras: {0}\n", 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(除非您有特定原因将其注释掉)
  • Label your Broadcast Receiver
  • Add stupid Xamarin constructors
  • Used constant property instead of string for IntentFilter
  • Remove IntentFilter Priority
  • Check for null Intent (might not be necessary)
  • Use Application.Context instead of Forms.Context (I use Forms.Context in other parts of my app so not sure about this one, but can't hurt)
  • Do not overwrite the passed in Intent
  • Create startup intent instead of regular
  • Add IncludeStoppedPackages flag before pulling out extras
  • Check for boot completed event
  • Use Notification.Builder instead of NotificationCompat.Builder (though you might need to change this back)
  • Add following flags to pendingintent: PendingIntentFlags.UpdateCurrent | PendingIntentFlags.OneShot -- Use NotificationManager (unless you have a specific reason you commented it out)

[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("\nIn AlarmBroadcastReceiver.OnReceive() - Intent is null\n");
            return;
        }

        #endregion

        intent.AddFlags(ActivityFlags.IncludeStoppedPackages);

        string action = intent.Action;
        Console.WriteLine("\nIn AlarmBroadcastReceiver.OnReceive() - Action: {0}\n", 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("\nIn AlarmBroadcastReceiver.OnReceive() - Process Shared Preferences Notifications\n");

            #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天全站免登陆