I start AlarmManager with PendingIntent and on few phones Alarm is not responding. On some devices is working ok on others it fails. I have made a few tests on different phones.
Nexus works ok, also Samsung Galaxy S4 zoom (4.2) works ok.
Samsung note 2 (4.3) works ok.
OPPO (4.4.4) alarm dies.
I have also implemented broadcast receivers which are working as they should on all devices.
Log.v(TAG, "START ALARM");
Intent intentAlarm = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 1000, 5000, pendingIntent);
Check whether the app is in stopped state.When the app is in stopped state it wont receive any alarm or events.
Also, I guess it might be OEM/manufacturer specific firmware/OS issue.To check whether the alarm has being actually schedule use adb shell dumpsys alarm and check whether your app alarm has being actually scheduled.
To check whether it is in stopped state use the following command:
adb shell dumpsys package "com.package.name" and check
"stopped=true"
To know more about stopped state refer:
Launch controls on stopped applications
Starting from Android 3.1, the system's package manager keeps track of
applications that are in a stopped state and provides a means of
controlling their launch from background processes and other
applications.
Note that an application's stopped state is not the same as an
Activity's stopped state. The system manages those two stopped states
separately.
The platform defines two new intent flags that let a sender specify
whether the Intent should be allowed to activate components in stopped
application.
FLAG_INCLUDE_STOPPED_PACKAGES — Include intent filters of stopped
applications in the list of potential targets to resolve against.
FLAG_EXCLUDE_STOPPED_PACKAGES — Exclude intent filters of stopped
applications from the list of potential targets. When neither or both
of these flags is defined in an intent, the default behavior is to
include filters of stopped applications in the list of potential
targets.
Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all
broadcast intents. It does this to prevent broadcasts from background
services from inadvertently or unnecessarily launching components of
stoppped applications. A background service or application can
override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES
flag to broadcast intents that should be allowed to activate stopped
applications.
Applications are in a stopped state when they are first installed but
are not yet launched and when they are manually stopped by the user
(in Manage Applications).
Please note stopped state is different from app process not running.
There could be a couple of different issues at work here:
The type of alarm you are requesting (ELAPSED_REALTIME) will not wake up the device to deliver the alarm. Instead, if it expires while the device is sleeping it will be delivered the next time the device wakes.
The triggerAtMillis value of 1000 is requesting the first alarm at 1 second after boot of the device. If the device has already been up and running and you request this alarm, the first alarm may not fire and could cause the subsequent ones to not get scheduled. This is just a guess, I've not verified by looking at the 4.4.4 AOSP sources
The alarm handling was changed in API 19 (Android 4.4) to handle collating of alarm timers (all are inexact by default) and this change could have affected things for the 2nd bullet. You might try changing the triggerAtMillis value to be (SystemClock.elapsedRealtime() + 1000)
Note that if you need the device to wake from sleep, you'll need to use a _WAKEUP alarm variant and also have your BroadcastReceiver take a wake lock which your Service or Activity releases when it is done handling the alarm.
This is only a guess but I think the issue has to do with the API. Starting with KitKat, the system messes up the AlarmManager. Perhaps consider trying using something else for systems at abd above kitkat.
"Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested. "
Taken from http://developer.android.com/reference/android/app/AlarmManager.html
Your alarms will continue to exist after your app is closed normally. If it is force stopped, or your device restarted, or an update for your app is installed, or your app is uninstalled, they will be lost. You can create BroadcastReceivers for some of those situations to recreate your alarms.
Also, setInexactRepeating is exactly that: inexact. When that alarm fires is implementation dependent and can not be precisely predicted.
Try the following:
1) Add teh Wake_lock permission to your manifest.
<uses-permission android:name="android.permission.WAKE_LOCK">
2) Change
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 1000, 5000, pendingIntent);
with
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, 5000, pendingIntent);
Could you show us the AlarmReceiver.class code?
Maybe you need to use return START_STICKY; on your onStartCommand method?
Try to place AlarmManager into background service.
i have also used Alarm Service in my project for preparative task in very 6 or 7 minutes. And it is running fine in all phone.
i have make a alarm Service like this:
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.util.Log;
public class MyAlarmService {
private static PendingIntent resetAlarm;
private static String TAG="CellPoliceChildGPSAlarmService";
private static AlarmManager am;
public static void start(Context context) {
try {
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
// Create an IntentSender that will launch our service, to be scheduled with the alarm manager.
//resetAlarm = PendingIntent.getService(context, 0, new Intent(context, Get_NonRootDetails.class), 0);
resetAlarm = PendingIntent.getService(context, 0, new Intent(context, CallNonRBackgroundService.class), 0);
// Schedule the alarm!
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Log.i(TAG, firstTime+"");
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 10*1000*60, resetAlarm);
}
catch (Exception e) {
Log.v("CellInfo", "Exception while start the MyAlarmService at: " + e.getMessage());
}
}
public static void stop(Context context) {
try {
// When interval going to change from web services
am.cancel(resetAlarm);
}
catch (Exception e) {
Log.v("CellInfo", "Exception while start the MyAlarmService at: " + e.getMessage());
}
}
}
I have called or start like this;
MyAlarmService.start(SplashActivity.this);
Given permission in Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK">
<service
android:name="com.secure.DataCountService"
android:enabled="true" >
<intent-filter>
<action android:name="com.secure.MyService" />
</intent-filter>
</service>
For notifications i also used pending intents like;
Intent notificationIntent = new Intent(context, DashBoardActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, PushNotificationUtils.notiMsg, pendingIntent);
notification.flags |= notification.FLAG_AUTO_CANCEL;
Try this it works when activity is not running..
Calendar calendar = Calendar.getInstance();
long timemills = calendar.getTimeInMillis();
Intent myIntent = new Intent(this, TimeChangeReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, timemills, pendingIntent);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timemills,
10000, pendingIntent);
This is how I am creating an alarm.
When the app is still running in background the alarm is fired.
but when it is cleared from the recent apps, the alarm is getting discarded. I am registering a new receiver and providing a unique action for differentiation between two alarms. Is there any mistake in my code.
String filter_action = "myPackageName" + request_code_value +"_time";
IntentFilter filter = new IntentFilter(filter_action);
registerReceiver(new AlarmReciever(), filter);
Intent intent = new Intent(filter_action);
intent.putExtra(getString(R.string.get_current_intent_value), request_code_value);
intent.putExtra(getString(R.string.alarmtext), alarm_title);
intent.putExtra(getString(R.string.alarm_time), newAlarm_Choose_Alarm_Value.getText().toString());
Calendar calNow = Calendar.getInstance();
Calendar calSet = (Calendar) calNow.clone();
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, request_code_value, intent, 0);
calSet.setTimeInMillis(timeInMillis);
if (calSet.compareTo(calNow) <= 0) {
// Today Set time passed, count to tomorrow
calSet.add(Calendar.DATE, 1);
}
alarmManager.set(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(), pendingIntent);
Manifest file.
<receiver android:name="com.bigbangpartners.YoWakeUp.activities.AlarmReciever" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="AlarmManager_Start" />
</intent-filter>
</receiver>
Please help me.
Thanks in advance.
If you are registering and de-registering the BroadcastReceiver programmatically in your Activitys, then a BroadcastReceiver created in this way will remain in existence only as long as the app process is alive. So when you remove your app from the list of recent apps, this BroadcastReceiver is also, in effect, destroyed.
On the other hand, a BroadcastReceiver registered in the manifest is a global, permanent component of an Android app that remains in existence forever, whether the app process is alive or not.
If you want your alarms to be activated even when the app is not in the foreground, then you need to register the BroadcastReceiver in the app manifest and specify the alarm action as well. You are not doing that, and this, I believe, is the root of your problem.
What you should do:
1. Define your BroadcastReceiver in manifest like this:
<receiver android:name="com.bigbangpartners.YoWakeUp.activities.AlarmReciever" >
</receiver>
2. Remove all calls to registerReceiver() and unRegisterReceiver() in your app code as that is not needed.
3. Define your alarm Intent like this:
Intent intent = new Intent(this, AlarmReceiver.class);
Rest of code remains same. First try this and see if it works.
I am building a game-like application and I've been reading about all the different approaches of running things with Services in background, foreground, Alarms and so on, and I am a bit confused.
My app would go like this (example):
user presses a button in Main, then he can close the app
after 30 minutes Activity1 opens up
user finishes whatever he needs to do in that activity, which
triggers the next activity to start after 2 hours
after 2 hours Activity2 opens up
user finishes whatever he needs to do there as well, triggering the
next one
after a day Activity3 opens up, and so on
What would be the best approach? Have a service running continuously to open those activities, or get a new alarm set up to start every time the user finishes one of the activities?
Please do not create a service just to it can stay idle for several hours. It makes no sense.
What you need to do is to create an alarm. something like:
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
This is just a general example for the Alarm API. You will need to adjust it for your needs.
Finally - please be aware: alarms is not boot resilient! That is: if for any reason
the user's device goes down, all of your alarms will be lost.
if you do want your app to be boot resilient you will need to register to an
event called RECEIVE_BOOT_COMPLETED (think post-boot) where you will restart your pending
alarms:
//manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".MyBootReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
//java class
public class MyBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
// restart alarms
}
}
}
Hope it helps
I know this is a possible duplicate, but i havent found a specific answer to this? (there are partial answers on how to force the widget to update every second but its not all i am after...)
I need to have a widget that will update once a minute.
How to make a battery&CPU&RAM efficient widget for this purpose? (The data will be fetched from the internet and parsed before showing it to the user(a small amount of data and processing to be done.))
Should i make a Service that runs on BOOT if the user has the widget on screen and have that service schedule an alarm manager that wakes up a service that updates the widget?
Also i would like to pause this service if the screen is locked or off to save battery...
That's exactly how I did something similar. I created a Service (IntentService if you don't need anything complicated) and then register it with the alarm manager.
long interval = intervalMinutes * 60 * 1000;
long firstTime = Calendar.getInstance().getTimeInMillis();
Intent i = new Intent(ctx, AlarmService.class);
// Use the widget ID to update only one widget at a time.
i.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id);
PendingIntent mAlarmSender = PendingIntent.getService(ctx, id, i, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) ctx.getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, firstTime, interval, mAlarmSender);
being AlarmService.class your Service or IntentService.
For boot event, you can create a BroadcastReceiver and manage a android.intent.action.BOOT_COMPLETED action where you can register the alarm.
You can register for that event in your AndroidManifest:
<receiver android:name=".BroadcastReceiverWidget" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
My app needs to execute a specific task every hour. It does not matter if app is runing, suspended, or even closed.
When app is running or suspended, I can do it by just scheduling an AlarmManager broadcastreceiver. But when the application is closed, I have to call "unregisterReceiver" to not leak an intent, and app will never be wake up (or something) to process the task.
Then, the question is: how to schedule an alarmmanager task that I don't need to unregister, so it will be called even if my application is closed?
Use AlarmManager.setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation) for this. Set the type to AlarmManager.RTC_WAKEUP to make sure that the device is woken up if it is sleeping (if that is your requirement).
Something like this:
Intent intent = new Intent("com.foo.android.MY_TIMER");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
long now = System.currentTimeMillis();
long interval = 60 * 60 * 1000; // 1 hour
manager.setRepeating(AlarmManager.RTC_WAKEUP, now + interval, interval,
pendingIntent); // Schedule timer for one hour from now and every hour after that
You pass a PendingIntent to this method. You don't need to worry about leaking Intents.
Remember to turn the alarm off by calling AlarmManager.cancel() when you don't need it anymore.
Don't register a Receiver in code for this. Just add an <intent-filter> tag to the manifest entry for your BroadcastReceiver, like this:
<receiver android:name=".MyReceiver">
<intent-filter>
<action
android:name="com.foo.android.MY_TIMER"/>
</intent-filter>
</receiver>
You need to user an Android Component Called Service for this. From the service code you can schedule your Task using the AlarmManager with PendingIntent Class for every hours. As your AlarmManger is declared in the Service Components it doesn't require any GUI and will get execute in background, till you have battery in your device.