I am trying to set two alarms which will run two different background services. I set the alarm inside the onCreate method of my activity class. But the problem is that the service classes which are extending IntentService are not getting called, i.e. their method onHandleIntent() is not getting called. This is how I set my alarms
//Creating alarm for showing notifications.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
//create an alarm for today if there is still time else schedule alarm for tomorrow.(Handled inside the one time alarm class).
//FIRST ALARM..............
Intent intent = new Intent(ActionBarTabActivity.this, ScheduleOneTimeAlarmForToday.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
//SECOND ALARM.............
Intent i = new Intent(ActionBarTabActivity.this,RemoteNotificationService.class);
PendingIntent pi = PendingIntent.getService(getApplicationContext(), 111, i, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(), 1000 * 60, pi);
I have declared the services inside the minifest file as below
<service android:name="com.nss.common.services.ScheduleOneTimeAlarmForToday" />
<service android:name="com.nss.common.services.RemoteNotificationService" />
Also the alarms run properly on my old samsung phone but when I test it on my new Asus Zenfone or any other new phone, it doesn't show up.
Edit:
My logcat shows this:
10-19 12:25:05.605 634-744/? V/AlarmManager﹕ triggered: flg=0x10000000 cmp=com.nss.zobbers/com.nss.common.services.ScheduleOneTimeAlarmForToday Pkg: com.nss.zobbers
10-19 12:25:06.846 634-744/? V/AlarmManager﹕ triggered: cmp=com.nss.zobbers/com.nss.common.services.RemoteNotificationService Pkg: com.nss.zobbers
So I don't get it, my alarm is triggered but the service it needs to call doesn't get called? I have tried many posts but couldn't find the error. Please help, thanks in advance.
I made it to work, but I won't accept it as my answer as maybe someone will tell the exact reason why it doesn't work. Well instead of directly calling services via alarmManager, I modified my code to call a broadcast receiver which then calls the respective service. Now it seems to work perfectly on different devices.
Related
Following code works perfectly for Activity:
Intent intent = new Intent(context, MyActivity.class);
PendingIntent operation = PendingIntent.getActivity(context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
However, when I do the same thing for IntentService, It works only if startTime and time I set alarm are on the same day. e.g. If I set the alarm today for 5 PM, it will be executed but when I set the alarm today for 5 PM tomorrow, it will not be executed. If this was Activity then it works for both cases.
Intent intent = new Intent(context, MyService.class);
PendingIntent operation = PendingIntent.getService(context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
How to solve this?
The goal here I am trying to achieve is to execute IntentService every day at the exact time.
The goal here I am trying to achieve is to execute IntentService every day at the exact time.
Google has made this progressively harder from release to release. See Android AlarmManager setExact() is not exact. There could be two ways to solve this for your case:
you start an activity, which starts the service (as starting an Activity seems to work for you)
you use either setExactAnd... or setAlarmClock. setAlarmClock also triggers in the new "doze" mode, see https://stackoverflow.com/a/47049705/1587329.
Another way would be to re-think why and if you really need this... or if a JobScheduler could not fit your purpose more easily.
add replace your line with this line :
alarmmanager.setRepeating(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
it will repeat on specific interval you set in alarm manager
Replace the AlarmManager with this code:
alarmManager.setRepeating(AlarmManager.RTC,
timeMills,
AlarmManager.INTERVAL_DAY,
pendingIntent);
Worked for me.
HERE IS a DETAILED ANSWER check link in the bottom for more details.
Hope this will help. Your issue can be probably related to android versions too so do check the link for more details
app gets an instance of the AlarmManager and sets an alarm using a PendingIntent. More on usage and setting alarms is coming in the next section. The AlarmManager is the app side interface to the backing AlarmManagerService. It abstracts the details of the Binder interface, used to communicate with the system process (system_server) hosting the AlarmManagerService. These two components manage the alarm(s) the app has set and will send the PendingIntent correctly. This manager/service architecture is used throughout Android framework and is done for security and isolation purposes. The system_server process is running with privileges which normal apps do not have. If you are unfamiliar with Android’s use of permissions, see this article for more details on app processes and user IDs. These extra permissions are what allows system_server to access the underlying kernel alarm driver. The alarm driver is what manages setting alarms to wake up the device regardless of the sleep state of the SoC.
When the alarm is triggered the device is awakened (if asleep) and the AlarmManagerService is notified of an alarm expiring. It will then send the PendingIntent accordingly. This will cause the appropriate component within MyApp to be activated. If MyApp has not been started or its process is not cached, it will be started so the component can be activated.
basic usage will be as
public class MyActivity extends Activity {
...
private AlarmManager mAlarmMgr;
...
public void onCreate(Bundle savedInstance) {
...
mAlarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
...
}
...
}
let’s create a PendingIntent for our MyActivity using the component name.
Intent alarmIntent = new Intent(context, MyActivity.class);
PendingIntent pend = PendingIntent.getActivity(context,
0,
alarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Now that we have our PendingIntent and the AlarmManager, we can set our alarm so our Activity is triggered when the alarm has expired. To do this, we need to figure out when we want our alarm to go off and whether it should wake up the device or just be delivered the next time the device is awakened. Remember, we have two different ways of specifying time for our alarms: elapsed time or calendar (RTC) time. So our options are ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC or RTC_WAKEUP. The _WAKEUP variants are our “aggressive” alarms where we want the device to come out of low power to call our app back. For our sample app, let’s set this up in a custom BroadcastReceiver and have it trigger our Activity about 30 seconds after the device is booted
public class MyBootReceiver extends BroadcastReceiver {
public void onReceive(Context, context, Intent intent) {
...
AlarmManager alarmMgr =
(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
long wakeTime = SystemClock.elapsedRealtime() + 30000;
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeTime, pend);
}
}
Now when our device boots and the BOOT_COMPLETED broadcast is sent, our app’s process will be started and our receiver will set an alarm to trigger our Activity to be launched about 30 seconds later. Note that on Android 3.1 devices or newer, you must first manually launch your app before the BOOT_COMPLETED.
CREDIT GOES to writer of this BLOG
if you want to set the repeated alarm using SetExact you are bound to stop all other pending intents on the same time check this link for that here are many examples of how to do it! again credit goes to this writer
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
calendar.set(Calendar.HOUR_OF_DAY, 1);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context,MyClass.class),PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 7*24*60*60*1000, pi);
I have this simple pending repeating alarm and it works just fine only when system android alarm is not set up. It doesnt matter on what time alarms are set in system Alarm app, looks like this system app stops all my pending intents. Any idea how to debug this? What can cause this problem ?
I would like to use it in paralel with system alarms.
make sure you have permission
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
For Debugging:
override onNewIntent() in your activity MyClass Activity like this:
#Override
onNewIntent(Intent intent){
android.os.Debug.waitForDebugger();
if(intent.hasExtra("alarm")){ //Put a break point here
Log.d("Alarm fired","yes");
}
}
Create you PendingIntent for firing alarm like this:
Intent intent=new Intent(context,MyClass.class);
intent.putExtra("alarm","yes");
PendingIntent pi = PendingIntent.getService(context, 0, intent,0);
So, when your alarm gets fired, control will come to onNewIntent and wait for you to attach a debugger. That time go to Attach debugger button in android studio and attach debugger to your application. And this is how you will know that you alarm has been fired.
I'm looking for a solution for days now. There might not even be a solution.
What happens is the following:
I got an application which schedules alarms for users, for the user to get out of bed. It's really important that the alarms "always" go off.
To be able to let the alarms go off I make use of an AlarmManager. This schedules intents to be executed on scheduled times. This works fine when the Application is open or closed with the back/home button.
When I close the app with Force Close option, the Alarm Manager alarms get cleared from the system and they will not go off.
I have tried the following things already:
START_STICKY Service
DefaultUncaughtExceptionHandler - Won't work, because there isn't an exception caught for force closing the app.
Broadcast Receiver - The issue is with the alarms being deleted.
I'm wondering if anyone has experienced the same issue with the AlarmManager class and if you found a solution or alternative to fix this problem.
p.s. I'm creating the Alarm Manager alarms like this:
Intent myIntent = new Intent(getApplicationContext(), CheckAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(),
1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getApplicationContext().getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
int daysTillAlarm = AlarmHelper.calculateDaysTillAlarm(alarm);
calendar.add(Calendar.DATE, 0);
calendar.set(Calendar.HOUR_OF_DAY, 15);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
EDIT:
To try and see if I wasn't the only one with the issue, I downloaded some well used alarm clocks. They all seem to have the same behavior as I do. For now I'll leave it be. They're also well rated.
Still if you might have the solution to this problem I'd like to know!
Try changing you code:
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(),
1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
to:
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(),
1, myIntent, 0);
Also try adding:
alarmManager.cancel(pendingIntent);
before:
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
From my point of view (as Android user) this is right behavior. Imagine application which has bug leading to crash (with crash dialog), and this application scheduled some action to be started every minute. What can you do with crash dialog appearing every minute?
So I hope there is no direct answer to your question (like "just call this method").
As always, there are ugly ways - like starting several processes which track all others and restart if needed, but then your application starts to look like virus...
I'm usign an Alarm Manager to update a widget with a Service. I've two different questions.
First question: I'm calling the service with Alarm Manager's intent. Like this:
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyService.class);
pi = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
context.startService(new Intent(context, MyService.class));
Long repeat = Long.parseLong(prefs.getString("update_preference", "600"));
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), 1000*repeat, pi);
Is it wrong?
It looks and works right. But when I have looked at working services, I can't see my service name in the list. Perhaps it's not running as a single/seperate service. Just saw application name (not as a service). I'm not sure how to seperate or does it matter?
Another question: Over long time, running application, which controls widgets update, is closed somehow (manually or by a task killer). Of course Alarm Manager gonna stop and widget's functions gonna stop too. For example button clicking.
But, Twitter solved this problem. While the widget is active, if I close the main application (Twitter) -which controls widget- than click the widget, somehow widget triggering application and it starts again well. So buttons work properly. How is that possible?
Any help would be appreciated.
You dont need to do context.startservice that what the pending intent is for, if you want the service to run right away the first time just set it to run at the current time then set the interval from the current time.
You are also setting 2 different types of repeating when you don't need to setRepeating is strict where setInexact is not and can be adjusted by the OS when it gets fired hence the inexact in it. You want one or the other not both.
Also those intervals are very small and its going to kill the battery significantly.
It should just be this
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyService.class);
pi = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Long repeat = Long.parseLong(prefs.getString("update_preference", "600"));
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
Calendar.getInstance().getTimeInMillis(), 1000*repeat, pi);
It's good that your application/service isn't running all the time.
In fact it doesn't need/has to run all the time for updating a widget. If you schedule an Intent with AlarmManager the application will be started when the intent is fired if it has been closed.
This works fine:
Intent intent = new Intent(HelloAndroid2.this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(HelloAndroid2.this, 0,
intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (12 * 1000), pendingIntent);
This doesn't work. I hear the alarm only time.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (12 * 1000), 3 * 1000, pendingIntent);
I have also tried this, no luck:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 5);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 7000, pendingIntent);
What is the problem?
From the PendingIntent doc for FLAG_ONE_SHOT:
this PendingIntent can
only be used once. If set, after
send() is called on it, it will be
automatically canceled for you and any
future attempt to send through it will
fail.
So after the pendingIntent is fired the first time, it will be cancelled and the next attempt to send it via the alarm manager will fail
Try using FLAG_UPDATE_CURRENT
Looking at your code samples in order:
In your first sample you are using AlarmManager.set - this is strictly for one-off alarms so yes, it will only fire once. If you want to use AlarmManager.set then the last thing the code triggered should do is to set a fresh alarm (which should also use a fresh PendingIntent).
In your second example you are using a repeating alarm. You do not need to create a fresh PendingIntent each time this fires as the OS takes care of the repeating aspect of the alarm.
There is no reason why your alarm should not repeat every 3 seconds, so I would start looking at the BroadcastReceiver implementation you have written to handle the alarm.
Check that you've implemented it properly. Comment out all the code in the onReceive() method and instead just have it writing a log message. Once you see your log message appearing in the logcat every time the alarm fires, add your code back in (keeping the log message), and another log message to the end of the method. This allows you to see how long the method takes to execute - you want it to be finished before the alarm fires again to avoid any unexpected side effects.
As an aside, if you want a repeating alarm, android.os.Handler is a much more efficient approach although alarms set through AlarmManager do fire very accurately.