[关闭应用程序时,Android本地通知操作

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

我正在使用Xamarin来创建和使用Android应用程序,但我一直停留在通知中。

我想实现的目标:

  1. 通知每天在特定时间出现
  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

c# android xamarin xamarin.forms xamarin.android
1个回答
0
投票
1。创建服务

MyService.cs:

[Service(Enabled = true)] public class MyService : Service { private Handler handler; private Action runnable; private bool isStarted; private int DELAY_BETWEEN_LOG_MESSAGES = 5000; private int NOTIFICATION_SERVICE_ID = 1001; private int NOTIFICATION_AlARM_ID = 1002; private string NOTIFICATION_CHANNEL_ID = "1003"; private string NOTIFICATION_CHANNEL_NAME = "MyChannel"; public override void OnCreate() { base.OnCreate(); handler = new Handler(); //here is what you want to do always, i just want to push a notification every 5 seconds here runnable = new Action(() => { if (isStarted) { DispatchNotificationThatAlarmIsGenerated("I'm running"); handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES); } }); } public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { if (isStarted) { // service is already started } else { CreateNotificationChannel(); DispatchNotificationThatServiceIsRunning(); handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES); isStarted = true; } return StartCommandResult.Sticky; } public override void OnTaskRemoved(Intent rootIntent) { //base.OnTaskRemoved(rootIntent); } public override IBinder OnBind(Intent intent) { // Return null because this is a pure started service. A hybrid service would return a binder that would // allow access to the GetFormattedStamp() method. return null; } public override void OnDestroy() { // Stop the handler. handler.RemoveCallbacks(runnable); // Remove the notification from the status bar. var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.Cancel(NOTIFICATION_SERVICE_ID); isStarted = false; base.OnDestroy(); } private void CreateNotificationChannel() { //Notification Channel NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.Max); notificationChannel.EnableLights(true); notificationChannel.EnableVibration(true); notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 }); NotificationManager notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService); notificationManager.CreateNotificationChannel(notificationChannel); } //start a foreground notification to keep alive private void DispatchNotificationThatServiceIsRunning() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .SetDefaults((int)NotificationDefaults.All) .SetSmallIcon(Resource.Drawable.Icon) .SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 }) .SetSound(null) .SetChannelId(NOTIFICATION_CHANNEL_ID) .SetPriority(NotificationCompat.PriorityDefault) .SetAutoCancel(false) .SetContentTitle("Mobile") .SetContentText("My service started") .SetOngoing(true); NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this); StartForeground(NOTIFICATION_SERVICE_ID, builder.Build()); } //every 5 seconds push a notificaition private void DispatchNotificationThatAlarmIsGenerated(string message) { var intent = new Intent(this, typeof(MainActivity)); intent.AddFlags(ActivityFlags.ClearTop); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot); Notification.Builder notificationBuilder = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID) .SetSmallIcon(Resource.Drawable.Icon) .SetContentTitle("Alarm") .SetContentText(message) .SetAutoCancel(true) .SetContentIntent(pendingIntent); var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.Notify(NOTIFICATION_AlARM_ID, notificationBuilder.Build()); } } 2。您的活动:

protected override void OnResume()
  {
      base.OnResume();
      StartMyRequestService();
  }
public void StartMyRequestService()
  {
      var serviceToStart = new Intent(this, typeof(MyService));
      StartService(serviceToStart);
  }
© www.soinside.com 2019 - 2024. All rights reserved.