I'm writing my android application, which should always show a notification every day at 10:00 AM, no matter what. I use an alarm service to fire notifications at a specific time.
I set notifications to fire in two cases:
when I open the app, I set the alarm service to fire at the nearest 10:00 AM
when I receive notifications, I set the alarm service to fire the next day at 10:00 AM
The problem is: When the interval between the moment when I set alarm service and the actual alarm is greater than approx 12 hours, I just don't receive that notification. If the interval is smaller - I do. But I checked the logs, the alarm service is scheduled properly and for the correct time no matter how I set notifications.
I expect the problem is in the battery optimizer, but I don't know how to verify (and fix) that.
What I tried
In Android I've added my app to exceptions, allowing it to run in the background.
Tested on Huawei P30 Pro, Android 10.
Attaching the code how notifications are scheduled
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// display notification
NotificationController.scheduleNextNotification(context);
}
}
public class NotificationController {
public static void scheduleNextNotification(Context context) {
Intent myIntent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
long notificationTime = getNotificationTime(new Date());
int alarmType = AlarmManager.RTC_WAKEUP;
alarmManager.setExactAndAllowWhileIdle(alarmType, notificationTime, pendingIntent);
}
}
Related
I want to repeat a notification in android at a scheduled time in a specific day of the week (8:30am Saturday). I have set up the code and the alarm works (with the notification). The alarm need not wake up the device and fires the notification on next wake up.
Problem: The alarm is fired once every time the app is newly opened.
Tried different combinations but cant get it to work. Your help is much appreciated. Thank you.
MainActivity.java (OnCreate)
AndroidHelper ahelper= new AndroidHelper();
public static long rand_news_notify_freq= AlarmManager.INTERVAL_DAY * 7;
Calendar ca = Calendar.getInstance();
ca.set(Calendar.HOUR_OF_DAY,8);
ca.set(Calendar.MINUTE,30);
ca.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
ca.set(Calendar.SECOND, 0);
ca.set(Calendar.MILLISECOND, 0);
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
ahelper.setAlarms(alarmMgr, getApplicationContext(), RandomNewsNotification.class, ca, rand_news_notify_freq);
AndroidHelper.class
public class AndroidHelper{
public AndroidHelper()
{
}
public void setAlarms(AlarmManager alarmMgr, Context tctx, Class alarmClass, Calendar calendar, long freq)
{
Intent alarmIntent = new Intent(tctx, alarmClass);
PendingIntent pendingIntent = PendingIntent.getBroadcast(tctx, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
//alarmMgr.setRepeating(alarmMgr.RTC, calendar.getTimeInMillis(), freq, pendingIntent); // This is not working
alarmMgr.setInexactRepeating(alarmMgr.RTC, calendar.getTimeInMillis(), freq, pendingIntent); // This is not working too (same problem)
}
}
What needs to be changed?
I don't know you want to set exact repeating or inexact repeating. for exact repeating, you yourself should handle repeating with exact methods and don't use repeating methods of alaramManager like setInexactRepeating.
also consider if device is on Doze mode, alaram won't fire. so you should use setExactAndAllowWhileIdle method to guarantee that the alarms will execute.
you can see more detail on Android Developer document:
https://developer.android.com/training/scheduling/alarms
I want to make it so that a user will receive a push notification every 24 hours after he completes an action within my android game. Push notifications are working with Parse, but I don't know how to delay 24 hours, and then send the push. The Parse documentation mentions background jobs, but since those time out after 15 minutes, I don't think I can use those. Is there something I'm missing, or another option I can use?
Instead of push notification, you can depend on In-app notification, for that you have to set an AlarmManager to trigger the notification after 24 hour, and on receive of alarm you can initialize another alarm that has to be triggered after 24 hours.
ex:
public static void startAlarm(Context context) {
Calendar nextAlarmTime = getNextAlarmTime(context);
if (nextAlarmTime != null) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intentAlarm = new Intent(context, AlarmReceiver.class);
alarmManager.set(AlarmManager.RTC_WAKEUP, nextAlarmTime.getTimeInMillis(), PendingIntent.getBroadcast(context, 1, intentAlarm, PendingIntent.FLAG_CANCEL_CURRENT));
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
private static final String TAG =
AlarmReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
initNotificationMessage(context);
scheduleNextNotification(context);
}
}
and if you wish to change the notification messages then you have to make an api call to your server just before showing the notification,and receive the message from server and show it as notification
and if you insisted to use push notification, it is better to keep the logic in client side than using cron job or any similar mechanism, that means use the same logic as mentioned above and request your server to send a push notification to your device.
I want to start a service every day from 8am to 6pm. I am using 3 alarms.
For starting alarm2 everyday at 8am.
For starting service every 1 min.
To stop alarm2.
Is it the proper way? Also I am unable to start alarm2 from alarm1.
This is code for alarm 1:
public class AlarmReceiver1 extends BroadcastReceiver {
int interval;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent in=new Intent(this,AlarmReceiver2);
PendingIntent startingIntent = PendingIntent.getBroadcast(context, 0,in, 0);
long duration = interval * 60 * 1000;
manager.setRepeating(AlarmManager.RTC_WAKEUP,timeOn.getTimeInMillis(), 86400000,startingIntent);
}
}
Far from enough code to tell if it has been set up properly. There is a good example here on how you should set up the AlarmManager. I'd recommend looking it through if there is something you've missed.
Also as you can see in the example you gotta reset the Alarms every time the phone is rebooted. If you don't the services will not run.
I have an Android application that allows a user to add an alarm that will log their location. For example, every day at 8am I want to log where I am. When the alarm is received, it starts a service that gets the user's location and saves it to a db. The feature works fine when the app is running (in the background or foreground).
The problem is, the alarm doesn't seem to go off if I go into the task manager and force the app to close. This is important as the user could reboot their phone and kill the app.
Here is the method that sets the alarm:
private void setNewAlarm(int hour, int minute, int id) {
Intent alarmIntent = new Intent(AutoLoggerActivity.this, AlarmReciever.class);
alarmIntent.putExtra(Constants.ALARMID_FIELD_NAME, id);
PendingIntent sender = PendingIntent.getBroadcast(AutoLoggerActivity.this, id, alarmIntent, 0);
Calendar alarmCal = Calendar.getInstance();
alarmCal.set(Calendar.HOUR_OF_DAY, hour); // set user selection
alarmCal.set(Calendar.MINUTE, minute); // set user selection
alarmCal.set(Calendar.SECOND, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmCal.getTimeInMillis(), 120000, sender);
}
Here is the BroadcastReceiver:
public class AlarmReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
int alarmId = bundle.getInt(Constants.ALARMID_FIELD_NAME);
Toast.makeText(context, "Alarm Running: ID = " + alarmId, Toast.LENGTH_LONG).show();
Log.d(TAG, "AlarmReceiver: onRecieve. ID = " + alarmId);
Intent serviceIntent = new Intent(context, LocationRecordingService.class);
serviceIntent.putExtra(Constants.ALARMID_FIELD_NAME, alarmId);
context.startService(serviceIntent);
}
}
Any idea why this is happening?
This is actually a design feature of the Android operating system, and isn't something you can cirumvent. An application that is in a "stopped" state cannot receive any broadcasts. It is only in this state under two conditions:
When the application is first installed before it is ever launched
When the user actively goes into Settings and does a force close
The problem is, the alarm doesn't seem to go off if I go into the task manager and force the app to close. This is important as the user could reboot their phone and kill the app.
This is not quite true, because if the device is rebooted the application is not considered to be in this state of being "stopped". However, alarms do not persist reboots, so your application will need to listen for ACTION_BOOT_COMPLETED broadcast by the system when the device starts up so you can reschedule any pending alarms.
If the user actively kills your app, you must respect that choice of theirs.
I tried to develop a sample Alarm Application. I searched Google and SC, most of their examples confused. How can I create an alarm application with the following requirements,
In My Home screen i have a button, like "START ALARM", when i click the button a time picker must enable.
I select the time as I wish, once I pick the time, the alarm icon will enabled on widget. (For example if we set the alarm in default mobile Alarm application, the icon will be enabled, that indicates the alarm is set).
When the set time is reached (the time which is set form the TimePicker app), the alarm will beep.
These are my requirements, I finished the first two points, but I'm still struggling on setting the alarm.
Take a look at AlarmManager. And, If you want to use alarm simultaneously you must use Service class for that. And, see below sample code -
public class OnBootReceiver extends BroadcastReceiver {
private static final int PERIOD=300000; // 5 minutes
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager mgr =
(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, OnAlarmReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+60000, PERIOD, pi);
}
This will repeat the alarm with every 6 Mins. See Scheduling Repeating Alarms document.
when you enable the alarm you have to call inbuilt alarm manager and use the alarmmanager.set to set the alarm time in the manager.
Once the alarm time (in milliseconds) is given to the alarm manager it will send message and you can retrive the message through reciever class
//creating and assigning value to alarm manager class
Intent AlarmIntent = new Intent(MainActivity.this, AlarmReciever.class);
AlarmManager AlmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent Sender = PendingIntent.getBroadcast(MainActivity.this, 0, AlarmIntent, 0);
AlmMgr.set(AlarmManager.RTC_WAKEUP, Alarm.getTimeInMillis(), Sender);
For recieving the alarm you have to make a new class which extends reciever where in onrecieve you can set the intent to the activity u want to call on alarm time , you can also provide notification.
public class AlarmReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{ //Build pending intent from calling information to display Notification
PendingIntent Sender = PendingIntent.getBroadcast(context, 0, intent, 0);
NotificationManager manager = (NotificationManager)context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
Notification noti = new Notification(android.R.drawable.stat_notify_more, "Wake up alarm", System.currentTimeMillis());
noti.setLatestEventInfo(context, "My Alarm", "WAKE UP...!!!", Sender);
noti.flags = Notification.FLAG_AUTO_CANCEL;
manager.notify(R.string.app_name, noti);
//intent to call the activity which shows on ringing
Intent myIntent = new Intent(context, Alarmring.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
//display that alarm is ringing
Toast.makeText(context, "Alarm Ringing...!!!", Toast.LENGTH_LONG).show();
}}
If you still get any problem ask again..:)
If you want to make things interesting, you can try to create one without a possibility of dismissing/snoozing. I made this a while ago, you can read about it in this tutorial:
Alarm Application in Android (Tutorial using AlarmManager)
And test the app functionality by downloading this app:
Oversleeper on Google Play
To finish your last point you need to do Date Comparision and use AlaramManager Alaram Doc and again you need to use Service
to compare next date and time. Hope it will helpful for you.
You need to use RingtoneManageror the NotificationManager(to show any text or image to the user for notification at the top of screen), Or you can use MediaPlayerto set to play sound when alarm time is reached. You have to set <receiver> tag in manifest file, that must include a class extending BroadCastReceiver. In the receiver class you can write your code to wake your device up.