【问题标题】:Local notification not triggering in Android 10本地通知未在 Android 10 中触发
【发布时间】:2020-07-15 07:07:05
【问题描述】:

我正在开发 xamarin.forms 应用程序,并且正在使用警报管理器设置本地通知。它在 android version 8 和 9 上触发良好,但不知何故在 Android 10 中没有触发。

Android 10 的 android 设备日志中,我得到了

07-22 15:00:06.612  Samsung SM-M205F    Verbose 4185    SamsungAlarmManager Sending to uid : 10244 action=null alarm=Alarm{a757a70 type 0 when 1595410200000 com.MyApp.andr.connect}

07-22 15:00:06.613  Samsung SM-M205F    Warning 4185    BroadcastQueue  Unable to launch app com.MyApp.andr.connect/10244 for broadcast Intent { flg=0x14 cmp=com.MyApp.andr.connect/crc640e87e93c5dbd1629.AlarmReceiver (has extras) }: process is bad

更新Android 10仍然存在问题)

我已经设法在应用程序运行时收到通知,但现在当应用程序关闭时通知不会触发。

注意:我制作了一个在 Android 10 上运行良好的示例,当应用在示例中运行或关闭时会触发通知。我不必使用前台服务。 (我在我的工作项目中使用了相同的方法)。所以我的工作项目有问题,我无法弄清楚。

这是当应用关闭且通知即将触发时的Android设备日志

如果有人可以帮忙!

【问题讨论】:

    标签: xamarin.forms xamarin.android broadcastreceiver alarmmanager localnotification


    【解决方案1】:

    当您的应用程序关闭时,包括警报管理器在内的所有代码都将被冻结。 如果您希望它还活着,我们可以使用前台服务: https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/foreground-services 这可能有点过时了,这是我创建通知的方法:

    [Service]
    public class SampleService : Service
    {
        public static string CHANNEL_ID = "com.channelid";
        public static string CHANNEL_NAME = "com.channelname";
        public override void OnCreate()
        {
            base.OnCreate();
    
               
        }
    
        public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
        {
            registerNotificationChannel();
            int notifyId = (int)JavaSystem.CurrentTimeMillis();
            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
            mBuilder.SetSmallIcon(Resource.Mipmap.ic_launcher);
            if (Build.VERSION.SdkInt < BuildVersionCodes.N)
            {
                mBuilder.SetContentTitle("app name");
            }
            StartForeground(notifyId, mBuilder.Build());
            return StartCommandResult.Sticky;
        }
    
        private void registerNotificationChannel()
        {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                NotificationManager mNotificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
                NotificationChannel notificationChannel = mNotificationManager.GetNotificationChannel(CHANNEL_ID);
                if (notificationChannel == null)
                {
                    NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                            CHANNEL_NAME, NotificationImportance.High);
                    channel.EnableLights(true);
                    channel.LightColor = Color.Red;
                    channel.LockscreenVisibility = NotificationVisibility.Public;
                    mNotificationManager.CreateNotificationChannel(channel);
                }
            }
        }
    
        public override IBinder OnBind(Intent intent)
        {
            throw new NotImplementedException();
        }
    }
    

    更新

    现在你不需要再使用alarmmanager了。

    在 MainActivity 中

     public static MainActivity Instance { get; set; }
    
     protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
          
            base.OnCreate(savedInstanceState);
    
            Instance = this;
    
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
        }
    

    AlarmAndNotificationService

    void IAlarmAndNotificationService.ScheduleLocalNotification(string notificationTitle, string notificationMessage, DateTime specificDateTime, TimeSpan timeSpan, int notificationId, NotificationInterval interval)
    {
       // start service here 
       Intent s = new Intent(MainActivity.Instance, typeof(SampleService));
    
       MainActivity.Instance.StartService(s);
    }
    

    在 SampleService 中

     public class SampleService : Service
    {
        private Handler handler;
        private Action runnable;
        private bool isStarted;
        private int DELAY_BETWEEN_LOG_MESSAGES = 5000;  // set time span 
        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());
        }
    }
    

    【讨论】:

    • 即使应用程序在前台运行,我也没有收到通知。
    • 您可以在另一台设备(或模拟器)上测试该应用程序。在某些特定设备上可能会出现一些未知问题。
    • 我已经设法在应用程序使用 BroadcastReceiver 运行时收到通知。但是当应用程序关闭时它不会触发。所以我认为上述解决方案可以提供帮助。如果我使用 ForegroundService 触发通知,是否需要 BroadcastReceiver 以及如何设置通知以在特定日期和时间触发?
    • 当然BroadcastReceiver 还是需要的。具体时间如何启动服务,可以查看stackoverflow.com/questions/39092274/…
    • 我做了一个使用alarmmanager触发本地通知的示例项目,它在应用程序运行和关闭时工作得很好。我什至不必在示例项目中使用前台服务。所以这可能是我工作项目的其他问题。当我解决我的工作项目中的问题时,我会在这里提供更新。
    猜你喜欢
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    相关资源
    最近更新 更多