How to Give Notifications on Android on Specific Time

How To give notifications on android on specific time?

first you need to use a broadcastreceiver. and because a broadcast receiver up only for a short time

from the android developer blog.When handling a broadcast, the application is given a fixed set of time (currently 10 seconds) in which to do its work. If it doesn't complete in that time, the application is considered to be misbehaving, and its process immediately tossed into the background state to be killed for memory if needed.

its a better practice to use also intent service here you have a example how to do it.

this is the broadcast receiver class.

public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}

@Override
public void onReceive(Context context, Intent intent) {

Intent intent1 = new Intent(context, MyNewIntentService.class);
context.startService(intent1);
}
}

and register it in the manifest.

<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="false" >
</receiver>

this is the intent service class.

public class MyNewIntentService extends IntentService {
private static final int NOTIFICATION_ID = 3;

public MyNewIntentService() {
super("MyNewIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {
Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle("My Title");
builder.setContentText("This is the Body");
builder.setSmallIcon(R.drawable.whatever);
Intent notifyIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 2, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//to be able to launch your activity from the notification
builder.setContentIntent(pendingIntent);
Notification notificationCompat = builder.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
managerCompat.notify(NOTIFICATION_ID, notificationCompat);
}
}

and register it in the manifest.

<service
android:name=".MyNewIntentService"
android:exported="false" >
</service>

and then in your activity set the alarm manger to start the broadcast receiver at a specific time and use AlarmManager setRepeating method to repeat it this example bellow will repeat it every day.

 Intent notifyIntent = new Intent(this,MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast
(context, NOTIFICATION_REMINDER_NIGHT, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
1000 * 60 * 60 * 24, pendingIntent);

i hope this will help you.

How To give notifications on Android on specific time in Android Oreo?

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.

UPDATE (Aug-2022): For Android 12 Devices

To make this work with Android 12 devices, you need to modify the pendingIntent's flags from 0 to FLAG_IMMUTABLE like this:

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, FLAG_IMMUTABLE);

Up until Build.VERSION_CODES.R, PendingIntents are assumed to be mutable by default, unless FLAG_IMMUTABLE is set. Starting with Build.VERSION_CODES.S, it will be required to explicitly specify the mutability of PendingIntents on creation with either FLAG_IMMUTABLE or FLAG_MUTABLE.
You can find more information on PendingIntent Flags here

Send notification at specific time

Everyone is telling you to use Alarm Manager class but there is no example code provided. Here is one of my implementation.

    AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 02);
calendar.set(Calendar.MINUTE, 00);

// setRepeating() lets you specify a precise custom interval--in this case,
// 1 day
alarmMgr.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis()/1000,
AlarmManager.INTERVAL_DAY, alarmIntent);

Here you need to provide the time at which you want to call the intent. In my code it is 2AM every night. Also for repeat interval I selected a day because my process needed to be called on daily basis.
Ask me if you have difficulty in understanding the code or if this solve your problem mark this as accepted. Thank you.

Notification at specific time with time from sharedpreferences

Finally I found out how to do it. For anyone who might need the same, I'll post the code:

This here is the method to call the notification in the activity once time is right:

 public void notifyAtTime() {
sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
long time = sharedPref.getLong("Timepref", 0);
SimpleDateFormat formatter = new SimpleDateFormat("HH", Locale.UK);
SimpleDateFormat formatter1 = new SimpleDateFormat("mm", Locale.UK);

Date date = new Date(time);
Date date1 = new Date(time);
long hour = Long.parseLong(formatter.format(date));
long minute = Long.parseLong(formatter1.format(date1));

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
notificationIntent.addCategory("android.intent.category.DEFAULT");

PendingIntent broadcast = PendingIntent.getBroadcast(this, 100, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, (int) hour);
cal.set(Calendar.MINUTE, (int) minute);
cal.set(Calendar.SECOND,0);
if (alarmManager != null) {
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, broadcast);
}
}

This here is the receiver

public class AlarmReceiver extends BroadcastReceiver {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onReceive(Context context, Intent intent) {
Intent notificationIntent = new Intent(context, TicketActivity.class);

TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(TicketActivity.class);
stackBuilder.addNextIntent(notificationIntent);

PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String ringer = sharedPreferences.getString("key_notifications_new_message_ringtone","");
boolean vibrate = sharedPreferences.getBoolean("Vibrate",true);
Uri ringtone = Uri.parse(ringer);

Notification notification = builder.setContentTitle(context.getResources().getString(R.string.notific))
.setContentText(context.getResources().getString(R.string.notific))
.setTicker(context.getResources().getString(R.string.notific))
.setSmallIcon(R.mipmap.ic_launcher)
.setSound(ringtone)
.setContentIntent(pendingIntent).build();

NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(0, notification);
}
}}

Android - Notification at specific time every day

Alarm Manager

public static void startAlarmBroadcastReceiver(Context context) {
Intent _intent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, _intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}

Alarm Broadcast Receiver

In AndroidManifest, just define the class as

<receiver android:name=".AlarmBroadcastReceiver" >
</receiver>

And code will be like

public class AlarmBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
showNotification(context);

}

void showNotification(Context context) {
String CHANNEL_ID = "your_name";// The id of the channel.
CharSequence name = context.getResources().getString(R.string.app_name);// The user-visible name of the channel.
NotificationCompat.Builder mBuilder;
Intent notificationIntent = new Intent(context, TestActivity.class);
Bundle bundle = new Bundle();
notificationIntent.putExtras(bundle);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

if (android.os.Build.VERSION.SDK_INT >= 26) {
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(mChannel);
mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setLights(Color.RED, 300, 300)
.setChannelId(CHANNEL_ID)
.setContentTitle("Title");
} else {
mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(Notification.PRIORITY_HIGH)
.setContentTitle("Title");
}

mBuilder.setContentIntent(contentIntent);
mBuilder.setContentText("Your Text");
mBuilder.setAutoCancel(true);
mNotificationManager.notify(1, mBuilder.build());
}

}



Related Topics



Leave a reply



Submit