本地通知未在 Android 10 中触发

Posted

技术标签:

【中文标题】本地通知未在 Android 10 中触发【英文标题】:Local notification not triggering in 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=Alarma757a70 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设备日志

如果有人可以帮忙!

【问题讨论】:

【参考方案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 还是需要的。具体时间如何启动服务,可以查看***.com/questions/39092274/… 我做了一个使用alarmmanager触发本地通知的示例项目,它在应用程序运行和关闭时工作得很好。我什至不必在示例项目中使用前台服务。所以这可能是我工作项目的其他问题。当我解决我的工作项目中的问题时,我会在这里提供更新。

以上是关于本地通知未在 Android 10 中触发的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的本地通知没有在 iOS 10 的前台触发?

iOS 10:如何在特定日期触发后重复本地通知?

如何在swift 3中每天在特定时间触发本地通知

声音文件未在本地通知 iOS7 上播放

当 iOS 10 应用程序在后台时,有啥方法可以触发本地通知?

UNUserNotificationCenter Swift - 在特定情况下未触发本地通知