Android AlarmManager execution time problem - android

I have set a AlarmManager which will give alarm repeatedly after certain time. I used following code for that.
Intent intent = new Intent(ViewDoughnut.this, NotificationMessage.class);
PendingIntent sender = PendingIntent.getBroadcast(ViewDoughnut.this, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP,nextAlarmTime, alarmInterval, sender);
Now to execute proper work at the alarm time I have created the following class extending BroadcastReceiver. Now I need the time in millisecond when the Alarm work should execute in that class. How to get it?
public class NotificationMessage extends BroadcastReceiver {
// Display an alert that we've received a message.
// #Override
public void onReceive(Context context, Intent intent) {
// here I need the time when the alarm should execute.
}
}
Here I like to add, system time is not working for me, because if the device is switch off at the alarm time, it execute that when the device is on after that time. But I need the time when it should execute.

You could create a class that derives from Application which holds all global variables. Then just set a long variable to hold the time before initialising the alarm

Related

Repeating background service using Alarm Manager

Currently I'm working on a new android project which uses background service. Because android version >=Oreo kills service automatically. So i use AlarmManager. I need to display a notification on exact time. Time for notification is setted in shared preferences.
My Alarm handler is following
class AlarmHandler {
private Context context;
AlarmHandler(Context context){
this.context=context;
}
void setAlarmManager(){
Intent intent=new Intent(context,NotificationService.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(context,2,intent,0);
AlarmManager alarmManager= (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if(alarmManager!=null){
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,5000,60000,pendingIntent);
}
}
void cancelAlarmManager(){
Intent intent=new Intent(context,NotificationService.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(context,2,intent,0);
AlarmManager alarmManager= (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if(alarmManager!=null){
alarmManager.cancel(pendingIntent);
}
}
}
My Notification service is following
public class NotificationService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String t1=timeFromsharedPreferences("t1");
String t2=timeFromsharedPreferences("t2");
String systemTime=getCurrentTime();
if(systemTime.equals(t1)){
notify();
}else if(systemTime.equals(t2)){
notify();
}
}
}
I start AlarmHandler using following code
AlarmHandler alarmHandler=new AlarmHandler(this);
alarmHandler.cancelAlarmManager();
alarmHandler.setAlarmManager();
I also register the broad cast receiver as following
<receiver android:name=".NotificationService" android:enabled="true" />
My problem is some times it's skipping my notification. Time is sheduled for 10:00 pm and 7:00 am. Notification on 10 pm is recieved (Note that i'm using phone at 10:00 pm or used minutes before 10:00 pm). But notification on 7:00 am is not receiving all time. Also note that i need notification on every day at same times. Please help me.
You cannot have a repeating exact alarm. If you need it to repeat at exact intervals, you need to set an exact alarm at the 1st interval, then re-arm the alarm when it fires so it is armed for the next interval, and keep repeating that process.
Edit:
you need to do something like this
1.- compute delta in millis to next interval
2.- set exact alarm to fire in delta millis
3.- when the alarm fires, handle the event and then go to step 1

How to add adding "remind me after half an hour" functionality - android

I have done an application that fire an alarm in certain time, and i am stuck on implementing remind me after half an hour functionality
what can i do to implement receiver, or service or anything that runs after half an hour of clicking the button of reming me after half an hour
any suggestions ?
Edited the code from Android execute a function after 1 hour to half an hour.
// the scheduler
protected FunctionEveryHalfHour scheduler;
// method to schedule your actions
private void scheduleEveryHalfHour(){
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
new Intent(WAKE_UP_AFTER_HALF_HOUR),
PendingIntent.FLAG_UPDATE_CURRENT);
// wake up time every 1 hour
Calendar wakeUpTime = Calendar.getInstance();
wakeUpTime.add(Calendar.SECOND, 30 * 60);
AlarmManager aMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
aMgr.set(AlarmManager.RTC_WAKEUP,
wakeUpTime.getTimeInMillis(),
pendingIntent);
}
//put this in the creation of service or if service is running long operations put this in onStartCommand
scheduler = new FunctionEveryHalfHour();
registerReceiver(scheduler , new IntentFilter(WAKE_UP_AFTER_HALF_HOUR));
// broadcastreceiver to handle your work
class FunctionEveryHalfHour extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// if phone is lock use PowerManager to acquire lock
// your code to handle operations every half hour...
// after that call again your method to schedule again
// if you have boolean if the user doesnt want to continue
// create a Preference or store it and retrieve it here like
boolean mContinue = getUserPreference(USER_CONTINUE_OR_NOT);//
if(mContinue){
scheduleEveryHalfHour();
}
}
}
You can write a simple service with a timer and whenever the time is up.it can do your thing.all you need to do is start a service with a timer inside of it

Android: Setting up a periodical alarm with AlarmManager

In my app, I need to add a row to a database and simultaniously set up an Alarm event to repeat every day at the time specified in one of the database columns. I already have some code, but it doesent trigger the alarm event at the specified time. Here is my code:
public class Add_reminder extends Activity {
AlarmManager am;
int hours, minutes;
REMIND_DB db;
Calendar calendar;
Cursor cursor;
Button button;
public void onCreate(Bundle savedInstanceState) {
//The usual code in the beginning of onCreate
//I load db from extended Application class as global since i use it in more
//Activities. Ints hours and minutes is set by user interaction
calendar = Calendar.getInstance();
am = (AlarmManager) getSystemService(ALARM_SERVICE);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
db.open();
db.insertReminder( -- parameters for database --);
cursor = db.getAllReminders();
cursor.moveToLast();
calendar.set(Calendar.HOUR, hours);
calendar.set(Calendar.MINUTE, minutes);
Intent intent = new Intent(Add_reminder.this, ReminderAlarm.class);
intent.putExtra("id_of_db_row", cursor.getInt(0));
PendingIntent pi = PendingIntent.getActivity(Add_reminder.this,
cursor.getInt(0), intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
24*3600*1000, pi);
db.close()
}
});
}
}
Database is updated correctly, but the ReminderActivity never starts on specified time. I dont know what could be wrong. I saw some example codes using BroadcastReceiver instead of starting the Activity right on with the PendingIntent, but this should work too, right? Does anyone knows what could be wrong?
My second question is if Im going to need the same instance of AlarmManager when I want to add or remove some alarms from a different Activity, or do I just declare another AlarmManager in every Activity I need?
Thank you!
You should use a broadcast receiver for alarms, and then start a service that does the actual work. Broadcast receivers shouldn't block the UI thread with lengthy operations (such as writing to the DB). Additionally, 'once a day' alarms might be problematic: if the user reboots the phone: registered alarms will be lost. You need to:
save the time the alarm is supposed to run to, say, SharedPreferecnes
re-register your alarm when the phone boots (receive the BOOT_COMPLETED broadcast)
don't use setRepeating() but let each alarm register the next on
Using a shorter period (1 or 2 minutes) for testing also helps.
As for the AlarmManager instance, it's a system service, you don't need to care about what instance you are using. Just get it using getSystemService()

access to activity from BroadCastReceiver.onReceive

Im developping alarm application.
I'm using listview on activity to reserve alarm.
after application finish BroadcastReceiver.onReceive() method,
I want to remove check of list.
But i dont know how to access to activity.
anybody knows?
The following is my code:
public class Activity_001 extends ListActivity {
Intent intent = new Intent(this, ReceiverGenerateAlarm.class);
intent.setAction(Conf.GenerateAlarm);
intent.putExtra(cal,timerList.get(0).getCal().getTimeInMillis())
PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent,
0);
AlarmManager am = (AlarmManager)
(this.getSystemService(ALARM_SERVICE));
am.set(AlarmManager.RTC_WAKEUP,
timerList.get(0).getCal().getTimeInMillis(), sender);
}
.
public class ReceiverGenerateAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context,Intent intent) {
String action = intent.getAction();
if(action.equals(Conf.GenerateAlarm)) {
Bundle bundle=intent.getExtras();
long cal = bundle.getLongArray("cal");
Calendar c = Calendar.getInstance();
c.setTimeInMillis(cal);
MediaPlayer_inherit_Class tm = new MediaPlayer_inherit_Class(cal);
tm.play();
//in here, wanna access alarm reservation list and remove check of list. as application has executed.
//set next alarm, if needed.
}
If I understand you correctly, you should be using a SQLite db to store your "alarm reservations". If this is true, simply update your db entries in your onReceive(). When the Activity is restored, it should check for changes to the alarm db table and update the UI accordingly.
One alternative is to call startActivity() from your onReceive() with bundled extras. Possibly pass a row id or time-stamp to query with Intent.putExtra().
Another is to put the BroadcastReceiver in your Activity class.
Hope that helps.

AlarmManager.RTC not working?

I changed AlarmController.java in ApiDemo a little bit, so I want the alarm not to go off when the phone is sleeping by using AlarmManager.RTC.
Intent intent = new Intent(AlarmController.this, RepeatingAlarm.class);
PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,
0, intent, 0);
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
firstTime += 15*1000;
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, //AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, 15*1000, sender);
The receiver code is like below:
public class RepeatingAlarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("DEBUG", "In RepeatingAlarm.onReceive, intent=" + intent);
Toast.makeText(context, R.string.repeating_received, Toast.LENGTH_SHORT).show();
}
}
I ran the modified app, but I still see many log messages as below after the phone wento sleep (the screen was black):
D/DEBUG ( 1390): In RepeatingAlarm.onReceive, intent=Intent { flg=0x4 cmp=com.example.android.apis/.app.RepeatingAlarm (has extras) }
This means the flag AlarmManager.RTC didn't work. Can someone tell me why?
Thanks.
Since you are using elapsedRealtime to get the alarm start time, I think you need to use the ELAPSED_REALTIME flag instead of the RTC flag.
My guess is that the alarm manager is thinking it's missed a ton of alarms because you are using the RTC flag which means the alarm manager is expecting you to send a time value in milliseconds since Jan 1st 1970, but instead you are sending elapsed milliseconds since the device booted, which is going to be a much much smaller number.
If you use the RTC flags you need to use System.currentTimeMillis() or get the time in milliseconds from a Java Date or Calendar object. If you use ELAPSED_REALTIME flags then you need to use SystemClock.elapsedRealtime().

Categories

Resources