dynamic alarm manager at midnight - android

my mean goal is to run a task periodically at midnight (00:00:00)
but the user can set the period based on the interval (daily, weekly , monthly)
let's assume that this job is a backup Scheduling.
this task will triggred at midnight but based on the user preference (midnight everyday, every week , or monthly ), and if the phone was in the doze mode or even off , wait untill the next start and start backup.
when i start implementing the code , i started with JobService and JobScheduler , but unfortunately i learned that i can set the repetitive but i can't set the exact time, so the last solution was to work with alarmmanager.
i use this code for triggering the alarm :
public static void setTheTimeToStartBackup(Context context,String periode) {
int DATA_FETCHER_RC = 123;
AlarmManager mAlarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
Intent intent = new Intent(context, BackUpAlarmRecevier.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, DATA_FETCHER_RC,intent, PendingIntent.FLAG_UPDATE_CURRENT);
long interval = 0;
switch (periode){
case "never":
return;
case "daily":
alarmStartTime.set(Calendar.HOUR_OF_DAY, 0);
interval = AlarmManager.INTERVAL_DAY;
break;
case "weekly":
alarmStartTime.set(Calendar.DAY_OF_WEEK, 1);
interval = AlarmManager.INTERVAL_DAY*7;
break;
case "monthly":
alarmStartTime.set(Calendar.WEEK_OF_MONTH, 1);
interval = AlarmManager.INTERVAL_DAY*30;
break;
}
alarmStartTime.set(Calendar.HOUR_OF_DAY, 0);
alarmStartTime.set(Calendar.MINUTE, 0);
alarmStartTime.set(Calendar.SECOND, 0);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),interval, pendingIntent);
Log.e("Alarm","Set for midnight");
}
this is my receiver :
public class BackUpAlarmRecevier extends BroadcastReceiver {
SharedPreferences preferences;
#Override
public void onReceive(Context context, Intent intent) {
Log.e("BackUpAlarmReciver","Triggred");
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG:APP");
wl.acquire();
sendNotification(context);// simple notification...
Toast.makeText(context, "Alarm !!", Toast.LENGTH_LONG).show();
startBackupProcess();
wl.release();
}}
the problem is task never start.
so i went to test it with less time interval (15min as the minimum possible as i read ), so i change my first function setTheTimeToStartBackup to this :
public static void setTheTimeToStartBackup(Context context,String periode) {
int DATA_FETCHER_RC = 123;
AlarmManager mAlarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 55);
Intent intent = new Intent(context, BackUpAlarmRecevier.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, DATA_FETCHER_RC,intent, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
Log.e("Alarm","Set for midnight");
}
and exactly the same problem , nothing started, no log , no notification , nothing.
and i already set the Receiver in my manifest with all permission like that :
<receiver android:name=".job.BackUpAlarmRecevier"
android:enabled="true"
android:process=":remote"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
what im doing wrong in both cases ? and if it work , this code will persist for ever or i need to set it again each time ?
thanks :)
EDIT:
i call my function setTheTimeToStartBackup in the MainActivity.

You could set it to occur at midnight if you did the appropriate time calculations. Dynamically get the current time and date, calculate when to register the broadcast for the alarm manager. Customize the onReceive method to set another alarm at 12pm again.
Either way you can trigger a broadcast receiver by registering your receiver manually.
Broadcast receiver class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Alarm received!! ");
// Register alarm again here.
}
}
Code to register a receiver with a custom intent filter.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlarmManager mAlarmManager = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
getApplicationContext().registerReceiver(new AlarmReceiver(), new IntentFilter("AlarmAction"));
PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, new Intent("AlarmAction"), 0);
// Add dynamic time calculations. For testing just +100 milli.
mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 100, broadcast);
;
}
You could achieve what you wanted through a background service.

My suggestion would be to turn the problem around a bit.
Create three topics on Firebase (daily, weekly, monthly). Subscribe users to appropriate topics. Have a Firebase function that is triggered by CRON job which sends the data notification down to the device, this data notification should schedule one-time WorkManager job for the update. This way you can control everything from server-side, if the phone is off, it will still execute as soon as it turns on and you don't need to manually take care of catching the Boot completed with alarm manager etc.

Related

AlarmManager fires late or doesn't fire at all

Hi everybody I'm trying to learn how to use AlarmManager and BroadcastReceiver in Android.
I'm having some problems with the AlarmManager:
I'm setting two alarms at 1 minute distance, but only one fires and it is some minutes late (not predictable i guess).
Here's my main activity (i'm setting Alarms by tapping a button)
public class MainActivity extends AppCompatActivity {
AlarmManager alarmManager;
Intent intent;
PendingIntent pendingIntent;
AtomicInteger atomicInteger;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
intent = new Intent(Constants.EXTENDED_DATA_STATUS);
atomicInteger = new AtomicInteger();
setContentView(R.layout.activity_main);
Button startButton = (Button) findViewById(R.id.start_button);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int id = atomicInteger.incrementAndGet();
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),id,intent,0);
Calendar firstLullo = Calendar.getInstance();
Calendar secondLullo = Calendar.getInstance();
firstLullo.set(Calendar.HOUR_OF_DAY,10);
firstLullo.set(Calendar.MINUTE,55);
secondLullo.set(Calendar.HOUR_OF_DAY,10);
secondLullo.set(Calendar.MINUTE,56);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP,firstLullo.getTimeInMillis(),pendingIntent);
alarmManager.setExact(AlarmManager.RTC_WAKEUP,secondLullo.getTimeInMillis(),pendingIntent);
}
Log.d("ALARM","settato con id " + String.valueOf(id));
}
});
}
}
My Receiver simply shows a Toast and makes the phone vibrate.
Constants.EXTENDED_DATA_STATUS is a string from a Constants class and it's added to the intent-filter of my Reveiver in the Android Manifest.
What am i missing? I googled a lot and only found that i have to use setExact() but no luck..
Thanks in advance
The reason why only one fires is because your canceling your first one always
From the docs: If there is already an alarm scheduled for the same IntentSender, that previous alarm will first be canceled.
To fix this, use different PendingIntents for both alarms.
- To let your receiver fire multiple times, reschedule it in your onReceive()
Example:
Only if u want two receivers apart from eachother!
//Declare AlarmManager
AlarmManager am = (AlarmManager) LayoutActivity.this.getSystemService(ALARM_SERVICE);
//create new calendar instance for your first alarm
Calendar startTime= Calendar.getInstance();
//set the time of your first alarm
firstLullo.set(Calendar.HOUR_OF_DAY,10);
firstLullo.set(Calendar.MINUTE, 55);
firstLullo.set(Calendar.SECOND, 0);
//create a pending intent
PendingIntent firstPI = PendingIntent.getBroadcast(yourActivity.this, 0, new Intent("yourFirstAlarmReceiver"), PendingIntent.FLAG_UPDATE_CURRENT);
//schedule time for pending intent, and set the interval to day so that this event will repeat at the selected time every day
am.setRepeating(AlarmManager.RTC_WAKEUP, firstAlarm.getTimeInMillis(), firstPI);
//----------------------------------------------------
//create new calendar instance for your second alarm
Calendar endCalender = Calendar.getInstance();
//Set the time alarm of your second alarm
secondLullo.set(Calendar.HOUR_OF_DAY,10);
secondLullo.set(Calendar.MINUTE,56);
secondLullo.set(Calendar.SECOND, 0);
//create a pending intent to be
PendingIntent secondPI= PendingIntent.getBroadcast(yourActivity.this, 0, new Intent("yourSecondAlarmReceiver"), PendingIntent.FLAG_UPDATE_CURRENT);
//schedule time for pending intent, and set the interval to day so that this event will repeat at the selected time every day
am.setRepeating(AlarmManager.RTC_WAKEUP, secondLullo.getTimeInMillis(), secondPI);
Register alarms in Manifest.XML:
<receiver android:name="firstAlarm" >
<intent-filter>
<action android:name="yourFirstAlarmReceiver" >
</action>
</intent-filter>
</receiver>
<receiver android:name="secondAlarm" >
<intent-filter>
<action android:name="yourSecondAlarmReceiver" >
</action>
</intent-filter>
</receiver>
Now u can call your alarms with:
First Alarm:
public class yourFirstAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Do something when first alarm goes off
}
}
Second Alarm:
public class yourSecondAlarmReceiverextends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Do something when second alarm goes off
}
}
Should help u out.
Yes, of course the above code will trigger only one Alarm, because you are setting same id for both alarms.
Alarm are identified and differentiated by their id in pendingintent.
Use different id for different alarms
Update Code:
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1234 ,intent,0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP,firstLullo.getTimeInMillis(),pendingIntent);
pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 5678, intent,0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP,secondLullo.getTimeInMillis(),pendingIntent);

How to keep a service alive using AlarmManager.setInexactRepeating()?

I have some existing code that spawns a service intent which does a bunch of stuff in the background. This code does work...
Intent serviceIntent = new Intent(context, APMService.class);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(serviceIntent);
My question is: how to change this to use the AlarmManager.setInexactRepeating(...) methods?
I have changed the above code to this:
Intent serviceIntent = new Intent(context, APMService.class);
serviceIntent.putExtra("STARTED_BY", starter);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//Set up recurring alarm that restarts our service if
// it crashes or if it gets killed by the Android OS
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, serviceIntent, 0);
//am.cancel(pi);
am.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP //wake up the phone if it's asleep
, cal.getTimeInMillis()
, 10000
, pi);
And I have added these permissions to AndroidManifest.xml...
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="com.android.alarm.permission.WAKE_LOCK"/>
My understanding is that this is supposed to start the service immediately and then try to restart it again every 10 seconds. But this code isn't working properly.
Using this new code, the service never starts at all and I cannot see why not. To complicate matters the debugger never seems to attach to the app in time to see what's going on.
Can anyone see what I'm doing wrong?
Put AlarmManager code under onDestroy() function of service to schedule start of service as below:
#Override
public void onDestroy() {
/**
* Flag to restart service if killed.
* This flag specify the time which is ued by
* alarm manager to fire action.
*/
final int TIME_TO_INVOKE = 5 * 1000; // try to re-start service in 5 seconds.
// get alarm manager
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AutoStartServiceReceiver.class);
PendingIntent pendingIntent = PendingIntent
.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// set repeating alarm.
alarms.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() +
TIME_TO_INVOKE, TIME_TO_INVOKE, pendingIntent);
}
And handle starting of your service in AutoStartServiceReceiver as below:
public class AutoStartServiceReceiver extends BroadcastReceiver {
private static final String TAG = AutoStartServiceReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
// check broadcast action whether action was
// boot completed or it was alarm action.
if (intent.getAction().equals(AppConstants.ACTION_ALARM_INTENT)) {
context.startActivity(new Intent(context, YourActivity.class));
// handle service restart event
LockerServiceHelper.handleServiceRestart(context);
}
}
}
Kindly note that, your service will not restart if you stop it manually from settings-apps-running apps-your app.
Your service is not starting because of AlarmManager.ELAPSED_REALTIME_WAKEUP, while it should be using AlarmManager.RTC_WAKEUP
If you want to run every 10s keep in mind that above API 21 alarm intervals below 60s are rounded up to 60s.
Also, consider using WakefulIntentService
https://github.com/commonsguy/cwac-wakeful

Android: setting an alarm clock from a broadcast receiver only works once

I'm making an android app to be used to help recover a lost phone. The app uses a Service that is constantly running and when a text message (SMS) is received by the phone, a BroadcastReceiver's (already registered in the service) onReceive() event is triggered. The functionality that I want is that the BroadcastReceiver be able to make the phone produce a loud noise even if the phone was on silent. The most logical way I can think of doing this is to use and alarm clock set one minute from the current time.
This is the code I'm currently using inside of the broadcast receiver:
Calendar c = Calendar.getInstance();
Intent alarmIntent = new Intent(AlarmClock.ACTION_SET_ALARM);
alarmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
alarmIntent.putExtra(AlarmClock.EXTRA_MESSAGE, "Polo!");
alarmIntent.putExtra(AlarmClock.EXTRA_HOUR, c.get(Calendar.HOUR_OF_DAY));
alarmIntent.putExtra(AlarmClock.EXTRA_MINUTES, c.get(Calendar.MINUTE) + 1);
context.startActivity(alarmIntent);
Fortunately, this code works, but it only ever works once. But that I mean, the first time this code is run, the phone's flow is interrupted and the clock app is opened with a new alarm set. When you attempt to do this again, the clock app is opened, but no alarm is set. I have to restart my phone to get this to work again.
From what I can tell, the issue has to do with the clock app and I need to restart the clock app to get my service to work. This is a really sketchy solution, but I don't know what else to do.
Any recommendations?
The trick is to develop your own Alarm screen and re-set the alarm while onCreate.
Like that, your app will continuously ring up.
for that :
initialise a WakefulBroadcastReceiver
manifest.xml
<receiver android:name="com.mycompany.myapp.AlarmManagerBroadcastReceiver"></receiver>
AlarmManagerBroadcastReceiver.java
public class AlarmManagerBroadcastReceiver extends WakefulBroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Calendar c = Calendar.getInstance();
Intent alarmIntent = new Intent(context, MyAlarm.class);
alarmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
alarmIntent.putExtra(AlarmClock.EXTRA_MESSAGE, "Polo!");
alarmIntent.putExtra(AlarmClock.EXTRA_HOUR, c.get(Calendar.HOUR_OF_DAY));
alarmIntent.putExtra(AlarmClock.EXTRA_MINUTES, c.get(Calendar.MINUTE) + 1);
context.startActivity(alarmIntent);
}
}
MyAlarm.java :
public class MyAlarm extends Activity{
#Override
public void onCreate(Bundle savedInstanceState){
// doing UI stuff
AlarmUtil.setAlarm(this);
}
}
AlarmUtil.java
public class AlarmUtil {
#SuppressLint("NewApi")
public static void setAlarm(Context context){
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
int requestCode = 1234;
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
am.setExact(AlarmManager.RTC_WAKEUP, 60 * 1000, pi);
}
else{
am.set(AlarmManager.RTC_WAKEUP, 60 * 1000, pi);
}
}
}

AlarmManager Not called next day if the app sleeps for abt 1 day

I am developing an android app which shows a notification every 12 hour if the time is saved in the database. So everytime a data is entered or edited in the database ,I cancel the current alarmmanager and start a fresh new one so that I dont miss one. Also on reboot I have called the alarmmanager. On the broadcast receiver, the database is checked for entry and if found a notification is set and the app is opened automatically.
So when I test the app by changing the date manually,the app works as expected.Also on reboot the app works.But if I keep the app idle for nearly 14 hours,the notification is not set ,but if I open the app and suspend it the notification is set after that.
This is how I call the alarmmanager.
Intent alarmintent = new Intent(context, package.Alarm_Manager.class);
alarmintent.putExtra("note","Notify");
sender = PendingIntent.getBroadcast(context , 0 , alarmintent , PendingIntent.FLAG_CANCEL_CURRENT | Intent.FILL_IN_DATA);
alarm_manger = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarm_manger.cancel(sender);
Calendar cal = Calendar.getInstance();
long now = cal.getTimeInMillis();
alarmintent = new Intent(context, package.Alarm_Manager.class);
alarmintent.putExtra("note","Notification");
sender = PendingIntent.getBroadcast(context , 0 , alarmintent , PendingIntent.FLAG_CANCEL_CURRENT | Intent.FILL_IN_DATA);
alarm_manger = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm_manger.setRepeating(AlarmManager.RTC_WAKEUP, now, AlarmManager.INTERVAL_HALF_DAY, sender);
This is the broadcast receiver
#Override
public void onReceive(Context context, Intent intent)
{
NotificationManager manger = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Calendar cal = Calendar.getInstance();
date = (int)(cal.getTimeInMillis()/1000);
Notification notification = new Notification(R.drawable.vlcsnap_396460 , "Notify" , System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
notification.setLatestEventInfo(context, "App", "Notify" , contentIntent);
notification.flags = Notification.FLAG_INSISTENT;
manger.notify( 0 , notification);
}
You don't need to call alarm_manager.cancel(sender); if you set the PendingIntent.FLAG_CANCEL_CURRENT.
Your call to
alarm_manger.setRepeating(AlarmManager.RTC_WAKEUP, now, AlarmManager.INTERVAL_HALF_DAY, sender);
will trigger the alarm right away, since the now is already passed when you set the alarm.
I suggest you use
now + DateUtils.HOUR_IN_MILLIS / 2
for the triggerAtMillis parameter
Did you tried to schedule it for smaller interval? Does it get triggered ?
After having seen your Alarm_Manager code, I think it is illegal to do this in your BroadcastReceiver object directly. Quote:
If this BroadcastReceiver was launched through a tag, then the object is no longer alive after returning from this function.
I believe there is no other way than to create a Service which is informed by your BroadcastReceiver, and make sure that the Service calls setLatestEventInfo() with itself (this) as the Context.
The reason why your asynchronous Broadcast fails while it works when your app is running is probably that the Context provided to the BroadcastReceiver lives only for the duration of the call to the BroadcastReceiver when your app does not run. So the Notification service, which only runs after your BroadcastReceiver has died along with the temporary context, is missing a valid context.
When your app runs, the Broadcast probably comes with your Activity or Application object as Context, and this is still vaild when the Notification manager runs.
Hope this helps.
Update: An `IntentService`` will do. You don't want a full time Service for that.
Update 2: Some snippets.
<service android:name=".MyIntentService" android:label="#string/my_intent_service_name" />
public final class MyIntentService extends IntentService {
public MyIntentService() {
super("service name");
// set any properties you need
}
#Override
public void onCreate() {
super.onCreate();
// do init, e.g. get reference to notification service
}
#Override
protected void onHandleIntent(Intent intent) {
// handle the intent
// ...especially:
notification.setLatestEventInfo(this, "App", "Notify" , contentIntent);
// ...
}
}
public final class MyAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, MyIntentService.class));
}
}

Display alertDialog on alarm?

I would like to display an alert dialog when the alarm goes off. Here is where i am so far. Im not sure if im doing it right.
#Override
void doTaskWork(Intent intent){
String taskId = intent.getStringExtra(TaskHelper._id);
NotificationManager mgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(this, TaskDetails.class);
notificationIntent.putExtra(TaskHelper._id, taskId);
PendingIntent pi = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT);
Notification note = new Notification(R.drawable.stat_sys_warning, );
}
}
Alarm:
You can schedule a pending intent that drives what you want when the alarm fires. The process is:
Determine how often you want the alarm to fire. You can fire at an exact time, a specific time from now (in 10 seconds..), or a specific repeat at an interval (every x seconds/minutes/etc.). You can also set a specific time to start the repeat process. The interval isn't variable. Then you have to do one shots and set another alarm for the next time. You can also set flags that determine the time format (millis, RTC, ...). Finally, you can have the alarm firing wake up the device or let it sleep and get scheduled the next time the phone is awake.
Now, as to what is scheduled. A pending intent is scheduled. The pending intent wakes up a broadcast receiver. Here's some clips of code I use to fire a timer at 1 minute past midnight daily. (It updates a widget that has to update daily.)
Intent intent = new Intent(context, DaysReceiver.class);
PendingIntent receiverIntent = PendingIntent.getBroadcast(context,
DaysConstants.UPDATE_ALARM,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Schedule the alarm!
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(receiverIntent);
if (cancelAlarm) {
MyLog.d(TAG, "setAlarm cancel");
return;
}
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
JodaTime jtime = new JodaTime();
am.set(AlarmManager.RTC_WAKEUP, jtime.afterMidnight(), receiverIntent);
//am.setRepeating(AlarmManager.RTC_WAKEUP, jtime.nowPlusMillis(30 * 1000),
// 30 * 1000, receiverIntent);
MyLog.d(TAG, "setAlarm set");
}
The JodaTime class does date and time calculations. the afterMidnight() bit above returns 1 minute after midnight tonight. The routine can be used to just cancel an outstanding alarm.
The receiver is just a normal broadcast receiver and you can do anything in it that you can do in any other broadcast receiver. (Don't forget to put the usual stuff in the manifest. Permissions, and such like.
Here's the receiver I'm using less the imports. It's pretty straight forward. It grabs all the widgets that are on home screens and updates them. The update routine is a static function in the widget provider. It's a class because it is driven from two places. The widget config and the widget provider. The timer is rescheduled every 24 hours. The alarm won't live through a boot, but the provider's on update is driven at reboot. (All that's happening is the new day calculations are performed and the widget display is updated.) You could drop my code and put in a startActivity.
Ooops. Almost forgot. Use PendingIntent.FLAG_UPDATE_CURRENT so you don't have multiple intents stacked up accidentally...
public class DaysReceiver extends BroadcastReceiver {
static String TAG = "DaysReceiver";
#Override
public void onReceive(Context context, Intent intent) {
MyLog.d(TAG, "onReceive");
updateWidgets(context);
}
private void updateWidgets(Context context) {
MyLog.d(TAG, "updateWidgets");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName componentName = new ComponentName(context, DaysProvider.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(componentName);
final int N = appWidgetIds.length;
if (N < 1) {
MyLog.d(TAG, "No widgets");
return;
}
for (int i = 0; i < N; i++) {
MyLog.d(TAG, "Update widget " + Integer.toString(appWidgetIds[i]));
DaysProvider.updateAppWidget(context, appWidgetManager, appWidgetIds[i]);
}
}
}
Hope I haven't rambled to much, but I'm in a rush to get back to some other business. I don't have the time to really edit the post. Hope this helped...
Do you really need a notification? Why not fire off an activity that can do the alarm notification and disappear. You can sound an alarm, vibrate the phone, whatever. Even do a notification if you still want to...
Intent intent = new Intent(context.MyAlarmResponse);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("REASONFORALARM", "What ever you want");
context.startActivity(intent);
In the manifest, use the following theme to look like a dialog:
<activity android:name=".MyAlarmResponse"
android:theme="#android:style/Theme.Dialog">
</activity>
It doesn't have to look like a dialog. You can do a full court press with a full screen display, animation, vibrate, and sound. The user than hits your cancel key and it all goes away.

Categories

Resources