I currently have a small project running in Android Studio that I need help with. I want to include a reminder function with notifications.
I have a total of 4 time pickers for each of which I want to set an alarm at the corresponding selected time.
With my current code the planned feature works only halfway, with the following problem:
If I select one time, then I sometimes get a notification at this time as desired. However, not always on time. Most of the time the alert doesn't appear and if it does, then half a minute to a minute later. And if I set all 4 alarms, in the best case I get a notification at the last selected time. In the worst case nothing happens.
But all I want is to get daily notifications at the selected 4 times.
About my code, I use an alarm manager which I call 4 times for the 4 alarms. I also use a broadcast receiver in which the notification is triggered. And I use a different RequestCode for each PendingIntent.
I really searched all relevant posts on SO, but not one of them worked for me. Maybe I have included it in the wrong way. I hope someone can help me. Here are my methods:
Alarm method from Activity.class
(UhrzeitInMillis describes the chosen time by timepicker, for example 16.03):
public void SetAlarm(Context context, long UhrzeitInMillis) {
Intent intent = new Intent(context, Optionen_Alarm.class);
final int id = (int) System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), id, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, UhrzeitInMillis, AlarmManager.INTERVAL_DAY, pendingIntent);
}
BroadcastReceiver (Optionen_Alarm.java):
public class Optionen_Alarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "myapp:mywakelocktag");
wl.acquire();
createNotificationChannel(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "1");
builder.setContentTitle("titel");
builder.setContentText("text!");
builder.setSmallIcon(R.drawable.picture);
builder.setColor(context.getResources().getColor(R.color.red));
builder.setVibrate(new long[]{0, 300, 300, 300});
builder.setLights(Color.WHITE, 1000, 5000);
builder.setAutoCancel(true);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setStyle(new NotificationCompat.BigTextStyle().bigText("text!"));
Intent notifyIntent = new Intent(context, Activity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 2, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
Notification notificationCompat = builder.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(15, notificationCompat);
wl.release();
private void createNotificationChannel(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "name";
String description = "description";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel("1", name, importance);
channel.setDescription(description);
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
```java
For battery reason, from android 6.0 the time you set on the alarm manager will not be guaranteed to trigger at the exact same time you have set. You could use the method '''setExactAndAllowWhileIdle()''' to make the alarm behave like you want.
You can read more about this here https://developer.android.com/training/scheduling/alarms
Related
I am currently developing an app on android studio using java where I want the user to be able to receive notifications from calendar events that they create. However, my notifications are not coming on time as they are either lagging or just not showing.
Here is my coding for the alarm receiver which sets up the notification:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String event = intent.getStringExtra("event");
String time = intent.getStringExtra("time");
int notId = intent.getIntExtra("id", 0);
Intent activityIntent = new Intent(context, CalendarActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, activityIntent, PendingIntent.FLAG_ONE_SHOT);
String channelId = "channel_id";
CharSequence name = "channel_name";
String description = "description";
NotificationChannel channel = new NotificationChannel(channelId, name, NotificationManager.IMPORTANCE_HIGH);
channel.setDescription(description);
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentTitle(event)
.setContentText(time)
.setDeleteIntent(pendingIntent)
.setGroup("Group_calendar_view")
.build();
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
notificationManagerCompat.notify(notId,notification);
}
}
Here is my CustomCalendarView Activity that sets up the alarm:
private void setAlarm(Calendar calendar, String event, String time, int RequestCode){
Intent intent = new Intent(context.getApplicationContext(), AlarmReceiver.class);
intent.putExtra("event",event);
intent.putExtra("time",time);
intent.putExtra("id",RequestCode);
#SuppressLint("UnspecifiedImmutableFlag") PendingIntent pendingIntent = PendingIntent.getBroadcast(context,RequestCode,intent,PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager)context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis() ,pendingIntent);
}
For example: When I set an alarm for 10:20 am, the notification either doesn't pop up or pops up really late like at 10:22 am. Please help! Let me know if I need to provide any more information.
You should use exact alarms for firing alarm on time,
use alarmManager.setExact() instead of alarmManager.set().
setExact() method is like set(), but does not permit the OS to adjust the delivery time. The alarm will be delivered as nearly as possible to the requested trigger time.
Put setExact() instead of set
alarmManager.setExact(...);
But with different devices and interface updates, the performance of the application work differed from one device to another, in this case you must put some settings in your application such as Disable Software Battery Optimizations, make the application run in the background even after closing, give Permissions Autostart, turn on all notifications and display them etc. Finally, call the functions in the onStop() event of the Activity.
Yes, correct. You should ask user to allow Battery Optimization and in Android 12 or higher you should ask user to enable Alarms & Reminders permission as well.
But, when your app wants to fire alarms exactly on time you have to use exact alarms.
A lot of questions on this topic have outdated answers (1-4 years old).
How To give notifications on android on specific time?
How To give notifications on android on specific time in Android Oreo?
Repeat notification every day 12h
The documentation for android did not lead me to specific solutions but helped me understand AlarmManager and the NotificationCompat. My code looks like this in my MainActivity
Intent notifyIntent = new Intent(this, MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_REMINDER,
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hours);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, seconds);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY,
pendingIntent);
My BroadcastReceiver looks like this
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Test", "RAN");
Intent intent1 = new Intent(context, MyNewIntentService.class);
context.startService(intent1);
}
}
My IntentService looks like this
public class MyNewIntentService extends IntentService {
private static final int NOTIFICATION_ID = 3;
public MyNewIntentService() {
super("MyNewIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("SH",
"Simple",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("Notifs");
mNotificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), "SH")
.setSmallIcon(R.mipmap.ic_launcher) // notification icon
.setContentTitle("Title") // title for notification
.setContentText("Message")// message for notification
.setAutoCancel(true); // clear notification after click
Intent intent1 = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pi);
mNotificationManager.notify(0, mBuilder.build());
}
}
I've added these to my AndroidManifest.xml right under my activity within the application tag
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true" >
</receiver>
<service
android:name=".MyNewIntentService"
android:exported="false" >
</service>
The notification fires for me but does not when the app is closed. In the android documentation, it seems like android has tried to limit the amount of background processing and timing of apps and the AlarmManager does not run at an accurate time because of this.
How do I make this into a reliable notification reminder for my app that runs at nearly the same time every day even when the app is closed?
You are almost there. Very close just one more thing.
Instead of startService() you should use startForegrounService(). In that case your alarm will always fire. Just a few tips:
you should declare the foreground service in your manifest
You have to use alarmManager.setExactAndAllowWhileIdle for API level higher than 23
You can also check this out for more information.
Update: This method worked forme on Xiaomi Redme note 8, but the just suddenly stopped working! It may not be a very dependable solution for custom OS devices at the moment. Hope google come up with a solid solution.
This question already has answers here:
Notification not showing in Oreo
(24 answers)
Closed 4 years ago.
I'm trying to pop up a notification when my alarm manager fires my onReceive() method. This is what I have done
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
//Acquire the lock
wl.acquire(10000);
startNotification(context);
wl.release();
}
public void setAlarm(Context context){
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(Activity, "MainActivity.class");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
assert am != null;
am.set(AlarmManager.RTC_WAKEUP, 60000, pi);
}
private void startNotification(Context context){
// Sets an ID for the notification
int mNotificationId = 001;
NotificationManager notificationManager;
NotificationCompat.Builder mBuilder;
// Build Notification , setOngoing keeps the notification always in status bar
mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("RandomTitle")
.setContentText("RandomText")
.setOngoing(true);
// Create pending intent, mention the Activity which needs to be
//triggered when user clicks on notification(StopScript.class in this case)
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.putExtra("extra","Extra Notificacion");
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent , PendingIntent.FLAG_UPDATE_CURRENT);
// context.startActivity(notificationIntent);
mBuilder.setContentIntent(contentIntent);
// Gets an instance of the NotificationManager service
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//Android Oreo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("notify_001",
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
// Builds the notification and issues it.
notificationManager.notify(mNotificationId, mBuilder.build());
}
Im really confused why this notification is not showing, I have tested my alarm and it triggers after 1 minute of beign created, but the notification is still not showing.
Any ideas?
thanks
From Android developer:
When you target Android 8.0 (API level 26), you must implement one or
more notification channels. If your targetSdkVersion is set to 25 or
lower, when your app runs on Android 8.0 (API level 26) or higher, it
behaves the same as it would on devices running Android 7.1 (API level
25) or lower.
Because your targetSdkVersion is 28, so you must add channelId in the Builder constructor too.
Change your code to:
// Build Notification , setOngoing keeps the notification always in status bar
mBuilder = new NotificationCompat.Builder(context, "notify_001") // Add channel ID to the constructor.
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("RandomTitle")
.setContentText("RandomText")
.setOngoing(true);
As per Android Developers Documentation :
NotificationCompat.Builder
NotificationCompat.Builder (Context context)
This constructor was deprecated in API level 26.1.0. use
NotificationCompat.Builder(Context, String) instead. All posted
Notifications must pecify a NotificationChannel Id.
Reference here
Edit:
Try the following :
Leave the NotificationCompat.Builder as it is now (with a string
representing NotificationChannel) .
Comment out your if block where you create a notification channel
Replace your NotificationManager with NotificationManagerCompat as the following :
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(mNotificationId, mBuilder.build());
I'm currently working on a notification that has to show at a specific time chosen by the user.
BUT when I run it, notifications show but not at the selected time, only when I ask the time in a timepickerdialog appear, before even choosing a time.
Does anyone know how to change the code so that notifications only appear at the time selected?
showDialog(DIALOG_ID); //this is the dialog that asks for an hour and minute.
alarmMethod1();
private void alarmMethod1(){
Calendar calendari1 = Calendar.getInstance();
calendari1.set(Calendar.HOUR_OF_DAY, hour_x);
calendari1.set(Calendar.MINUTE, minute_x);
calendari1.set(Calendar.SECOND, 00);
Intent myIntent1 = new Intent(Main2Activity.this, NotifyService1.class);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
pendingIntent1 = PendingIntent.getService(Main2Activity.this, 0, myIntent1, 0);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendari1.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent1);
}
Then here is the class where the intent goes:
public class NotifyService1 extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onCreate(){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager nNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(),Main3Activity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification mNotify = new Notification.Builder(this)
.setContentTitle("Hora d'entrenar!")
.setContentText("Clica per començar entrenament de pit i braços")
.setSmallIcon(R.drawable.logofinal)
.setContentIntent(pIntent)
.setSound(sound)
.build();
nNM.notify(1,mNotify);
}
}
Since Android API 19, all alarms are inexact in order to reduce battery consumption, that means that your alarms will not be triggered exactly when you want, but if you really need to do it, you need to use setExact and then write the repeat alarm handler by yourself, there's no longer a "set exact and repeat". Please, see:
http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)
http://developer.android.com/reference/android/app/AlarmManager.html#setExact(int, long, android.app.PendingIntent)
I want to add a Notificationmanager which should start after some milliseconds.
Everything is running, but still I don't knoe how to add the time that the notification comes after some weeks for example?
public void test(){
int icon = R.drawable.ic_launcher;
CharSequence ticker ="ticker";
long showAt =System.currentTimeMillis();
Notification notification = new Notification(icon, ticker, showAt);activity/intent
CharSequence notificationTitle = "test";
CharSequence notificationMessage = "Test1";
Intent intent = new Intent(this, Activity.class);
PendingIntent objPendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
Context ctx = getApplicationContext();
notification.setLatestEventInfo(ctx, notificationTitle, notificationMessage, objPendingIntent);
final int notificationIdentifier = 101; //an unique number set by developer to identify a notification, using this notification can be updated/replaced
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationIdentifier, notification);
// ...
}
You need to use Alarm manager with notification for repeating your notification after a regular time interval. Check AlarmManagerNotificationManagerTutorial , Android AlarmManager tutorial and Multiple Notifications Using AlarmManager . There are many tutorials out there. Hope this helps.