How to cancel alarms? - android

I have the following situation.
I need to set many alarms to start the same Activity at different specific dates.
In order to accomplish this, I obviously use an AlarmManager.
Since the PendingIntents given to the AlarmManager are all equivalent, in order to have Android create all of them (and not just 1) I use a different requestCode to differentate among them.
All of this works fine, all alarms are created correctly.
The point is that sometimes I have to cancel them!
If I do not do it with the same requestCode the AlarmManager does not cancel them.
It is very difficult to retrieve the original requestCode in the code, since they are created at runtime at different moments/days...
Any suggestion on how to address this situation?

You have the right approach, as the only way I know to cancel the alarms would be cancel the pending intents with the same requestCode, however your issue is retrieving the same request codes made at run time. You would have to store these codes some how either by SQLite, or shared preferences perhaps to have them stored on the device then retrieve them as needed. Alternatively you could pass the requestCode as a bundle in the intent and then cancel it immediately after it fires off, or when ever through the alarms life cycle you choose. Hope this helped a bit.

Related

Keeping track of multiple requestCodes

I'm creating an app which copies the functionality of the default alarm app. I'm storing all of the user's entries (alarms) in a Room database (to display all of my alarms in a RecyclerView). Whenever I store an entry, I set an alarm using the AlarmManager.
How do I make sure that the user can edit an alarm which is already set?
As I understand, I need to create an identical PendingIntent (which includes also the same requestCode and then use the cancel method).
I want to use the rowIds from the DB as requestCodes for the alarm.
How do I make sure that when the user modifies an alarm I have access to the corresponding rowId?
Of course, I can make DB queries to get back the rowId based on the other properties which I save in the TextViews from the RecyclerView (title, description, date), but is there a better way?
Should I also save the rowId in an invisible TextView (for easy access to the data)?
The answer to a somewhat similar question posted here was to set an alarm only when a previously set alarm fires. I don't think this is a solution since I can have multiple alarms which need to be triggered at the same time.
Also, please help if you know a better method.

how to call certain method of activity via appwidget

i'm trying to call a method in my main activity via a button of a widget.
the widget has different buttons with different values. i want the method to do its job without showing up the gui attached to the main activity. (send http request with button value)
so far i searched for some tutorials but i didn't quite understand them, my code got all clumsy and it barely worked. i think a mix of intents, services and broadcasts are needed to realize this?! i really don't know, can somebody post a understandable description or tutorial which covers all aspects of how to do this?
i think there is no code or pictures to provide because there is nothing look at right now.
thanks in advance for any answer.
Android AppWidgets don't need to have any relation at all to an Activity, although it is certainly possible to have a click or something start an activity.
As you probably know, the primary interface to AppWidgets is through your AppWidgetProvider (if you don't know what any of this is about, take a look at the official android guide).
You can tell a button to use a PendingIntent to do one of several things when clicked:
To start a service (probably your best option for time consuming tasks like http requests), using PendingIntent.getService.
To start an activity, use PendingIntent.getActivity.
To broadcast a message to a BroadcastReceiver, create it using PendingIntent.getBroadcast.
In all of these cases, you would tell the button to run the PendingIntent with the
setOnClickPendingIntent(int id, PendingIntent operation) method of RemoteViews.
The Intent you pass to any of these methods should typically be created using the Intent(Context, Class) constructor, where the second argument is the service, activity or receiver class you want the pending intent to be sent to.

how to retrieve the result code from a PendingIntent starting a service?

I have provide two objects of type PendingIntent to be passed to SmsManager.sendDataSms(). These two pendingIntents are used to trigger a service at a later time.
According to documentation:
this PendingIntent is
broadcast when the message is successfully
sent, or failed. The result code will be
Activity.RESULT_OK
The question is how can I retrieve this 'result code' inside my service?
Basically, except for Activity (through onActivityResult() or something), none of the application components has a mean to retrieve this 'result code' passed to different variations of PendingIntent.send().
First of all, at least in my head, a resultCode for service would not make much sense as it i suppose to be a self contained process. Again, that is just my perspective.
Secondly, the documentation of the getResultCode() for BroadcastReceiver says:
Retrieve the current result code, as set by the previous receiver.
which implies a dependency to an earlier receiver that Services does not have.
As I suggest in the comments to the question, I think the way to go would be to register a BroadcastReceiver inside the Service.
A final note to your comment:
However, I (and I'm sure lots of other people) still wanna know if there's a way of retrieving the result code from inside a service or not. If not, whay such a thing hasn't been explicitely mentioned in documentation?
The fact that the documentation does not state that you can get a resultCode in a Service is a good indication that it is not possible. Furthermore, it is fairly uncommon to document explicitly what some code cannot do.
I think you would retrieve the result code in the BroadcastReceiver and put it in a extra int or something in the intent and send it to the service through the startService.

WakefulIntentService Integration

I have a few questions regarding the WakefulIntentService implementation by CWAC:
1) Is it safe to use multiple WakefulIntentServices at the same time within my application?
2) Is it still ok to use my own code that handles AlarmManager? This would save me re-implementing my alarm handling code. Currently, I have a class with static methods and variables which are used by other classes within the application to set the alarm. My AlarmReceiver then starts the WakefulIntentServices by classing doWakefulWork().
This class is fantastic work!
Thanks
Is it safe to use multiple WakefulIntentServices at the same time within my application?
You should only need one. Use different Intent information (e.g., actions, extras) to distinguish the different commands.
I have not tried multiple distinct services -- while it is possible that it will work, I cannot guarantee it.
Is it still ok to use my own code that handles AlarmManager?
Oh, sure. Follow the "Basic Usage" instructions, calling sendWakefulWork() on WakefulIntentService when you want the work to be done. Just bear in mind that you must do that from a BroadcastReceiver's onReceive() if AlarmManager is the trigger -- that's an AlarmManager requirement.
This class is fantastic work!
I am glad that you like it!

Should I schedule an operation performed in an Android custom Application class onCreate() method?

I have an Android application which depends on the value returned by a webservice. This value changes only once a week. Clients should detect this changed value, but the exact time they detect this change is not really important, 12 to 24 hours later should be no problem.
My current implementation starts an IntentService in the onCreate() method of my custom Application class which retrieves the value from the webservice. I also persist the last retrieved value in the SharedPreferences, so the application does not have to wait until this value is retrieved.
Now my question is if it is necessary to schedule the retrieval of this value after it's first retrieval in the onCreate() method, lets say after 12 hours. I know the onCreate() method is called only once in the lifecycle of an application, but I do not know how likely it is an application will be terminated by the Android system. Is it reasonable to assume that the application will be terminated enough times so that scheduling is not necessary? And in the case I should schedule the operation, what will be the best way to achieve this?
If you used onCreate(), I don't think you'd have any guarantees that it would be called a second time. E.g. if the user plugs their phone in to charge, has go-to-sleep turned off and leaves your app running for days on end. Very unlikely, but not impossible.
If I were you I'd set up some sort of scheduled task. Maybe this link will help:
http://developer.android.com/resources/articles/timed-ui-updates.html
The example uses an OnClickListener to cancel the task.
OnClickListener mStopListener = new OnClickListener() {
public void onClick(View v) {
mHandler.removeCallbacks(mUpdateTimeTask);
}
};
You would want to put this elsewhere, in onDestroy() perhaps.
There are a couple of options, as I have had similar design challenges. Both have pros and cons.
Option A
You could have a splash screen, like many apps, and use the asyncTask class to make web requests and update your shared preferences. You could set a custom timeout so the app doesn't get stuck on the splash screen for too long. No matter what the result, if it updated or did not, you can then load what ever is in sharedPreferences and use that for app usage on that run.
The good thing about this is that every time the app starts you won't have to worry if the data is up to date or not, as you will just go and get it. For performance updates you could also store the last time the sharedPref value was updated (e.g. you got the value less than 12 hours ago) and therefore skip the web request - the result makes your splash screen quite quick to come and go.
Option B
You could use an Alarm via the AlarmManager, this is would be much better than a service which would be a unnecessary battery drain. There is even an enum for the interval of a day "INTERVAL_DAY". When the alarm is triggered a broadcast recevier will execute your custom code that would make the web request and get the values and store them. You can state if the Alarm repeats is a single use.
Hope that helps.
EDIT: there aren't the only options just the ones i picked out of relevance.

Categories

Resources