AlarmManager.setExact() does not work - android

I wrote an application which is able to set alarms based on some specif times. These specific times change day by day. For example, sunrise time changes every day. So, I defined a main activity which is responsible to call setExact() method every night at 11:55 p.m and then it has to set tomorrow's alarms based on the specific times for tomorrow. The issue is, it does not work! When I set the alarm, it just works for one time, and it is not going to be set for the second time. I really need help. Thank you :)
public class MainPage extends AppCompatActivity {
private Calendar calendar = new GregorianCalendar();
protected GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setMainAlarm();
}
private void setMainAlarm() {
AlarmManager alarmMgr = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(".mainAlarmReciever");
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar alertCalendar = Calendar.getInstance();
alertCalendar.set(Calendar.HOUR,23);
alertCalendar.set(Calendar.MINUTE,54);
alertCalendar.set(Calendar.SECOND,59);
if (Build.VERSION.SDK_INT >= 23) {
alarmMgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alertCalendar.getTimeInMillis(), alarmIntent);
}else{
alarmMgr.setExact(AlarmManager.RTC_WAKEUP, alertCalendar.getTimeInMillis(), alarmIntent);
}
}
This is the related receiver class for that:
public class mainAlarmReciever extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
AlarmSetter.createOrUpdateAllAlarms(context);
this.completeWakefulIntent(intent);
}

The issue is you do not set the mainAlarm for tomorrow on your mainAlarmReciever.
Imagine that your mainAlarmReciever->onRecieve run at 11:54:59 P.M tonight. And it does whatever tasks you want to do. You should also set the mainAlarm for Tomorrow at 11:54:59 P.M in your onRecieve function.
Another option is using setRepeating (as CommonsWare mentioned it is not exact after API 19+).

Related

Enable button for a limited time period in a day in Adndroid

I have a button it should work according to time from 09.00 Am to 04.00 pm and rest of time it should not work.
I am developing an app. I am new in android. I have three buttons namely register, events, gallery.
When I click register button it should work according to time mentioned above.
if the user click register on that time it should pass on to the next activity and rest of times the button click action should not work.
check for class AlarmManager
on app start create AlarmManage class service with
time gap current to desable/enable time in milisecond.
public class MyReceiver extends BroadcastReceiver {
private static final int PERIOD = 1200000;//20*60*1000; 20 minutes
#Override
public void onReceive(Context ctxt, Intent i) {
scheduleAlarms(ctxt);
}
public static void scheduleAlarms(Context ctxt) {
AlarmManager mgr =
(AlarmManager) ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, AuthenticateService.class);
PendingIntent pi = PendingIntent.getService(ctxt, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + PERIOD, PERIOD, pi);
}

About AlarmManager and the way it is saved

I'm making an app that uses an Alarm service. I'm still learning how it works but one thing is very unclear and explained nowhere.
Say you create an Alarm when you launch your app. The alarm is saved somewhere because it needs to trigger even when your app is not running, right?
If so, how can I get this alarm when relaunching my app, so I don't create a new one everytime and have an infinity of alarms stored somewhere?
If not, how does it work? I was thinking about using a database or a json file but I have a feeling it's not necessary.
In my MainActivity class, I have this code to check if the alarm exists already (this code is obviously wrong)...
AlarmReceiver alarm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button) findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(alarm != null){
alarm.cancel();
}
alarm = new AlarmReceiver(MainActivity.this);
}
});
}
I have set a BroadcastReceiver for when the device is rebooted (as explained in the android tutorial)
public class SampleBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
new AlarmReceiver(context);
}
}
}
This is the AlarmReceiver class itself:
public class AlarmReceiver {
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
public AlarmReceiver(Context context){
alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmBroadcastReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 17);
calendar.set(Calendar.MINUTE, 30);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, alarmIntent);
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
public void cancel(){
alarmMgr.cancel(alarmIntent);
}
}
And the AlarmBroadcastReceiver that simply launches a notification (which works):
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
new NotificationMessage(context);
}
}
The alarm is saved somewhere because it needs to trigger even when your app is not running, right?
Correct.
how can I get this alarm when relaunching my app
You don't. It's a write-only API.
so I don't create a new one everytime and have an infinity of alarms stored somewhere?
Only create an alarm when it is needed, not on every run of your app.
Beyond that, use an equivalent PendingIntent to an existing alarm when calling the AlarmManager methods to replace that alarm (or using cancel() to cancel the alarm).
I was thinking about using a database or a json file but I have a feeling it's not necessary.
You need enough information in persistent storage to know what to do when the alarm goes off. You also need enough information in persistent storage to know what alarms are needed, to handle reboots, when you have to reschedule your previously-scheduled alarms.

WakefulIntentService starts immediately after scheduling

I am attempting to use CommonsWare's WakefulIntentService in a new application, specifically its ability to easily schedule the intent service to run at a later time.
I have a PreferenceActivity that allows the user to pick the schedule that the service is run (daily at 5am for example). Once the user makes a change to the preference value, I call:
AutoDownloadIntentServiceAlarmListener alarmListener = new AutoDownloadIntentServiceAlarmListener();
alarmListener.setForcedHour(5); // we want to schedule alarm for 5am everyday.
WakefulIntentService.scheduleAlarms(alarmListener, this, true);
For some reason, the desired IntentService (that extends WakefulIntentService) immediately starts up and performs its work.
Here is the implementation of of AutoDownloadIntentServiceAlarmListener:
public class AutoDownloadIntentServiceAlarmListener implements WakefulIntentService.AlarmListener {
private static final String TAG = "AutoDownloadIntentServiceAlarmListener";
private int mForcedHour = -1;
#Override
public long getMaxAge() {
return AlarmManager.INTERVAL_DAY * 2;
}
public void setForcedHour(int forcedHour) {
mForcedHour = forcedHour;
}
#Override
public void scheduleAlarms(AlarmManager alarmManager, PendingIntent pendingIntent, Context context) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
String autoDownloadTimePref = MyApplication.getInstance().getPrefs().getString("autoDownloadEpisodesSchedule", "0");
int hourOfAlarm = Integer.parseInt(autoDownloadTimePref);
// if this class has been created with a specific hour
// use it instead of the value obtained from SharedPreferences above.
if (mForcedHour > -1) {
Log.w(TAG, "Forced hour has been set for this AlarmListener. " + mForcedHour);
hourOfAlarm = mForcedHour;
}
calendar.set(Calendar.HOUR_OF_DAY, hourOfAlarm);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Log.d(TAG, String.format("Scheduled inexact alarm for %d", hourOfAlarm));
}
#Override
public void sendWakefulWork(Context context) {
Intent serviceIntent = new Intent(context, AutoDownloadIntentService.class);
WakefulIntentService.sendWakefulWork(context, serviceIntent);
}
}
It is my intention that the service does not startup as soon as it is scheduled, and instead starts up only at 5am the next day. (and continues to repeat on this schedule indefinitely, or until the user elects to disable or change its schedule)
What am I doing wrong?
It is my intention that the service does not startup as soon as it is scheduled, and instead starts up only at 5am the next day.
Except that's not what your code does, ~80% of the time. Your code says that it should run at 5am today, as you are getting the current time and not changing the day. Most of the time, 5am today is in the past, and so AlarmManager will immediately do its work.
You need to see if your calculated Calendar is older than now, and if so, add a day.

How to Autostart an AlarmManager to start a Scheduled Activity?

This tutorial come from android-er,
The main activity(AndroidScheduledActivity.java) start a AlarmManager to trigger BroadcastReceiver(MyScheduledReceiver.java) repeatly. In the onReceive() method of MyScheduledReceiver, it start another activity(MyScheduledActivity.java) indirectly. Such that the activity(MyScheduledActivity.java) will be start in scheduled interval.
Now I would use AutoStart to start automatically, but I was not able to write the AutoStartNotifyReceiver .
please can you give me an idea how to manage it ?
Thanks a LOT !
main activity, AndroidScheduledActivity.java :
public class AndroidScheduledActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonStart = (Button)findViewById(R.id.start);
buttonStart.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
Intent myIntent = new Intent(getBaseContext(),
MyScheduledReceiver.class);
PendingIntent pendingIntent
= PendingIntent.getBroadcast(getBaseContext(),
0, myIntent, 0);
AlarmManager alarmManager
= (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
long interval = 60 * 1000; //
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), interval, pendingIntent);
finish();
}});
}
}
Then BroadcastReceiver, MyScheduledReceiver.java
public class MyScheduledReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent scheduledIntent = new Intent(context, MyScheduledActivity.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);
}
}
and my problem AutoStartNotifyReceiver :
public class AutoStartNotifyReceiver extends BroadcastReceiver {
private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
????????????????????
}
}
}
Your AutoStartNotifyReceiver extends BroadcastReceiver class is there because the alarms get cleared when the device resets. So, in the onReceive of this class (where you have the question marks) you need to set the alarm all over again with the same code (without, of course the finish())that you used to do it the first time in the onClick method of AndroidScheduledActivity.
Then, you need to put the following entry in your Manifest to let the system know to launch your AutoStartNotifyReceiver when the system boots up:
<receiver android:name=".AutoStartNotifyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
As well as a permission in the Manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Now, this is all assuming you only have one alarm and only set it one way every time. If that is not the case than this gets a bit more complicated. But based on the little info you provided, my solution should do what you want.
Also, since you are a newcomer here just a kindly reminder: when someone provides an adequate answer to a question, the person asking the question (you) accepts the answer by clicking the checkbox next to the answer. This is so the person answering gets credit. Welcome to SO!
thanks, it works. just need to improve my java a little more. I have to add "context" don t know exactly why.
public class AutoStartNotifyReceiver extends BroadcastReceiver {
private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
Intent myIntent = new Intent(context, MyScheduledReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
long interval = 60 * 1000;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), interval, pendingIntent);
}
}
}

Help required in Alarm Application

I am new to Android. I am trying to develop an Alarm Application, which is actually a speaking clock. I just want the clock to use TextToSpeech API and speak out the greeting stuff and the current time as soon as the alarm time is ticked. The speech part is done. And now I want to implement the Alarm functionality. But Initially I am just trying to display a toast after 10 secs in order to check whether my classes are working properly. And I am not getting the desired response and I don't know why ? Following are the classes
Main Class aClockActivity
public class aClockActivity extends Activity {
/** Called when the activity is first created. */
private PendingIntent mAlarmSender;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button1 = (Button)findViewById(R.id.buttonOn);
button1.setOnClickListener(mStartAlarmListener);
Button button2 = (Button)findViewById(R.id.buttonOff);
button2.setOnClickListener(mStopAlarmListener);
}
private OnClickListener mStartAlarmListener = new OnClickListener() {
public void onClick(View v) {
// We want the alarm to go off 30 seconds from now.
//long firstTime = SystemClock.elapsedRealtime();
EditText Ehour = (EditText) findViewById(R.id.hour);
EditText Eminute = (EditText) findViewById(R.id.minute);
CharSequence CharHour = Ehour.getText();
CharSequence CharMinute = Eminute.getText();
int hour = Integer.parseInt(CharHour.toString());
int minute = Integer.parseInt(CharMinute.toString());
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
// calendar.add(Calendar.MINUTE, 1);
cal.add(Calendar.SECOND, 10);
mAlarmSender = PendingIntent.getBroadcast(aClockActivity.this,
0, new Intent(aClockActivity.this, Alarm_Broadcast.class), 0);
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), mAlarmSender);
// Tell the user about what we did.
Toast.makeText(aClockActivity.this, "The Alarm is Set",
Toast.LENGTH_LONG).show();
}
};
private OnClickListener mStopAlarmListener = new OnClickListener() {
public void onClick(View v) {
// And cancel the alarm.
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.cancel(mAlarmSender);
// Tell the user about what we did.
Toast.makeText(aClockActivity.this, "Setting off the alarm",
Toast.LENGTH_LONG).show();
}
};
Second Class Alarm_Broadcast
public class Alarm_Broadcast extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm worked", Toast.LENGTH_LONG).show();
}
}
Note: Just ignore the Edittext part in the OnClick() method, I'd use it later on.
Apart from the above problem there are few questions that I would like to ask.
1) How can I implement this app so that when the alarm is set, it can actually run as a service in the notification bar where the original AlarmClock runs. So that even if the app is closed its still running to invoke the alarm message at the right time.
2) I cannot show any Dialog box or can use TTS if the AlarmManager invokes a Class that extends either Service or BroadcastReciever.
3) I would appreciate if some one give me the idea to implement this app, I am sure there are many experts who would have gone through the same application.
Regards
Omayr
Here is some sample code i used in an alarm clock app hope it helps.
To set the alarm:
private void setAlarm(){
Context context = getApplicationContext();
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OnAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
myCal = Calendar.getInstance();
myCal.setTimeInMillis(TIME_THE_ALARM_SHOULD_GO_OFF_AS_A_LONG);
mgr.set(AlarmManager.RTC_WAKEUP, myCal.getTimeInMillis(), pi);
Log.i(myTag, "alarm set for " + myCal.getTime().toLocaleString());
Toast.makeText(getApplicationContext(),"Alarm set for " + myCal.getTime().toLocaleString(), Toast.LENGTH_LONG).show();
}
This goes in the onAlarmReceiver class:
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AlarmActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
this will start AlarmActivity whenever it needs to go off. In your case you'd put the toast and speech into the AlarmActivity.
How can I implement this app so that when the alarm is set, it can actually run as a service in the notification bar where the original AlarmClock runs. So that even if the app is closed its still running to invoke the alarm message at the right time.
Do not do this. Having a service stick around in memory 24x7 to watch a clock is a waste of RAM and will get you attacked by task killers, reducing your app's effectiveness. Please stick with AlarmManager.
I cannot show any Dialog box or can use TTS if the AlarmManager invokes a Class that extends either Service or BroadcastReciever.
Start an activity, perhaps a dialog-themed activity.
Just got the answer, whatever service, receiver, activity and etc you are using, you need to register it in your AndroidManifest.xml. Or else it wont work

Categories

Resources