如何在 Android Oreo 的特定时间在 Android 上发出通知? [英] How To give notifications on Android on specific time in Android Oreo?

查看:26
本文介绍了如何在 Android Oreo 的特定时间在 Android 上发出通知?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种在 Settings 中创建 preference 的方法,以便在一天中的特定时间(由用户在设置中设置)在 Android 中发送通知应用程序.我已经查看了不同的线程,例如 this,但是这不适用于 Android Oreo.

有人可以帮我解决这个问题或给我指点教程吗?

解决方案

在看了不同的帖子和对 AlarmManager 实现的一些研究后,这对我有用.

此基础是帖子和安排重复警报 Android 文档.

这是我目前的实现:

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

SwitchPreference 询问用户是否要启用重复每日通知.

TimePicker 设置通知时间.

MainActivityOnCreate 方法或任何你正在阅读 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 接收器 = 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);//如果用户启用了每日通知如果(每日通知){//region 启用每日通知日历日历 = Calendar.getInstance();calendar.setTimeInMillis(System.currentTimeMillis());calendar.set(Calendar.HOUR_OF_DAY, sharedPref.getInt("dailyNotificationHour", 7));calendar.set(Calendar.MINUTE, sharedPref.getInt("dailyNotificationMin", 15));日历.设置(日历.SECOND,1);//如果通知时间早于所选时间,则在第二天发送通知if (calendar.before(Calendar.getInstance())) {日历.添加(日历.日期,1);}如果(经理!= null){manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);如果 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);}}//启用Boot Receiver类pm.setComponentEnabledSetting(接收器,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,PackageManager.DONT_KILL_APP);//结束区域} else {//禁用每日通知if (PendingIntent.getBroadcast(this, 0, alarmIntent, 0) != null && manager != null) {manager.cancel(pendingIntent);//Toast.makeText(this,"Notifications was disabled",Toast.LENGTH_SHORT).show();}pm.setComponentEnabledSetting(接收器,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);}

接下来添加实现 BroadcastReceiverAlarmReceiver 类,如下所示:

public class AlarmReceiver extends BroadcastReceiver {@覆盖public void onReceive(上下文上下文,意图意图){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,通知意图, 0);如果 (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {NotificationChannel channel = new NotificationChannel("default","每日通知",NotificationManager.IMPORTANCE_DEFAULT);channel.setDescription("每日通知");如果(纳米!= 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("{是时候看一些很酷的东西了!}").setContentTitle("我的酷应用").setContentText("是时候看一些很酷的东西了!").setContentInfo("信息").setContentIntent(pendingI);如果(纳米!= null){nm.notify(1, b.build());日历 nextNotifyTime = Calendar.getInstance();nextNotifyTime.add(Calendar.DATE, 1);sharedPrefEditor.putLong("nextNotifyTime", nextNotifyTime.getTimeInMillis());sharedPrefEditor.apply();}}}

如果设备断电或重启,系统将关闭AlarmManager,所以在BOOT COMPLETE重新启动它添加这个类:

public class DeviceBootReceiver extends BroadcastReceiver {@覆盖public void onReceive(上下文上下文,意图意图){如果(Objects.equals(intent.getAction(),android.intent.action.BOOT_COMPLETED")){//在设备启动完成后,重置警报意图 alarmIntent = new Intent(context, AlarmReceiver.class);PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);最终 SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(Objects.requireNonNull(context));日历日历 = Calendar.getInstance();calendar.setTimeInMillis(System.currentTimeMillis());calendar.set(Calendar.HOUR_OF_DAY, sharedPref.getInt("dailyNotificationHour", 7));calendar.set(Calendar.MINUTE, sharedPref.getInt("dailyNotificationMin", 15));日历.设置(日历.SECOND,1);日历 newC = new GregorianCalendar();newC.setTimeInMillis(sharedPref.getLong("nextNotifyTime", Calendar.getInstance().getTimeInMillis()));如果(日历.after(newC)){日历.添加(日历.小时,1);}如果(经理!= null){manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);}}}}

最后不要忘记将这些权限添加到AndroidManidest:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

并在 AndroidManifest

中注册您的接收器

<应用程序<!--您的应用程序的东西--><receiver android:name=".DeviceBootReceiver"机器人:启用=假"><意图过滤器><action android:name="android.intent.action.BOOT_COMPLETED"/></意图过滤器></接收器><receiver android:name=".AlarmReceiver"/>

Notification 应该在 TimePicker 指定的一天中的特定时间设置,如果用户启用了 SwitchPreference.>

I am looking for a way to create a preference in Settings to send a notification at a specific time of the day (set by user in settings) in an Android app. I have looked at different threads like this, however this is not working in Android Oreo.

Can someone help me with this or point me to a tutorial?

解决方案

After looking at different posts and some research on AlarmManager implementation, this is what worked for me.

The base for this is this post and Schedule repeating Alarms Android Documentation.

This is my current implementation:

I have a SwitchPreference and a TimePicker implementation is Settings

SwitchPreference to ask if user wants to enable Repeating Daily Notifications.

TimePicker to set the Notification time.

In MainActivity's OnCreate method or wherever you are reading the SharedPreferences do this:

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);
}

Next add AlarmReceiver class that implements BroadcastReceiver like this:

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();
        }
    }
}

The system will turn off the AlarmManager if Device is powered off or reboots, so restart it again on BOOT COMPLETE add this class:

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);
        }
    }
}
}

And Finally do not forget to add these permissions to AndroidManidest:

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

and register your receivers in 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" />

The Notification should be set by this at a specific time of the day specified by TimePicker and if user enabled the SwitchPreference.

这篇关于如何在 Android Oreo 的特定时间在 Android 上发出通知?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆