Xamarin.Forms菜鸟笔记--7.本地通知及点击跳转(安卓+ios)

官网给了本地通知的demo,但是没有点击事件,网上可以搜到安卓的点击跳转
但是没有ios的,我在官方给的demo基础上做了一些修改,实现了XF点击通知跳转
先上代码,再说原理
首先把官网的代码都用上

  1. pcl中
    NotificationEventArgs.cs加了条属性ApplicationID ,用来指定跳转页面的参数
    public class NotificationEventArgs : EventArgs
    {
        public string Title { get; set; }

        public string Message { get; set; }

        public string ApplicationID { get; set; }
    }

INotificationManager.cs因为NotificationEventArgs.cs加了属性,所以这里调用的时候也要添加参数

    public interface INotificationManager
    {
        event EventHandler NotificationReceived;

        void Initialize();

        int ScheduleNotification(string title, string message,string appid);

        void ReceiveNotification(string title, string message, string appid);

    }

重点:App类,新增一个构造函数用来跳转

        public App(Page p)
        {
            InitializeComponent();
            DependencyService.Get<INotificationManager>().Initialize();
            MainPage = p;
        }

生成通知的方法,我重新包了个类,不过代码大抵相同

    public class NotificationService
    {
       
        /// <summary>
        /// 弹出通知
        /// </summary>
        /// <param name="title"></param>
        /// <param name="message"></param>
        public static void Alert(string title, string message)
        {
            try
            {
                INotificationManager notificationManager = DependencyService.Get<INotificationManager>();
                notificationManager.NotificationReceived += (sender, eventArgs) =>
                {
                    var evtData = (NotificationEventArgs)eventArgs;
                    ShowNotification(evtData);
                };
                notificationManager.ScheduleNotification(title, message,"12345821"); // 参数12345821根据自己需求来
            }
            catch (Exception)
            {

            }
        }

        private static void ShowNotification(NotificationEventArgs ne)
        {
            //Device.BeginInvokeOnMainThread(() =>
            //{
            //    var msg = new Label()
            //    {
            //        Text = $"Notification Received:\nTitle: {ne.Title}\nMessage: {ne.Message}"
            //    };
            //});
        }

    }
  1. 安卓中
    AndroidNotificationManager.cs
[assembly: Dependency(typeof(命名空间.AndroidNotificationManager))]
namespace 命名空间
{
    public class AndroidNotificationManager : INotificationManager
    {
        #region 变量

        const string channelId = "default";
        const string channelName = "Default";
        const string channelDescription = "The default channel for notifications.";
        const int pendingIntentId = 0;
        public const string TitleKey = "title";
        public const string MessageKey = "通知事件的MessageKey";
        bool channelInitialized = false;
        int messageId = -1;
        NotificationManager manager;

        #endregion

        #region 接口

        public event EventHandler NotificationReceived;

        public void Initialize()
        {
            CreateNotificationChannel();
        }

        public int ScheduleNotification(string title, string message, string appid)
        {
            if (!channelInitialized)
            {
                CreateNotificationChannel();
            }

            messageId++;

            Intent intent = new Intent(AndroidApp.Context, typeof(MainActivity));
            intent.PutExtra(TitleKey, title);
            intent.PutExtra(MessageKey, message); // 在MainActivity会检查此MessageKey是否存在
            intent.SetAction("通知事件");
            PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId, intent, PendingIntentFlags.OneShot);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
                .SetContentIntent(pendingIntent)
                .SetContentTitle(title)
                .SetContentText(message)
                .SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.approve_selected))
                .SetSmallIcon(Resource.Drawable.approve_selected)
                .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);

            Notification notification = builder.Build();
            manager.Notify(messageId, notification);
            notification.Dispose();
            return messageId;
        }

        public void ReceiveNotification(string title, string message, string appid)
        {
            var args = new NotificationEventArgs()
            {
                Title = title,
                Message = message,
                ApplicationID = appid,
            };
            NotificationReceived?.Invoke(null, args);
        }

        #endregion

        #region 其他

        void CreateNotificationChannel()
        {
            manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);

            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                var channelNameJava = new Java.Lang.String(channelName);
                var channel = new NotificationChannel(channelId, channelNameJava, NotificationImportance.Default)
                {
                    Description = channelDescription
                };
                manager.CreateNotificationChannel(channel);
            }
            channelInitialized = true;
            // manager.Wait
        }

        #endregion

    }
}

MainActivity中
LaunchMode = LaunchMode.SingleTop这个一定加上

[Activity(Label = "name", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            MyInit();
            CrossCurrentActivity.Current.Init(this, savedInstanceState);
            MobileBarcodeScanner.Initialize(Application);
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
            CreateNotificationFromIntent(Intent);
        }

        private void MyInit()
        {
            UserDialogs.Init(this);
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            var c = PermissionsImplementation.Current;
            c.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

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

        /// <summary>
        /// 通知点击事件
        /// </summary>
        /// <param name="intent"></param>
        void CreateNotificationFromIntent(Intent intent)
        {
            if (intent.Action == "通知事件" && intent.HasExtra("通知事件的MessageKey"))
            {
                LoadApplication(new App(new Views.MyPage()));
                string title = intent.Extras.GetString(AndroidNotificationManager.TitleKey);
                string message = intent.Extras.GetString(AndroidNotificationManager.MessageKey);
                DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
            }
        }

    }

跳转的关键就是在CreateNotificationFromIntent(Intent intent)中加一个LoadApplication(new App(new Views.MyPage()));
3. ios中
iOSNotificationManager.cs

[assembly: Dependency(typeof(命名空间.iOSNotificationManager))]
namespace 命名空间
{
    public class iOSNotificationManager : INotificationManager
    {
        int messageId = -1;

        bool hasNotificationsPermission;

        public event EventHandler NotificationReceived;

        public void Initialize()
        {
            // request the permission to use local notifications
            UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
            {
                hasNotificationsPermission = approved;
            });
        }

        public int ScheduleNotification(string title, string message, string appid)
        {
            // EARLY OUT: app doesn't have permissions
            if (!hasNotificationsPermission)
            {
                return -1;
            }

            messageId++;

            var content = new UNMutableNotificationContent()
            {
                Title = title,
                Subtitle = appid,
                Body = message,
                Badge = 1
            };

            // Local notifications can be time or location based
            // Create a time-based trigger, interval is in seconds and must be greater than 0
            var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.25, false);

            var request = UNNotificationRequest.FromIdentifier(messageId.ToString(), content, trigger);
            UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
            {
                if (err != null)
                {
                    throw new Exception($"通知失败: {err}");
                }
            });

            return messageId;
        }

        public void ReceiveNotification(string title, string message, string appid)
        {
            var args = new NotificationEventArgs()
            {
                Title = title,
                Message = message,
                ApplicationID = appid
            };
            NotificationReceived?.Invoke(null, args);
        }
    }
}

iOSNotificationReceiver.cs

    public class iOSNotificationReceiver : UNUserNotificationCenterDelegate
    {
        AppDelegate _app;
        string id = "";

        public iOSNotificationReceiver(AppDelegate a)
        {
            _app = a;
        }

        public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
        {
            DependencyService.Get<INotificationManager>().ReceiveNotification(notification.Request.Content.Title, notification.Request.Content.Body, notification.Request.Content.Subtitle);
            id = notification.Request.Content.Subtitle;
            // alerts are always shown for demonstration but this can be set to "None"
            // to avoid showing alerts if the app is in the foreground
            completionHandler(UNNotificationPresentationOptions.Alert);
        }

        public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
        {
            _app.LoadApp(id);
            // base.DidReceiveNotificationResponse(center, response, completionHandler);
        }
    }

AppDelegate.cs

    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            UNUserNotificationCenter.Current.Delegate = new iOSNotificationReceiver(this);
            LoadApplication(new App());
            return base.FinishedLaunching(app, options);
        }

        public void LoadApp(string appid)
        {
            Xamarin.Forms.Application.Current.MainPage.Navigation.PushAsync(new Page(), false);
        }

    }

原理:Xamarin.form官方是没有集成通知功能的,而且安卓和ios的实现也不一样,估计因为ios的权限管理太严格,搞通知的话需要手动配置的地方太多。所以官方推荐上也是在pcl上写接口,然后native实现。
native实现:安卓有自己的通知方式,直接按照官方demo实现本地通知接口即可,主要问题是点击通知跳转。这次实现点击功能发现了xamarin.form和native的一个区别,native的跳转是通过Activity实现的,不同的页面对应不同的Activity,而xf只有一个Activity,就是MainActivity,虽然有的例子在跳转这新写了一个。
我的方法在ios的实现原理和安卓一样,都是重新加载一下整个app,然后在加载时跳转到想进的页,不过ios注意一下权限问题,我还根据官方demo改了下Info.plist,不知道不改会不会出错,反正我改了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值