Android локальные действия при закрытии приложения - PullRequest
0 голосов
/ 19 февраля 2020

Я использую Xamarin для создания приложения и Android и застрял с уведомлениями.

Чего я хочу добиться:

  1. Появляется уведомление каждый день с указанием c час
  2. Он имеет две кнопки «да» и «нет»
  3. Пользователь может щелкнуть их, и мое приложение что-то сделает с этими данными.

Проблема:

Появляется уведомление, я закрываю приложение (просто отмахиваюсь от экрана последних приложений) и затем нажимаю на кнопку уведомления - ничего не происходит. Если я нажму на тело уведомления - приложение откроется, но мне нужно, чтобы оно выполнило некоторые действия с помощью этих кнопок.

Вот некоторые из моих исходных файлов:

MainActivity.cs

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        AnswerReciever receiver;
        public static long reminderInterval = 30 * 1000; //every 30 seconds for test

        protected override void OnCreate(Bundle savedInstanceState)
        {
            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);
            receiver = new AnswerReciever();

            //trying to schedule notification for specific time of the day
            var alarmIntent = new Intent(this, typeof(AlarmReceiver));
            var pending = PendingIntent.GetBroadcast(this, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
            var alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>();
            alarmManager.SetInexactRepeating(AlarmType.RtcWakeup, FirstReminder(), reminderInterval, pending);
        }

        public static long FirstReminder()
        {
            var dt = DateTime.Now;
            //dt = dt.Date.AddHours(22).AddMinutes(00).AddSeconds(0);
            //TODO set from user settings

            var timestamp = (long)(dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;

            return timestamp;
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

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

        protected override void OnResume()
        {
            try
            {
                UnregisterReceiver(receiver);
            }
            catch (IllegalArgumentException) { }

            RegisterReceiver(receiver, new IntentFilter(Constants.ANDROID_NOTIFICATION_ACTION));

            base.OnResume();
        }

        protected override void OnDestroy()
        {
            UnregisterReceiver(receiver);
            base.OnDestroy();
        }

        protected override void OnPause()
        {
            base.OnPause();
        }

        void CreateNotificationFromIntent(Intent intent)
        {
            if (intent?.Extras != null)
            {
                string title = intent.Extras.GetString(AndroidNotificationManager.TitleKey);
                string message = intent.Extras.GetString(AndroidNotificationManager.MessageKey);
                DependencyService.Get<INotificationManager>().ReceiveNotification(title, message);
            }
        }
    }

AlarmReceiver.cs

[BroadcastReceiver]
    public class AlarmReceiver : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            DependencyService.Get<INotificationManager>().ScheduleNotification(Constants.NOTIFICATION_TITLE, Constants.NOTIFICATION_TEXT);
        }
    }

AnswerReciever.cs

[BroadcastReceiver(Enabled = true, Exported = true)]
    [IntentFilter(new[] { Constants.ANDROID_NOTIFICATION_ACTION })]
    public class AnswerReciever : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            var manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);
            var result = intent.GetBooleanExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ACTION, false);
            var date = intent.GetStringExtra(Constants.ANDROID_NOTIFICATION_EXTRA_DATE);
            var id = intent.GetIntExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ID, -1);
            manager.Cancel(id);

            //do something with data
        }
    }

AndroidNotificationManager.cs

public class AndroidNotificationManager : INotificationManager
    {
        const int mainActivityPendingIntentId = 0;
        const int firstActionPendingIntentId = 1;
        const int secondActionPendingIntentId = 2;

        bool channelInitialized = false;
        int messageId = -1;
        NotificationManager manager;

        public static string TitleKey => "Title";
        public static string MessageKey => "Message";

        public event EventHandler NotificationReceived;

        public void Initialize()
        {
            CreateNotificationChannel();
        }

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

            messageId++;

            var mainActivityIintent = new Intent(AndroidApp.Context, typeof(MainActivity));

            var mainActivityPendingIntent = PendingIntent.GetActivity(AndroidApp.Context, mainActivityPendingIntentId, mainActivityIintent, PendingIntentFlags.OneShot);

            var firstActionIntent = new Intent(Constants.ANDROID_NOTIFICATION_ACTION);
            firstActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ACTION, false);
            firstActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_DATE, DateTime.Now.Date.ToString("s"));
            firstActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ID, messageId);

            var pFirstActionIntent = PendingIntent.GetBroadcast(AndroidApp.Context, firstActionPendingIntentId, firstActionIntent, PendingIntentFlags.OneShot);

            var secondActionIntent = new Intent(Constants.ANDROID_NOTIFICATION_ACTION);
            secondActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ACTION, true);
            secondActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_DATE, DateTime.Now.Date.ToString("s"));
            secondActionIntent.PutExtra(Constants.ANDROID_NOTIFICATION_EXTRA_ID, messageId);

            var pSeconActionIntent = PendingIntent.GetBroadcast(AndroidApp.Context, secondActionPendingIntentId, secondActionIntent, PendingIntentFlags.OneShot);


            var builder = new NotificationCompat.Builder(AndroidApp.Context, Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_ID)
                .SetContentIntent(mainActivityPendingIntent)
                .SetContentTitle(title)
                .SetContentText(message)
                .AddAction(Resource.Drawable.navigation_empty_icon, Constants.ANDROID_NOTIFICATION_ANSWER_NO, pFirstActionIntent)
                .AddAction(Resource.Drawable.navigation_empty_icon, Constants.ANDROID_NOTIFICATION_ANSWER_YES, pSeconActionIntent)
                .SetAutoCancel(true)
                .SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.navigation_empty_icon))
                .SetSmallIcon(Resource.Drawable.navigation_empty_icon)
                .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);

            var notification = builder.Build();
            manager.Notify(messageId, notification);

            return messageId;
        }

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

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

            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                var channelNameJava = new Java.Lang.String(Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_NAME);

                var channel = new NotificationChannel(Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_ID, channelNameJava, NotificationImportance.Default)
                {
                    Description = Constants.ANDROID_NOTIFICATION_DEFAULT_CHANNEL_DESC
                };
                manager.CreateNotificationChannel(channel);
            }

            channelInitialized = true;
        }
    }

Я создал образец проекта для воспроизведения моя проблема, если это поможет: https://github.com/Immelstorn/NotificationsTest

...