【问题标题】:AlarmManager and Notifications in Android 8.0(Oreo)Android 8.0(Oreo) 中的 AlarmManager 和 Notifications
【发布时间】:2018-05-24 20:36:16
【问题描述】:

在我的应用程序中,我有一个每周四重复的警报,我正在使用 AlarmManger,在所有以前的 android 版本中一切正常,但现在使用 android 8.0(oreo),警报没有触发,下面是我用来设置闹钟的课程。 根据我的搜索,我需要明确设置警报,但我 不明白怎么做。

主活动:

try
        {
            Intent alarmIntent = new Intent(this, typeof(AlarmReceiver));
            PendingIntent pending = PendingIntent.GetBroadcast(this, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
            AlarmManager alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>();

            if (Settings.AccessAlarm == 0)
            {
                alarmManager.SetRepeating(AlarmType.RtcWakeup, BootReceiver.FirstReminder(), BootReceiver.reminderInterval, pending);
                PendingIntent pendingIntent = PendingIntent.GetBroadcast(this, 0, alarmIntent, 0);
                Settings.AccessAlarm = 1;
            }
        }
        catch (Exception e)
        {
            Settings.AccessAlarm = 0;
        }

Bootreceiver.cs:

[BroadcastReceiver]
[IntentFilter(new[] { Intent.ActionBootCompleted })]
public class BootReceiver : BroadcastReceiver
{
    //the interval currently every one minute
    //to set it to dayly change the value to 24 * 60 * 60 * 1000
    public static long reminderInterval = AlarmManager.IntervalDay * 7;
    //public static long reminderInterval = 3 * 1000;

    public static long FirstReminder()
    {
        System.Random rnd = new System.Random();

        int minutenumber = rnd.Next(20, 40);

        Java.Util.Calendar calendar = Java.Util.Calendar.Instance;
        calendar.Set(Java.Util.CalendarField.DayOfWeek, Calendar.Thursday);
        calendar.Set(Java.Util.CalendarField.HourOfDay, 10);
        calendar.Set(Java.Util.CalendarField.Minute, minutenumber);
        return calendar.TimeInMillis;

    }

    public override void OnReceive(Context context, Intent intent)
    {
        try
        {
            Console.WriteLine("BootReceiver: OnReceive");
            var alarmIntent = new Intent(context, typeof(AlarmReceiver));
            var pending = PendingIntent.GetBroadcast(context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
            AlarmManager alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService);
            alarmManager.SetRepeating(AlarmType.RtcWakeup, FirstReminder(), reminderInterval, pending);

            PendingIntent pendingIntent = PendingIntent.GetBroadcast(context, 0, alarmIntent, 0);
            Settings.AccessAlarm = 1;
        }
        catch (Exception e)
        {
            Settings.AccessAlarm = 0;
        }

    }
}

报警接收器:

[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
    private int z = 0;
    private int i;


    public override void OnReceive(Context context, Intent intent)
    {
        try
        {
                Settings.AlarmNotification = 1;

                if (System.DateTime.Now.DayOfWeek == DayOfWeek.Thursday)
                {
                    Settings.AlarmCount =0;
                }

                var title = "Test";
                var message = "Something";

                Intent backIntent = new Intent(context, typeof(MainActivity));
                backIntent.SetFlags(ActivityFlags.NewTask);



                var resultIntent = new Intent(context, typeof(MainActivity));



                PendingIntent pending = PendingIntent.GetActivities(context, 0,
                    new Intent[] { backIntent, resultIntent },
                    PendingIntentFlags.OneShot);

                var builder =
                    new Notification.Builder(context)
                        .SetContentTitle(title)
                        .SetContentText(message)
                        .SetAutoCancel(true)
                        .SetSmallIcon(Resource.Drawable.icon)
                        .SetDefaults(NotificationDefaults.All);

                builder.SetContentIntent(pending);
                var notification = builder.Build();
                var manager = NotificationManager.FromContext(context);
                manager.Notify(1331, notification);

        }
        catch (Exception)
        {

        }
    }
}

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.android alarmmanager android-8.0-oreo


    【解决方案1】:

    当您使用明确的意图时,您的警报会正确触发。但在 Oreo/API26 .SetDefaults(NotificationDefaults.All 已过时,会导致静默失败,并且不会显示您的通知。

    因此,您需要设置一个通知渠道,以正确显示您的通知以及所有的花里胡哨。

    如果您替换通知生成器和通知代码:

    var builder =
        new Notification.Builder(context)
            .SetContentTitle(title)
    ~~~~
    manager.Notify(1331, notification);
    

    通过对 Oreo/API26(+) 的 API 检查,您可以为您的应用建立通知通道:

    using (var notificationManager = NotificationManager.FromContext(context))
    {
        Notification notification;
        if (Android.OS.Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.O)
        {
            notification = new Notification.Builder(context)
                                        .SetContentTitle(title)
                                        .SetContentText(message)
                                        .SetAutoCancel(true)
                                        .SetSmallIcon(Resource.Drawable.icon)
                                        .SetDefaults(NotificationDefaults.All)
                                        .SetContentIntent(pending)
                                        .Build();
        }
        else
        {
            // Setup a NotificationChannel, Go crazy and make it public, urgent with lights, vibrations & sound.
            var myUrgentChannel = context.PackageName;
            const string channelName = "SushiHangover Urgent";
    
            NotificationChannel channel;
            channel = notificationManager.GetNotificationChannel(myUrgentChannel);
            if (channel == null)
            {
                channel = new NotificationChannel(myUrgentChannel, channelName, NotificationImportance.High);
                channel.EnableVibration(true);
                channel.EnableLights(true);
                channel.SetSound(
                    RingtoneManager.GetDefaultUri(RingtoneType.Notification),
                    new AudioAttributes.Builder().SetUsage(AudioUsageKind.Notification).Build()
                );
                channel.LockscreenVisibility = NotificationVisibility.Public;
                notificationManager.CreateNotificationChannel(channel);
            }
            channel?.Dispose();
    
            notification = new Notification.Builder(context)
                                        .SetChannelId(myUrgentChannel)
                                        .SetContentTitle(title)
                                        .SetContentText(message)
                                        .SetAutoCancel(true)
                                        .SetSmallIcon(Resource.Drawable.icon)
                                        .SetContentIntent(pending)
                                        .Build();
        }
        notificationManager.Notify(1331, notification);
        notification.Dispose();
    }
    

    现在在设置中,您的应用分配了一个频道,用户可以选择自定义频道:

    【讨论】:

    • 您好,非常感谢您的帮助,现在正在工作,但是通知上的图标没有显示,在android 8.0中正常吗?另一件事,可以知道用户是否点击了通知?
    • @Phill 该图标 (SetSmallIcon) 应该显示在我的奥利奥上。您正在设置通知的Intent (backIntent) 并启动MainActivity 的新实例(通过NewTask),不确定这是否是您想要的。接受此答案,因为它有效,并在需要时发布有关用户单击通知的另一个问题。
    • 我会这样做的,你在drawable文件夹中的图标大小是多少,我的是48x48。
    • @Phill 我使用ldpixxxhdpi 的所有尺寸,48x48 将是xhdpi,所以应该可以正常工作并且可以放大和缩小...我也使用大图标:developer.android.com/reference/android/app/…
    • 我的代码与您几乎相同,但从 Android 8+ 开始,当设备重新启动并将 BOOT_COMPLETED 发送到应用程序时,应用程序崩溃并显示以下内容(我删除了一些文本以缩短事情):RuntimeException: Unable to start receiver PushHandlerBroadcastReceiver: IllegalStateException: Not allowed to start service Intent { act=android.intent.action.BOOT_COMPLETED cmp=....GcmService (has extras) }: app is in background uid ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 2019-10-01
    • 2018-03-09
    • 2018-02-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多