AlarmManager alarm start when system time is changed by user? - android

i am using AlarmManager class for setting Alarms it is working fine.
But if i set alarm like 9pm and current time is 8pm and i changed the system time to 10pm
then alarm 9pm alarm start automatically. so to solve this issue
i have searched so much but did not found any good answer
Please help
here is my code for alarm setting
final int id = (int) System.currentTimeMillis();
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("requestCode", id);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 2*60*1000, pendingIntent);

One of the options is to store all set alarms in database, then create a BroadcastReceiver which will listen for ACTION_TIME_CHANGE action. When user changes time it will be triggered. Then create a IntentService which will be responsible for resetting alarms. In this service class:
Read db and identify all passed alarms.
Cancel passed alarms
Set alarms for next day
Your code may look like as below:
In your Manifest:
<uses-permission android:name="android.permission.ACTION_TIME_CHANGE"/>
and below activities:
<receiver android:name=".TimeChangedReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.TIME_SET" />
</intent-filter>
</receiver>
<service android:name=".RestartAlarmsService"/>
Create class "TimeChangedReceiver" inside of which:
public class TimeChangedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if("android.intent.action.TIME_SET".equals(intent.getAction())) {
Intent i = new Intent(context, RestartAlarmsService.class);
ComponentName service = context.startService(i);
}
}
}
Create "RestartAlarmsService" class inside of which:
public class RestartAlarmsService extends IntentService {
public RestartAlarmsService() {
super("RestartAlarmsService");
}
#Override
protected void onHandleIntent(Intent intent) {
// read db here
// then cancel passed alarms
// reset them to next day
}
}
You can find many tutorials on how to use Databases and implement it in your code. Hope my answer is somehow helpful.

yes it will give you broadcast, as your pending intent object is still attached to that event while you change time that is greater than you alarm firing time.
solution- validate your condition while you receive broadcast from alarm manager

Related

Using Alarm Manager to execute a task once

I am trying to execute an action once at a later time using AlarmManager. I followed the code and the question here and came up with this.
public class EmailAccountUpdater extends BroadcastReceiver
{
// Constructors
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION))
{
Log.v("Test", " Step 1 - Creating the alarm " );
// Place holder
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent newIntent = new Intent("com.test.EMAIL_ACCOUNTS_CHANGED");
PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, newIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.set( AlarmManager.RTC_WAKEUP, 35000, pendingIntent);
}
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver
{
// constructors
#Override
public void onReceive(Context context, Intent intent)
{
Log.v("Test","Step 2 - Alarm received");
if (intent.getAction().equals("com.test.EMAIL_ACCOUNTS_CHANGED"))
{
onAccountsUpdated();
}
}
public void onAccountsUpdated()
{
// do something
}
}
In the manifestManifest.xml
<receiver android:name="full.path.AlarmReceiver">
<intent-filter>
<action android:name="com.test.EMAIL_ACCOUNTS_CHANGED"/>
</intent-filter>
</receiver>
Basically what I wanted to do was to put the following in Placeholder (just below the first log statement).
Thread.sleep(35000);
onAccountsUpdated();
But according to this, it is not suggestible to use postDelayed and Thread.sleep in BroadcastReceiver. So I came up with this. What happens is I always get the Step 1 but never reach the step 2. What I am I doing wrong? Any help would be welcome.
The solution is (as per the thread you linked):
you want something to happen some time after the broadcast you can start a service, and that service wait the amount of time, or if the amount of time you want to wait is longer than a few seconds, you should just put the launch of this service in the AlarmManager and let the AlarmManager launch the service for you.
Your plan doesn't work because the context is destroyed after EmailAccountUpdater.onReceive returns.

How to ensure the alarm is invoke even I haven't open the app in android?

Currently I work on a reminder android app, since it remind people to take the pill , so it is really important for the system not missing the alarm.
I found some tutorial and create the code like this:
setTimer.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
GregorianCalendar date = new GregorianCalendar(2014,5,4,15,4); // Month start at 0 , meaning January is 0
long dateTime = date.getTimeInMillis();
AlarmManager alarmManager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
Intent intentAlarm = new Intent(ctx, AlarmReceiver.class);
alarmManager.set(AlarmManager.RTC_WAKEUP, dateTime, PendingIntent.getBroadcast(ctx, 1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
}
});
Mainfest
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<receiver android:name=".Listener.AlarmReceiver" />
Receiver
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
}
The problem is I wonder will the alarm invoke even I haven't open the app. The only case missing the alarm is when the user turn off the device? Thanks
You can start a background service through your app which takes care of setting up alarms and firing them even when your app is not opened or in the foreground. Here's a tutorial on services ----> http://www.vogella.com/tutorials/AndroidServices/article.html

Wake up app from sleep at set time

I want to send my app to sleep and then wake it up at set times. I have it going to sleep but not waking up.
This sets the wakelock:
private void setWakeLock(){
System.out.println("wakelock");
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "DoNotDimScreen");
wl.acquire();
}
This sets alarms for wake/sleep times:
private void setWakeSleep(){
java.util.Calendar c = java.util.Calendar.getInstance();
c.set(java.util.Calendar.HOUR_OF_DAY, 17);
c.set(java.util.Calendar.MINUTE, 53);
c.set(java.util.Calendar.MILLISECOND, 0);
Intent sleepIntent = new Intent("SLEEP_INTENT");
PendingIntent sleepPendingIntent = PendingIntent.getBroadcast(this, 0, sleepIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), sleepPendingIntent);
c.set(java.util.Calendar.HOUR_OF_DAY, 18);
c.set(java.util.Calendar.MINUTE, 14);
c.set(java.util.Calendar.MILLISECOND, 0);
Intent wakeIntent = new Intent("WAKE_INTENT");
PendingIntent wakePendingIntent = PendingIntent.getBroadcast(this, 0, wakeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager2 = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager2.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), wakePendingIntent);
}
And this is the broadcast receiver:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Time updateHour = new Time();
updateHour.set(System.currentTimeMillis());
if (intent.getAction().equals("SLEEP_INTENT")) {
System.out.println("sleep");
wl.release();
}
if (intent.getAction().equals("WAKE_INTENT")) {
wl.acquire();
System.out.println("wake");
//initialise();
}
}
};
Any help greatly appreciated!
First, you don't want a wakelock; those are for keeping the device from going to sleep, which is highly anti-social unless your app really requires it (it kills the battery).
Second, your code to set the wakeup time will fail if you call it after 18:14 since you'll now be defining a time in the past. Let's ignore that for now.
Next, your intent action should be something like "org.user1797190.WAKE_INTENT" rather than simply "WAKE_INTENT" which could cause collisions. If you anticipate making this intent public, consider registering it at http://openintents.org. That's not your problem either, though.
You don't need alarmManager2 -- there's only one alarm manager in the system, so just re-use the first one.
I've never heard of making an app go to "sleep" per se. Do you mean you want the app to go away, and then come back later?
Here is what I would do. Forget about the "SLEEP_INTENT" completely. Just schedule a "WAKE_INTENT" and then call finish(). Your app will simply leave the screen.
I would forget about the broadcast receiver entirely. Instead, I would use getActivity() instead of getBroadcast() to get a pending intent that will restart the activity. Modify your manifest so that your WAKE_INTENT will go to the activity. Also, you should set the "android:launchMode" property to "singleTask" so multiple instances of your activity aren't created. You'll also need to implement onNewIntent() to handle the wakeup intent if your activity is already running when it arrives.
Finally, if your activity is part of the same application that will be creating the intent, you don't need a named intent at all; you can create them by class. You'll need another way to let the receiver know that this is a wakeup intent though.
So, putting it all together:
Your manifest should contain:
<activity android:name=".TestActivity" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Your code should contain:
/**
* Arrange for the activity to return at a specific time.
* Call finish() after calling this method().
* This function can be called from anywhere that has a valid Context.
*/
public static void scheduleWakeup(Context ctx, long timeMillis) {
if (DEBUG) Log.d(TAG, "Scheduling wakeup for " + timeMillis);
Intent intent = new Intent(ctx, TestActivity.class);
intent.putExtra("wakeup", true);
PendingIntent pi = PendingIntent.getActivity(ctx, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
mgr.cancel(pi); // Cancel any previously-scheduled wakeups
mgr.set(AlarmManager.RTC_WAKEUP, timeMillis, pi);
}
...
protected void onCreate(Bundle state) {
Intent intent = getIntent();
if (intent.getBooleanExtra("wakeup", false)) {
// We were woken up by the alarm manager
}
...
}
protected void onNewIntent(Intent intent) {
if (intent.getBooleanExtra("wakeup", false)) {
// We were woken up by the alarm manager, but were already running
}
}
This is pretty close to what I'm doing in my own apps, and it works pretty well for me.
You'll have to test this yourself, of course. Log.d() is your friend.
as above. The problem was that I was using a broadcast receiver within the calling activity.

android services life time continuation

In mainactivity
I have Broadcast Receiver, pending intent, and alarm manager. It triggers as per selected time (System.currentTimeMillis() + smstimeinmilliseconds).
Intent intent = new Intent(this, DBBroadcastReceiver.class);
intent.putExtra("message", message);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + smstimeinmilliseconds, pendingIntent);
On selected time, this pending intent triggers broadcast receiver.
public class DBBroadcastReceiver extends BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent)
{
message = intent.getStringExtra("message");
}
I can set message in activity and set time in alarm manager.
Every thing works flawless. I can activate and deactivate this. But if i set few alarm mangers in future time and reboot my mobile. all alarm manager destroy .....
Kindly tell me in steps and sequence what to do with activity , broadcast receiver and do i need service , if yes then how can i use it.
You need a BoradcastReceiver to be called on boot up.
Then you need in your manifest :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver
android:name=".broadcasts.YourBroadcastReceiverName">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
And this broadcast receiver needs to schedule again all the alarms.
Something like :
public class YourBroadcastReceiverName extends BroadcastReceiver {
private AlarmManagerFacade alarmManager;
#Override
public void onReceive(Context context, Intent intent) {
// Retreive data related to alarms
Cursor cursor = context.getContentResolver().query(Alarm.CONTENT_URI, null,
Alarm.COLUMN_ACTIVE + " = ? ",
new String[] { String.valueOf(1) }, "");
if (cursor.moveToFirst()) {
// Schedule all the active alarms.
alarmManager = new AlarmManagerFacade(context);
do {
// TODO : Schedule alarm according to data in cursor.
} while (cursor.moveToNext());
}
cursor.close();
}
}
(This code is coming from one of my app, some of the objects are not available in the Android SDK)
In order to be able to re schedule all the alarms, you need to have them stored somewhere.
You can write your own ContentProvider for example.
It works well with other android components thanks to the CursorAdapter widget.
It is not the easiest solution but it's the way to go if you want to follow android guidelines.
There may be other simpler alternative to store your alarms, like SharedPreferences.
It's easy to use.
But you will need to hack around to store multiple alarms in a friendly manner.
One last alternative is that you can create an object containing the information, serialize it and store it as a file on the SD Card.
It's ugly and not flexible.
But it not that hard to implement ...
If you want to have a closer look to each storage options, you can read about it in the docs here : http://developer.android.com/guide/topics/data/data-storage.html
I hope all this help you. :)

How to run a service every day at noon, and on every boot

In my app I have SQLite database that has one table with date rows in milliseconds. I would like to have a notification shown every day IF 30 days has passed since the last date value stored in my database. A service seems to be a good way to accomplish this check up.
I ran into Commonsware's WakefulIntentService and thought it could be the answer but I really don't know how should I implement it. In the demo it starts a service after 5 minutes since boot is complete which is just fine but what do I need to add to get it also start at every noon. (... but only to show one notification / day, not both, as from boot and regular daily check up)
I know this could be solved using AlarmManager but really don't know how. So, the help I need is to give me some samples / key points to get the service start on every boot and/or every day without app running.
thanks
Android alarmmanager is your answer. use it with a broadcast receiver which also resets the alarms on phone wake.
Now with code example:
Setting alarm inside a method:
Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction("packagename.ACTION");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Receiver for your interval:
public class AlarmReceiver extends BroadcastReceiver {
private final String SOMEACTION = "packagename.ACTION"; //packagename is com.whatever.www
#Override
public void onReceive(Context context, Intent intent) {
Time now = new Time();
now.setToNow();
String time = FileHandler.timeFormat(now);
String action = intent.getAction();
if(SOMEACTION.equals(action)) {
// here you call a service etc.
}
Receiver for resetting alarms whenever phone has been shut down.
public class AlarmSetter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// get preferences
SharedPreferences preferences = context.getSharedPreferences("name_of_your_pref", 0);
Map<String, ?> scheduleData = preferences.getAll();
// set the schedule time
if(scheduleData.containsKey("fromHour") && scheduleData.containsKey("toHour")) {
int fromHour = (Integer) scheduleData.get("fromHour");
int fromMinute = (Integer) scheduleData.get("fromMinute");
int toHour = (Integer) scheduleData.get("toHour");
int toMinute = (Integer) scheduleData.get("toMinute");
//Do some action
}
}
}
Manifest very important, this is added under application:
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="packagename.ACTION"/>
<action android:name="packagename.ACTION2"/>
</intent-filter>
</receiver>
<receiver android:name="AlarmSetter" >
<intent-filter>
<action
android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Also in order for this to work you need to add permission to receive the boot Broadcast in the manifest with following line:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Hope this cleared things up, if any errors plz tell.
Edit (added alarmsetter example):
public class AlarmSetter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do your stuff
}
}
This answer seems pretty old.
Now, I would totally recommend people to check out SyncAdapter framework provided by Google.
It is custom made for such things.
Here's the link: https://developer.android.com/training/sync-adapters/index.html
In the demo it starts a service after 5 minutes since boot is complete which is just fine but what do I need to add to get it also start at every noon.
Change the initial time of the setRepeating() call. The example shows one minute from now -- you would need to do the calculations to determine when the next noon is.
You can see an example of that sort of calculation in this OnBootReceiver from a different sample project. Here, I am setting up the alarm to go off every day at a user-specified time.

Categories

Resources