如何在Android Oreo中的特定时间在android上发出通知?

时间:2018-07-14 21:33:27

标签: android notifications sharedpreferences settings alarmmanager

我正在寻找一种在preference中创建Settings的方法,以便在一天中的特定时间(由用户在设置中设置)在Android应用中发送通知。我看过像this这样的不同线程,但这在Android Oreo中不起作用。

有人可以帮我解决这个问题或为我提供教程吗?

2 个答案:

答案 0 :(得分:6)

在查看了不同的帖子以及对AlarmManager的实现进行了一些研究之后,这才对我有用。

此操作的基础是this发布和安排Android Documentation重复警报。

这是我当前的实现方式:

我有一个SwitchPreference,一个TimePicker实现是Settings

SwitchPreference,询问用户是否要启用“重复每日通知”。

TimePicker设置通知时间。

MainActivity的{​​{1}}方法中或您在阅读OnCreate的任何地方,请执行以下操作:

SharedPreferences

接下来添加实现PreferenceManager.setDefaultValues(this, R.xml.preferences, false); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); Boolean dailyNotify = sharedPref.getBoolean(SettingsActivity.KEY_PREF_DAILY_NOTIFICATION, true); PackageManager pm = this.getPackageManager(); ComponentName receiver = new ComponentName(this, DeviceBootReceiver.class); Intent alarmIntent = new Intent(this, AlarmReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0); AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // if user enabled daily notifications if (dailyNotify) { //region Enable Daily Notifications Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, sharedPref.getInt("dailyNotificationHour", 7)); calendar.set(Calendar.MINUTE, sharedPref.getInt("dailyNotificationMin", 15)); calendar.set(Calendar.SECOND, 1); // if notification time is before selected time, send notification the next day if (calendar.before(Calendar.getInstance())) { calendar.add(Calendar.DATE, 1); } if (manager != null) { manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); } } //To enable Boot Receiver class pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); //endregion } else { //Disable Daily Notifications if (PendingIntent.getBroadcast(this, 0, alarmIntent, 0) != null && manager != null) { manager.cancel(pendingIntent); //Toast.makeText(this,"Notifications were disabled",Toast.LENGTH_SHORT).show(); } pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } 的{​​{1}}类,

AlarmReceiver

如果设备断电或重启,系统将关闭BroadcastReceiver,因此请在public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(Objects.requireNonNull(context)); SharedPreferences.Editor sharedPrefEditor = prefs.edit(); NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Intent notificationIntent = new Intent(context, MainActivity.class); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendingI = PendingIntent.getActivity(context, 0, notificationIntent, 0); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel("default", "Daily Notification", NotificationManager.IMPORTANCE_DEFAULT); channel.setDescription("Daily Notification"); if (nm != null) { nm.createNotificationChannel(channel); } } NotificationCompat.Builder b = new NotificationCompat.Builder(context, "default"); b.setAutoCancel(true) .setDefaults(NotificationCompat.DEFAULT_ALL) .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.ic_launcher_foreground) .setTicker("{Time to watch some cool stuff!}") .setContentTitle("My Cool App") .setContentText("Time to watch some cool stuff!") .setContentInfo("INFO") .setContentIntent(pendingI); if (nm != null) { nm.notify(1, b.build()); Calendar nextNotifyTime = Calendar.getInstance(); nextNotifyTime.add(Calendar.DATE, 1); sharedPrefEditor.putLong("nextNotifyTime", nextNotifyTime.getTimeInMillis()); sharedPrefEditor.apply(); } } } 上重新启动它,添加以下类:

AlarmManager

最后,不要忘记将这些权限添加到BOOT COMPLETE

public class DeviceBootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
    if (Objects.equals(intent.getAction(), "android.intent.action.BOOT_COMPLETED")) {
        // on device boot complete, reset the alarm
        Intent alarmIntent = new Intent(context, AlarmReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);

        AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(Objects.requireNonNull(context));

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY, sharedPref.getInt("dailyNotificationHour", 7));
        calendar.set(Calendar.MINUTE, sharedPref.getInt("dailyNotificationMin", 15));
        calendar.set(Calendar.SECOND, 1);

        Calendar newC = new GregorianCalendar();
        newC.setTimeInMillis(sharedPref.getLong("nextNotifyTime", Calendar.getInstance().getTimeInMillis()));

        if (calendar.after(newC)) {
            calendar.add(Calendar.HOUR, 1);
        }

        if (manager != null) {
            manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                    AlarmManager.INTERVAL_DAY, pendingIntent);
        }
    }
}
}

并在AndroidManidest

中注册您的接收者
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

AndroidManifest应该在<application <!--YOUR APPLICATION STUFF--> <receiver android:name=".DeviceBootReceiver" android:enabled="false"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> <receiver android:name=".AlarmReceiver" /> 指定的一天的特定时间设置,并且如果用户启用了Notification

答案 1 :(得分:2)

关于如何在StackOverflow上执行此操作的示例很多,但是不幸的是,由于Google更改了AlarmManager的工作方式,这些示例都不再起作用。

  • Android 6:打ze
  • Android 7:积极打ze睡[关闭屏幕后不久会禁用CPU]
  • Android 8:后台服务的其他限制

允许开发人员在特定时间唤醒设备的 only AlarmManager选项是AlarmManager.setAlarmClock。

Using setAlarmClock

除了警报之外,您还可以设置一个意图,使您可以在单击警报时启动应用程序。

还可以使用高优先级FCM Firebase Cloud Message在特定时间唤醒设备。

但是总而言之,没有其他选择:'setExact'和关联的方法不再像广告名称一样起作用。