Can I programmatically change time on device? - android

How to adjust device time from my application? Especially with tablets, as tablets do not sync time as phones do.

Edit: Try
AlarmManager a = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
a.setTime(millis);
Don't forget permission SET_TIME in your manifest.

Related

Android alarm not firing when phone is in sleep/doze mode [duplicate]

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

Android P Beta - AlarmManager Notifications not working

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.

Android exact Alarm is always 3 minutes off

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...

Android: Alarm starts at wrong time

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.

How to set time zone for android rooted device?

I have a rooted android device and I want to change my device's default time, date and time zone from my application. Changing time and date is quite easy, but how can I change my device's timezone?
If you have the correct permission(see below), you can do this with the AlarmManager. For example, to set the time to 2013/08/15 12:34:56, you could do:
Calendar c = Calendar.getInstance();
c.set(2013, 8, 15, 12, 34, 56);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(c.getTimeInMillis());
You need the permission SET_TIME to do this. Unfortunately, this is a signatureOrSystem permission.
Definition in AndroidManifest.xml:
<!-- Allows applications to set the system time -->
<permission android:name="android.permission.SET_TIME"
android:protectionLevel="signature|system"
android:label="#string/permlab_setTime"
android:description="#string/permdesc_setTime" />
The only apps that can use this permission are:
Signed with the system image
Installed to the /system/ folder
Unless you build custom ROMs, you're out of luck with the first.
For the second, it depends on what you are doing.
If you're building an app for wide distribution(Play Store, etc), you
probably shouldn't. It's only an option for root users, and can only
be installed manually. Any marketplace would not install it to the
correct location.
If you're building an app for yourself(or just as a learning
exercise), go for it. You'll need a rooted phone, though, so do that
first. You can then install the application straight to /system/app/
with adb or a file manager. See articles like this for more detail.
One final note: The SET_TIME permission and AlarmManager#setTime() were added in Android 2.2(API 8). If you're trying to do this on a previous version, I'm not sure it will work at all.
You need android.permission.SET_TIME. Afterward use the AlarmManager via Context.getSystemService(Context.ALARM_SERVICE) and it s method setTime().
Snippet for setting the time to 2010/1/1 12:00:00 from an Activity or Service:
Calendar c = Calendar.getInstance();
c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(c.getTimeInMillis());
If you which to change the timezone, the approach should be very similar (see android.permission.SET_TIME_ZONE and setTimeZone)
more info in this link and this

Categories

Resources