I am building a gym app that let the user pick the difficulties. The difficulties set according to the time and after the users check the difficulties and click the gym postures. Time will running according to the difficulties and if time run's up, alarm would be triggered. But in my condtion, the alarm would not triggered after the time run's out. I already add the receiver android:name at manifest. Here is my code:
private void saveAlarm(boolean checked) {
if (checked) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent;
PendingIntent pendingIntent;
int Hour, Minute;
alarmIntent = new Intent(Setting.this, AlarmNotificationReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
if (Build.VERSION.SDK_INT >= 23) {
Hour = timePicker.getHour();
Minute = timePicker.getMinute();
} else {
Minute = timePicker.getCurrentMinute();
Hour = timePicker.getCurrentHour();
}
Date dat = new Date();
Calendar cal_alarm = Calendar.getInstance();
Calendar cal_now = Calendar.getInstance();
cal_now.setTime(dat);
cal_alarm.setTime(dat);
cal_alarm.set(Calendar.HOUR_OF_DAY, Hour);
cal_alarm.set(Calendar.MINUTE, Minute);
cal_alarm.set(Calendar.SECOND, 10);
if (cal_alarm.before(cal_now)) {
cal_alarm.add(Calendar.DATE, 1);
}
alarmManager.set(AlarmManager.RTC_WAKEUP, cal_alarm.getTimeInMillis(), pendingIntent);
}
}
AlarmNotificationReceiver.java
public class AlarmNotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("It's time")
.setContentText("Time to training")
.setContentInfo("Info");
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1,builder.build());
}
}
Register your receiver like this in AndroidManifest.xml
<receiver
android:name="com.example.AlarmNotificationReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.example.AlarmNotificationReceiver" />
</intent-filter>
</receiver>
Set your intent like this and set Alarm like this:
Intent intent = Intent();
intent.setClass(context,AlarmNotificationReceiver.class);
intent.setAction("com.example.AlarmNotificationReceiver");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal_alarm.getTimeInMillis(), pendingIntent);
setExact is called on the exact time it is set.
Notice that from Android Oreo, notifications need notification channels to be displayed.
Create Notification channel like this:
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel("default","Default",NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
}
Create Notification like this:
Notification notification = new NotificationCompat.Builder(context, "default")
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("It's time")
.setContentText("Time to training")
.setContentInfo("Info")
.build();
manager.notify(1, notification);
Related
I would like to set a repeating alarm, in android 8 or 9 it works.
The question is how to set it to work it in 12 working parallel with android 8?
This is in the main activity, I set a startAlarm, and there is the missing part how to set the alarm in the case of sdk >= 31. When I start android to test it sends a notification at the beginning of the application but it do not send notification later.
MainActivity.java:
private void startAlarm(long when) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (alarmManager.canScheduleExactAlarms()) {
Log.e(TAG, "startAlarm: canScheduleExactAlarms");
}
}
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
} else {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent, 0);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
when*1000,
pendingIntent
);
} else {
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
when*1000,
pendingIntent
);
}
}
I set AlarmReceiver to send notification.
AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationHelper notificationHelper = new NotificationHelper(context);
NotificationCompat.Builder nb = notificationHelper.getChannelNotification();
notificationHelper.getManager().notify(1, nb.build());
long timeInSec = System.currentTimeMillis() / 1000;
Settings.setLastNotificationSent(timeInSec, context);
}
}
I set the permission in the manifest.
AndroidManifest:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<receiver android:name=".receiver.AlarmReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Probably you have to cancel previous alarm when you receive message in AlarmReceiver. I had the same problem and if i receive message from previous alarm i cancel it and then i can create new one.
private void cancelAlarm(){
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
} else {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pintent);
pintent.cancel();
}
I have a problem with notifications in my app. I want to set multiple notifications for different hours of the day. For example, let's take 8, 12 and 23 o'clock. But only the one at 23 o'clock triggers every day. What's wrong with my code and will it work even if the app is killed?
Here's the code that sets alarms in my activity
public void myAlarm(int hour, int minute) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
Intent intent = new Intent(getApplicationContext(), Reminder.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
if (alarmManager != null) {
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
and this is what I wrote in onCreate
myAlarm(8, 0);
myAlarm(12, 0);
myAlarm(23, 0);
this is my receiver
public class Reminder extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent in = new Intent(context, MySecoundActivity.class);
in.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "Reminder")
.setSmallIcon(R.drawable.bell)
.setContentTitle("Notification!")
.setContentText("Text of notification")
.setColor(0xfb3ff)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat notificationMngr = NotificationManagerCompat.from(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Reminder";
String description = "reminder channel";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel("Reminder", name, importance);
channel.setDescription(description);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
notificationMngr.notify(200, builder.build());
}
Receiver is in android manifest
<receiver android:name=".Reminder"/>
This is the expected behavior since in your code, when you set the alarm, you have to give every PendingIntent unique requestCode which in your case remains the same, i.e., 0. So when you set another alarm with same requestCode, the last alarm gets updated to the new time instead of creating a new alarm. So only your last alarm works. So at the time of setting the alarm, in your PendingIntent.getBroadcast(), instead of the 0, you could use either the Random class to generate a random number every time or you could just use (int)System.currentTimeMillis() which would always be a different number.
I am able to get notifications at a particular time in future by using Calendar class java (Example 9:15am). The Alarm manager sends the broadcast to the broadcast receiver whenever the time is 9:15am but when I open the app after 9:15am (Example 9:20am). I receive the same notification. Can anyone help my about this.
My Manifest
<receiver android:name=".others.NotificationReceiver"/>
Notification Receiver.java
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
createNotification(context);
}
private void createNotification(Context context) {
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
NotificationChannel linkChannel = new NotificationChannel(link_channel_id, "Link Channel", NotificationManager.IMPORTANCE_HIGH);
linkChannel.setDescription("This channel is used to show Zoom Links");
notificationManager.createNotificationChannel(linkChannel);
}
Notification notification = new NotificationCompat.Builder(context, link_channel_id)
.setSmallIcon(R.mipmap.ic_launcher_foreground)
.setContentTitle("Test Notification")
.setContentText("This is a test notification")
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.build();
notificationManager.notify(1, notification);
}
}
My Alarm Manager
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 10);
calendar.set(Calendar.SECOND, 0);
Intent myIntent1 = new Intent(this, NotificationReceiver.class);
myIntent1.setAction(ACTION_ONE);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(this, 1, myIntent1, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent1);
What I'm trying to do; the user picks a date he wants to be notified at with DatePicker, and then I add the name, the id, the release date and the alertTime (The time in milliseconds converted from the user's chosen time) as an entry in the alarms database called myAlarmsDB, which is simple SQL. And when it gets called by the OnReceive() method I delete the entry from the database, all is good except when I close my device; the alarms don't get restored and makes my app crash with no stack-trace. Any idea what might be the problem?
public class AlertReceiver extends BroadcastReceiver {
String name = "";
int id = 0;
String releaseDate = "";
// Called when a broadcast is made targeting this class
#Override
public void onReceive(Context context, Intent intent) {
Intent intActivity = new Intent(context, MainActivity.class);
intActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intActivity);
if("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Toast.makeText(context, "BOOT" , Toast.LENGTH_LONG).show();
// Set the alarm here.
Intent alertIntent = new Intent(context, AlertReceiver.class);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
for (Alarm alarm : MyApp.myAlarmsDB.getAllData()) {
alertIntent.putExtra("id", Integer.parseInt(alarm.get_id()));
alertIntent.putExtra("name", alarm.get_name());
alertIntent.putExtra("releaseDate", alarm.get_releaseDate());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, Integer.parseInt(alarm.get_id()), alertIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, Long.valueOf(Integer.parseInt(alarm.get_alertTime())), pendingIntent);
}
}
id = intent.getIntExtra("id", -1);
name = intent.getStringExtra("name");
releaseDate = intent.getStringExtra("releaseDate");
//delete from database
MyApp.myAlarmsDB.deleteFromId(String.valueOf(id));
}
}
How I set the alarms
public void setAlarm(View view) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, yearDate);
cal.set(Calendar.MONTH, monthDate);
cal.set(Calendar.DAY_OF_MONTH, dayDate);
long alertTime = cal.getTimeInMillis();
Intent alertIntent = new Intent(this, AlertReceiver.class);
// store id
alertIntent.putExtra("id", mainId);
alertIntent.putExtra("name", name);
alertIntent.putExtra("releaseDate", releaseDate);
Alarm alarm = new Alarm(String.valueOf(mainId), name, releaseDate, String.valueOf(alertTime));
MyApp.myAlarmsDB.addAlarm(alarm);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, mainId, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, alertTime, pendingIntent);
}
Permissions:
<receiver android:name=".AlertReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I'm using the AlarmManager to fire a notification daily in specific time which is selected via time picker. The notification fired correctly in the same day but doesn't repeat correctly every day!!!
This is the method for setting the notification using setRepeating():
public void witer_reminder(View view)
{
am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, Witer_Notification.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
Calendar calSet = (Calendar) cal.clone();
calSet.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
calSet.set(Calendar.MINUTE, picker.getCurrentMinute());
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
if(calSet.compareTo(cal) <= 0)
{
// Today Set time passed, count to tomorrow
calSet.add(Calendar.DATE, 1);
}
am.setRepeating(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),
24 * 60 * 60 * 1000, pendingIntent);
}
and this is the BroadcastReciver class:
public class Witer_Notification extends BroadcastReceiver
{
NotificationManager nm;
#Override
public void onReceive(Context context, Intent intent)
{
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
PendingIntent actiontIntent = PendingIntent.getActivity(context, 0,
new Intent(context, Suggestion.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("")
.setStyle(new NotificationCompat.BigTextStyle().bigText(""));
mBuilder.setContentIntent(contentIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
// mBuilder.setStyle(new NotificationCompat.InboxStyle());
NotificationManager mNotificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
BTW, the application target is SDK 19.
I found that the setExact() replacing to set()
Correct.
it's not applicable for intervalAtMilis as a parameter
Not directly. But, when you get control in your BroadcastReceiver from the setExact() event, call setExact() again to schedule the next event.
I didn't find anything for setRepeating()
There is no simple solution, because Google is trying to point out to you that this is bad for the battery. Using setExact() as described above is your only option for exact repeating.