I followed the instructions in this thread to create a daily alarm that starts a service at 12:30 each day which shows a notification. The problem I'm having is that setting the alarm also triggers the service (=> and the notification) every time the app starts.
Since I figured that the alarm will run only at the specified time (12:30) then I have no problem setting it when the app starts.
I realize that setting the alarm from scratch every time the app is launched is a bit ineffective since it only needs to be set once (I made it set on device boot as well), but it seemed like the easiest way.
So what's the best way to fix this? is there a way to set the alarm for the specified time without running the intent when setting?
Here's the code if you are interested (this function is called every time when launching the app):
public static void setAlarm(Context context)
{
Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction("com.Rani.app.SET_NOTIFICATION_ALARM");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar dailyCheckTime = Calendar.getInstance();
dailyCheckTime.setTimeZone(TimeZone.getTimeZone("GMT"));
dailyCheckTime.set(Calendar.HOUR_OF_DAY, 12);
dailyCheckTime.set(Calendar.MINUTE, 30);
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, dailyCheckTime.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
thanks in advance.
After trying several things, I used the information in this thread to preform a check if an alarm already exists, and setting one only if there isn't one already.
code:
public static void setAlarm(Context context)
{
Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction("com.Rani.app.SET_NOTIFICATION_ALARM");
boolean alarmUp = (PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_NO_CREATE) != null);
// check if an alarm already exists
if (alarmUp == false)
{
// set an alarm in case there isnt one already set
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar dailyCheckTime = Calendar.getInstance();
dailyCheckTime.set(Calendar.HOUR_OF_DAY, 12);
dailyCheckTime.set(Calendar.MINUTE, 30);
if (dailyCheckTime.getTimeInMillis() < Calendar.getInstance()
.getTimeInMillis()) {
dailyCheckTime.set(Calendar.DATE,
dailyCheckTime.get(Calendar.DATE) + 1);
}
AlarmManager alarm = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
alarm.setRepeating(AlarmManager.RTC_WAKEUP,
dailyCheckTime.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
Related
I want a task to do which require internet connection and it's must scheduled once in a day. I achieve above task partially using alarm manager like below.
Calendar c = Calendar.getInstance(); //gives u calendar with current time
c.add(Calendar.SECOND, 30);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0);
if (alarmManager != null) {
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
}
// my broadcast receiver
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//my task will be here
// for now I planned to check internet here and if it has i'll continue the task
}
}
//in manifest
<receiver android:name=".broadcast_receiver.AlarmReceiver" />
Is there any way to postpone above task in same day whenever got internet connection?
Can AlarmManager be used to achieve above requirement?
You can achieve that with WorkManager. Check out the official docs for more info.
I'm building an Android pedometer app that sends data to a SQLite database at 30 minute intervals using AlarmManager; if the phone is off when the transfer is supposed to occur, it will do the transfer immediately when the phone is switched back on.
(30 minutes is for testing - the actual interval will be 1 week).
I was told alarms wouldn't persist unless I used "intent.action.BOOT_COMPLETED" in the manifest, so I put that as a filter for my Alarm.java class.
My code to set the alarm (in MainActivity.java) is as follows:
public void insertData(View view) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long time= System.currentTimeMillis();
Date d = new Date(time);
editor.putLong("alarmtime", time); //the next ring time for the alarm is put in SharedPreferences
editor.apply();
Intent intent = new Intent(this, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, time, AlarmManager.INTERVAL_DAY, pendingIntent);
Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_LONG).show();
}
The code in the Alarm.java class (which extends BroadcastReceiver) is as follows:
Context context; //plus other declared variables
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
preferences = context.getSharedPreferences("MyPreferences", context.MODE_PRIVATE);
editor = preferences.edit();
long startedtime = preferences.getLong("alarmtime", 0); //get the next ring time
Date nextRingTime = new Date(startedtime);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
String action = intent.getAction();
//sometimes the onReceive() is called by the phone turning on
if (action != null && action.equals(Intent.ACTION_BOOT_COMPLETED)) {
//if phone turned on again before the alarm, just re-create the alarm for the same time, don't transfer data
Date currenttime = new Date(System.currentTimeMillis());
if ((currenttime.compareTo(nextRingTime) < 0)) {
Intent newintent = new Intent(context, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
newintent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, startedtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
return;
}
else if ((currenttime.compareTo(nextRingTime) > 0)) {
//if the phone was off when the alarm was supposed to make the transfer, set the alarm to the next intended ring time and insert data to db immediately
Calendar d = Calendar.getInstance();
d.setTime(nextRingTime);
d.add(Calendar.MINUTE, 30);
long newtime = d.getTimeInMillis();
Intent newintent = new Intent(context, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
newintent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, newtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
}
}
myDb = new DatabaseHelper(context);
// code for inserting data into database
//finally, update next intended ring time in SharedPreferences now that this particular transfer is done:
Calendar c = Calendar.getInstance();
c.setTime(nextRingTime);
c.add(Calendar.MINUTE, 30);
Log.v("insertdone, alarrm now", c.getTime().toString());
long nexttime = c.getTimeInMillis();
editor.putLong("alarmtime", nextime);
editor.apply();
}
Unfortunately, if the phone is off at the time of a scheduled alarm, when I turn it on afterwards, it calls onReceive() TWICE, meaning it inserts data twice.
How can this be stopped?
A solution would maybe be to use RTC_WAKEUP, but I really don't want to do that unless as an absolute last resort.
N.B. I have a separate bootBroadcastReceiver class that uses "intent.action.BOOT_COMPLETED" to restart a pedometer service, and am wondering whether having 2 different things started by the boot is causing problems...
I'm looking to create a function for an Android app in which I get a notification every 25th day of the month indicating I have to do a certain task.
I've been able to display the notification using the following code :
public class NotificationPublisher extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
long[] pattern = {0, 300, 0};
PendingIntent pi = PendingIntent.getActivity(context, 01234, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.small_logo_ico)
.setContentTitle(context.getResources().getString(R.string.notification_title))
.setContentText(context.getResources().getString(R.string.notification_content))
.setVibrate(pattern)
.setAutoCancel(true);
mBuilder.setContentIntent(pi);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(01234, mBuilder.build());
}
}
Now this system only works when I have my app open and doesn't allow me to display this when the app is closed. I've searched around and came to this:
Android notification at specific date
After trying this out (the schedule part) I noticed that it doesn't work when I close the app, as I get an error about unregistering the Receiver, doing this (unregistering) results in the receiver being canceled, and the notification can not be showed.
code used for the schedule:
NotificationPublisher receiver = new NotificationPublisher();
this.receiver = receiver;
IntentFilter filter = new IntentFilter("ALARM_ACTION");
registerReceiver(receiver, filter);
Intent intent = new Intent("ALARM_ACTION");
intent.putExtra("param", "My scheduled action");
PendingIntent operation = PendingIntent.getBroadcast(this, 0, intent, 0);
// I choose 15s after the launch of my application
alarms.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+15000, operation) ;
Is there anything I'm missing, or am I using the wrong methods to schedule a notification on a certain date? ( The current notification is set to be scheduled 15 seconds in the future, this is just for testing, I've got a function ready to display this at a certain date)
This is used to notify on middle of the month. Maybe You can get from below code.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, 15);
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 30);
}
Intent myIntent = new Intent(getApplicationContext(), MyReceiver.class);
myIntent.putExtra("NOTI_MSG",getString(R.string.notification_sidas));
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), NOTI_REQ_CODE_SIDAS, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY * 30, pendingIntent);
}
Alarm manager in my app does not work. I do everything like described here
https://developer.android.com/training/scheduling/alarms.html
but the alarm does not work.
Here is my code:
manifest
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
Reciever (Reciever registered in the Manifest)
#Override
public void onReceive(Context context, Intent intent) {
Intent alarmIntent = new Intent(Constants.ALARM_INTENT);
alarmIntent.setClass(context, NotificationActivity.class);
alarmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(alarmIntent);
}
Activity
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 1);
calendar.set(Calendar.MINUTE, 30);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
I do not know how to make it work. Please, help me to fix it.
First, remove the SET_ALARM permission, as it is not relevant here.
Second, you need to ensure that your Calendar object is in the future. Most of the time, yours will be in the past, because you are using calendar.set(Calendar.HOUR_OF_DAY, 1) and set(Calendar.MINUTE, 30). If you execute this code after 01:30, it will be in the past. In that case, you need to add() one day to make it be tomorrow at 01:30.
Third, use adb shell dumpsys alarm to see if your alarm is scheduled, once you make the above fixes.
Fourth, use LogCat to see if there are any warnings or errors coming from your code, such as perhaps AlarmReceiver or NotificationActivity not being registered in the manifest.
You're asking for an alarm based on the system's elapsed realtime clock here:
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
But you're passing it a time based on a normal calendar clock. If you want an alarm to happen using a calendar-based clock, say this instead:
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Note the differnce in javadoc between ELAPSED_REALTIME_WAKEUP and RTC_WAKEUP.
I'm trying out alarms and have hit a wall. I don't think my alarm is setting up properly because I never get a confirmation after the alarm is supposed to go off. Here's how I call on the alarm manager:
long alarmtime=new GregorianCalendar().getTimeInMillis()+10*1000;//run after 10 seconds
Intent i = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager alarmman = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmman.cancel(pi); // cancel any existing alarms
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
alarmtime, 10 * 1000, pi);//run every 10 seconds
And here's my AlarmReceiver.java:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "TEST", Toast.LENGTH_LONG).show();
}
}
However, the TEST text does not appear, and I can't figure out why.
Since you are using the AlarmManager.ELAPSED_REALTIME_WAKEUP argument, your initial alarm-time should be base on the elapsed real time of the device:
long alarmtime = SystemClock.elapsedRealtime() + 10 * 1000;
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmtime, 10 * 1000, pi);
(see this link).
For a BroadcastReceiver it's probably PendingIntent.getBroadcast() instead of PendingIntent.getService(). You are also cancelling the alarm, just update your PendingIntent like this and try not cancelling before:
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Read the documentation thoroughly for further information.
Make sure that the BroadcastReceiver is being called by doing a System.out.println("TEST"); instead of Toast. If you are able to see that in your logcat, then the problem probably is that you need to run the Toast in UI thread.