On some devices (even on some that, at least according to the manual, do not have a battery saver in the system, and the customers deny they installed one) the system broadcasts the Alarm Intent several hours later, only at the moment when the user switches the device on.
If the users set the alarm in a few minutes, it works. If it is set in a few hours, it might work, might be off by a few minutes or hours, most likely the latter.
This is getting on my nerves, as
I always get the complaints from the customers (understandably), and
I do not have a generic answer for them, as it might not be
obvious where the problem lies, where to exclude my app from that
"unexact" behaviour.
it is not even an 'about' time when it's several hours wrong!
I do target API >= 19/KitKat, so I distinguish already how to set the alarm:
PendingIntent pi = PendingIntent.getBroadcast(ctx, 1, i, PendingIntent.FLAG_UPDATE_CURRENT);
if (android.os.Build.VERSION.SDK_INT >= 19)
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calSeqStart.getTimeInMillis(), pi);
else
alarmManager.set(AlarmManager.RTC_WAKEUP, calSeqStart.getTimeInMillis(), pi);
Often, and also in the latest case it's not even an API 19 device:
TCT ONE TOUCH TAB 7HD (TAB7HD)
OS API Level: 16
To the code: I am sure "calSeqStart"'s time is correct, this cannot be a problem.
It cannot be a WakeLock problem, as soon as the BroadcastReceiver gets the Intent, it logs a message, and that message also appears at the wrong time! So the broadcast is sent only at the time the user switches the device on.
At my place, and hundreds of others, it works without problems.
My questions:
How can an Alarm App tell the system forcibly it needs to be woken up and started at a certain time?!
Does anybody know whether it's possible to find an energy-saver-app like STAMINA (Sony Experia Z) so that the user can be warned?
ADDITION:
In my app, I do set alarms in the alarm manager as AlarmManager.RTC_WAKEUP type, but when I dump the alarms using adb, I see they are mapped to AlarmManager.RTC type.
This only happens on some (or at least one: Alcatel onetouch TAB 7D) device. On all others, the alarms set by my app do correctly wake up the device (and I see them as RTC_WAKEUP in the "adb shell dumpsys alarm" as expected).
As it is Android 4.1.1, it cannot be an AppOpps check, must be something else.
And using the ADB, I see that only deskclock can set the alarm as WAKEUP, all entries of other apps are non-WAKEUP alarms.
Related
I am trying to run IntentService as such from AlarmManager setRepeating() for every half an hour. I want to send a to broadcast, from broad cast to intent service. In the service, some functionality will be done.
But, initially the AlarmManager in not triggering while the app is in closed state.
When my app is running or in background state the alarm is working fine and when I close the app the alarm is not working in some devices.
What should I do to run the alarm even if the app is closed?
From the documentation of setRepeating():
As of API 19, all repeating alarms are inexact.
Moreover, setRepeating() does not work with Doze.
You should use exact alarms (set by the appropriate AlarmManager method based on the API level of the device):
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
triggerTime, pendingIntent);
} else if (Build.VERSION.SDK_INT >= 19) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
}
And reschedule them every time they fire.
For the rescheduling you could add the original trigger time to the Intent:
intent.putExtra(KEY_TRIGGER_TIME, triggerTime);
Then retrieve this extra in onReceive(), add your desired interval to it and reschedule the alarm using the new value:
#Override
public void onReceive(Context context, Intent intent) {
long triggerTime = intent
.getLongExtra(KEY_TRIGGER_TIME, System.currentTimeMillis());
// adding one day to the current trigger time
triggerTime += TimeUnit.DAYS.toMillis(1);
// set a new alarm using the new trigger time
// ...
}
NOTE: As #Opiatefuchs mentioned in the comment above, some manufacturers (such as Xiaomi or Huawei) may implement certain battery saver functions that can prevent alarms from being fired and cannot be bypassed programmatically.
Nowadays devices are coming with more security in context of Battery power consumption. By default devices keep almost all apps in power saving mode. It means in some devices your background work (Location, Alarm manager) won't work as soon as you come out from the app. In other devices background tasks won't work after a battery threshold limit (like 13%). So you need to keep out your app from this battery saving mode to run your app smoothly even in background. The way to achieve that behavior in these two manufacturers is:
Xiaomi
Go to the Battery => Power => App battery Saver => select your app and choose No restrictions (for Background settings), then Allow option for Background location.
To AutoStart your app after Boot: Go to the Security app => Permissions => Auto start and check your app.
Samsung
Samsung Smart Manager App used to stop all background work after 3 days if you don't come to your app. So the way to disable this feature is:
Go to Battery in the Settings => Unmonitored apps => Add your app to the whitelist. Some other Samsung versions may differ the place to disable it, like Battery => Detail => Select the app and "Don't optimize".
For other devices there should be same power options either in settings option directly or some app are given to handle it.
First, there is a bug with android studio. If you start the app from the android studio and then swipe it away from the recents, the alarms will be deleted. So after that, relaunch your app by clicking on the launcher Icon and then if you swipe it away, the alarm will be still there.
Second, on some devicrs with battery optimization stuff, you should start a foreground service and that works totally fine.
I could make it work using these two points and now it works like a charm.
The below behavior changed after a full charge. Previously, after disabling energy saving for this app, it displayed that there was no battery saving active etc, but only after a full charge (from very low battery state) did the device behave as it should. So change those settings for the app, then do a full recharge (maybe only after previously having low battery). This could fix it.
ZTE Blade L110
Even with the battery saver disabled (Settings -> Battery -> Options -> Battery Saver) and the app marked as important for messages (Settings -> Prompt & notification -> App notifications -> appname -> Priority) it seems like neither setExact nor setAlarmClock are triggering on time.
for Lenovo phone:-
you need to go in setting -> application->select app-> uncheck Restrict to launch
now it will be work in the background as killed state
I'm testing my application on Android P beta release 4. My app's targetSdkVersion is 27
It has been observed that alarm manager notifications are not working as expected. I'm using below code to set the notifications -
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
} else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
} else {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, AlarmIntentBuilder.buildPendingIntent(context, uri));
}
I tested the same logic on Android 8.0 but it's working fine. In Android 9.0, notifications are working but sometimes they did not work at all. Also, if they work they are not exact and takes too much time and this happens even if the application is in foreground.
The logic is, I've the repeating reminders which are set on specific time and those should repeat them-self on daily basis at the specified time. Also these are high priority reminders and should land at exact time so I'm using setExact and once the notification is received it's being display and new alarm for the next week of the same day is set.
I've checked the Android P API documents but could not find any link which has the impact on working of AlarmManager and Notifications. Only thing which I feel is causing the issue is Power management in Android P and the priority buckets. However notifications are not working properly even if application is in foreground.
Anything I'm missing here. Any help is much appreciated.
As you yourself mentioned the new App Standby Buckets feature of Power Management is likely to be the cause. The new documentation states:
If an app is in the frequent bucket [or below], the system imposes stronger restrictions on its ability to run jobs and trigger alarms
and
In particular, the bucket determines how frequently the app's jobs run, how often the app can trigger alarms
Additionally, if you view Power Details you can get a rough idea of the delay times.
Worth noting is that it appears your bucket is based on average usage (and machine learning) not on current usage - which means even if your app has just been in the foreground, the buckets play some role
This is happening because of Power management feature introduced in Android Pie.
In android P, strict restrictions are introduced on the apps running in background. These restrictions are explained here
As we can see in the above link, if we connect the device to charging there are no restrictions imposed on the device and notifications are working properly. However, if we remove the device then Android system adds the certain restrictions for the apps running in background.
We can turn off this restrictions by turning off battery optimization for our application from device settings. Search for battery optimization in settings and turn it off for our application.
Also, testing the notifications by changing the device date and time was a hack that worked fine till now but in Android P, we've to either test them in real time scenario or turn off battery optimization for our application to test them.
I hope this will clear our doubts.
I am trying to get next alarm clock time on android. I use two known methods:
1: ( ( AlarmManager )Global.Context.getSystemService(Context.ALARM_SERVICE) ).getNextAlarmClock().getTriggerTime() // for SDK API 21+
2: Settings.System.getString(Global.Context.getContentResolver(), Settings.System.NEXT_ALARM_FORMATTED) // for SDK API 20-
This work ok on most part of devices. But on some devices with MIUI the results are wrong (for both methods 1 or 2). The results seem to be random without any consistence with alarm clock. May be these result are corresponding to calendar events notifications. But not with alarm clock.
The users of my app, that encounter such a problem, report me about other apps that show next alarm clock time correct. So I know that the solution exists.
I have an app which uses the AlarmManager to regularly wake up the phone at full hour and send a message to an Android Wear watch which than makes a short vibration. I have two users with a Samsung Galaxy S6 with stock Android 5.1.1 and the Sony SW 3 with 5.1.1 who experience a weird bug. At the very first full hour the vibration is at the exact time but all other vibrations are 3 minutes delayed. Sometimes even the first full hour vibration is delayed.
Here is some code:
final Calendar time = Calendar.getInstance();
time.set(Calendar.SECOND, 0);
time.set(Calendar.MILLISECOND, 0);
time.set(Calendar.MINUTE, 0);
time.set(Calendar.HOUR_OF_DAY, time.get(Calendar.HOUR_OF_DAY) + 1);
final Intent hourlyChimeIntent = new Intent(context, HourlyChimeReceiver.class);
hourlyChimeIntent.setAction(key);
final AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
final PendingIntent pi = PendingIntent.getBroadcast(context, 0, hourlyChimeIntent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setExact(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pi);
I acquire a WakeLock in the receiver and then send a message to the Wear watch in a thread. No vibration is missed, they are just 3 minutes late.
I have no other reports about this issue and all my testing devices are working good. I have no Samsung device though.
Any ideas what could cause the 3 minutes delay? Does Samsung ignore setExact and makes my alarm an inexact? How to force exact alarms on Samsungs?
EDIT:
Here is the Android Wear specific code. In the receiver's onReceive method I do this:
final PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
final PowerManager.WakeLock lock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID);
lock.acquire(7L * 1000L);
final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context).addApi(Wearable.API).build();
new Thread(new Runnable() {
#Override
public void run() {
googleApiClient.blockingConnect();
long pattern[];
pattern = new long[] {0L, 500L};
final NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await(2000L, TimeUnit.MILLISECONDS);
if (nodes != null) {
for (final Node node : nodes.getNodes()) {
// just send and forget
Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), "/hourly_chime", Utils.Vibrator.serializeVibratePattern(pattern).getBytes()).await();
}
}
}
}).start();
The issue seems to occur only on Samsung devices (e.g. Galaxy Grand, S4, S5, S6, Note 3, Note 4) with Lollipop (5.0, 5.1, 5.1.1). It seems that alarms are scheduled inexact when device is on battery with screen off. If device is charging or has screen on during scheduling alarm the issue will not occur.
You can verify if next alarm will be inexact with:
adb shell dumpsys alarm
I didn't find perfect solution for this problem - only workarounds where each has some drawbacks:
Use setAlarmClock instead setExact (see this answer). This works very well (not on all devices), but the issue with this solution is that the alarm will affect the system by showing alarm icon in status bar (if someone doesn't have alarm clock set already) and displaying next alarm scheduled time on alarm widgets etc. Unfortunately while this works on Galaxy Grand with 5.1.1 it doesn't on Galaxy S4 with 5.0.1.
Enable screen before scheduling the alarm (I do this half second before scheduling next alarm to avoid race condition). Of course it is not good solution for every app to enable screen just to schedule next alarm.
One bug report describing similar issue connects it with app package name length! I didn't verify if it really fixes the issue, because changing package name is not an option for already published app.
There is another report where someone claims this can be fixed by using WakefulBroadcastReceiver, but it doesn't work in my case.
BTW This issue drives me crazy :)
Edit: Looks like this issue does not occur when there is keyword "alarm" or "alert" in the app package name (as pointed out by Mathieu H. in comments below).
I was also able to fix the issue manually by disabling App optimization in Battery settings (or in Smart Manager app). It seems it cannot be done programmatically, so you can try asking your users...
I am trying to build an app on my wife's phone that pranks her on April 01, April Fool's day of course. The app is going to change her background to look like the screen was cracked, the background is very convincing when I try it on my Droid (I was pranked similarly).
Anyway, digging into how this would work, I think its quite the process, however, I may be looking too far into this. I started diving into setting an alarm, however, I am confused about a couple things:
Would it be necessary for my wife's phone to load this prank application in the background each time she reboots her phone? I am assuming yes, as I believe this prank application would most likely invoke a broadcast receiver to "listen" for April 01, 2011?
If the application doesn't need to load each time in the background, what facilitates Android alerting my application and firing it when April 01, 2011 comes around?
I hope that makes any sense, basically, I want to ensure this application runs on April 01, 2011 even if my wife's phone crashes or reboots.
What would be the most straightforward method of making this work? I apologize if I don't understand broadcast receivers properly, this is quite the new concept which I am not use to. The Service and Broadcast Receiver functionality is native to Android and not any other language, no?
Thanks for helping this NEWB :)
Bit too early for planning for April Fools,eh? :)
All you need is a single BroadcastReciever.
Create a BroadcastReciever add BOOT_COMPLETED to its intent filter. You're onRecieve() will be called. This will happen in 2 cases
1) Your Phone Booted up.
2) Your hit the Alarm.
To check which event occured, Check if your recieved Intent Action is "BOOT_COMPLETED", if it is then your phone booted up so setup an alarm for April 1, 2011. (Technically, you should have your own Custom Intent Action, but you don't need it in this case...)
Now, if your Action wasn't the Boot completed it means its april 1 so in that case change the wallpaper, using the WallpaperManager. Your new wallpaper will obviously be in your resources..
void onRecieve(Context ctx,Intent intent)
{
if( intent.getAction.equals( /* Boot Completed */)
{
//setup alarm using alarm manager
}else
{
//change wallpaper.
}
}
I'm sorry if i misunderstood you question, did you need help with the Alarm Manager?
Ofcourse, As Macarse pointed out you'll need SET_WALLPAPER and RECEIVE_BOOT_COMPLETED Permissions.