My application should have some changes after some time (in hours or days) and I would like to test that.
I try to use SystemClock.setCurrentTimeMillis() in my unit test to simulate the change of time/date, but without any luck.
I declared the <uses-permission android:name="android.permission.WRITE_SETTINGS" /> in the manifest of both the application and the test application, that did not change anything.
At this time, I am running those tests on the emulator if that makes any difference...
Edit : With Nick's help, also requested SET_TIME permission:
<uses-permission android:name="android.permission.SET_TIME" />
But now, the logcat shows :
WARN/PackageManager(59): Not granting permission android.permission.SET_TIME to package com.matthieu.tests (protectionLevel=3 flags=0xbe46)
Another Edit : With dtmilano's answer...
Added this code (with the right try/catch) in my test:
Runtime.getRuntime().exec("date \"$((10800 + $(date +%s)))\"").waitFor();
When I go on the shell, I can run that command without any problem and I see the time changing in the emulator (I am trying to add 3 hours). When I run my tests with my code, the time does not change at all... ?
What I do on the command line is :
date "$((10800 + $(date +%s)))"
I doubt I need to add the "adb shell" part in the Runtime.exec...
Seems like this is on the right path, but still not able to get it running. And it might also go along what Nick pointed to that it needs to be a system process to be able to change the time... ?
Add android.permission.SET_TIME_ZONE to your manifest if you need to change the timezone,
then from your activity (or wherever you need it.. but you'll need to grab an appropriate context..)
Context context = getContext(); // or (Context) this, or whatever depending on where you are
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mgr.setTimeZone(timezoneid); // replace timezoneid with the time zone you need e.g. "pacific/Auckland"
mgr.setTime(timeinmillis); // replace timeinmillis with the time you need in millis, probably from a Date or Calendar object... but watch the timezone in the calendar ;-)
The whole point being that the AlarmManager system service contains members to set the system time and timezone..
http://developer.android.com/reference/android/Manifest.permission.html#SET_TIME
I searched "android permissions" then on the permissions page, did a find on the word "time". if you are past api level 8, i would recommend you request that permission.
Update: based on this link, I do not think it is possible to set the system time from a user space app. For your testing purposes, you may need to manually change the time on the emulator. The only other option I have found requires building and signing your own Android build.
From your host (assuming you are using linux) you may run:
$ adb shell date $(date --date='2011-06-11 12:10:10' +%s.0)
mainly if is the emulator. Replace the date and time with the desired values.
You should find a way of synchronizing this change with your tests or you can even run it from your tests using Runtime.exec().
Related
I know from https://developer.android.com/guide/topics/connectivity/telecom/selfManaged, that you can set the default dialer by having the necessary items in your manifest and permissions listed. One of those being the Dial intent.
What i'm trying to do is build a library that does all of these content provider calls and provide a nice reactive way of doing things to my application. While building the library I would like to add some integration tests around these device calls.
There's the GrantPermissionsRule that helps with setting permissions already defined in your manifest but how does one deal with becoming the default dialer or SMS application? I'd accept even an adb command that you could run using a Runtime execute command.
I also tried testing on an emulator and I noticed that you can give your app WRITE_SECURE_SETTINGS but not MANAGE_USERS which is the other necessary permission you need if you were to use reflection to access the https://android.googlesource.com/platform/frameworks/base/+/master/telecomm/java/android/telecom/DefaultDialerManager.java
Any help is much appreciated!
you can try adb command:
adb shell settings put secure dialer_default_application com.google.android.dialer
replacing com.google.android.dialer with your package.
In my android App, there is an Activity which shows time string according to the System Time Format (12Hr. / 24Hr.).
I am writing espresso test to test this behavior whether the time displays gets changed as the System time format changes.
In order to achieve this, i want to change my System time format through my Instrumentation test for pure testing purpose. and i've added permission in test project's manifest, like this
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
and wrote the following code to change system time format
Context context = InstrumentationRegistry.getContext();
Settings.System.putString(context.getContentResolver(),Settings.System.TIME_12_24, "12");
and it is throwing Permission Denial error. (you can use below link to see the stack trace)
Error StackTrace Screenshot
i am not able to understand, since the code which is trying to change the system time format in the test project itself and it has permission to change the system time setting,
I verified Using this command
adb shell dumpsys package com.my.app.package | grep permission
Please tell me, what i am missing here ?
I've already found an explanation to your issue. Here is it:
The user application does not have permission to change the device
time. Please read the answer by cashbash in the following post
for the alternate option.
Copying here for quick reference:
According to this thread, user apps cannot set the time,
regardless of the permissions we give it. Instead, the best approach
is to make the user set the time manually. We will use:
startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));
Unfortunately, there is no way to link them directly to the time
setting (which would save them one more click). By making use of
ellapsedRealtime, we can ensure that the user sets the time correctly.
From: Set Android's date/time programmatically
Try also instead of using Espresso, use uiatomator as that instrumentation test framework can perform actions with Dialogs, Marshmallow permissions or lockscreen.
It works perfectly with Espresso.
Check this site: http://qathread.blogspot.com/2015/05/espresso-uiautomator-perfect-tandem.html
Hope it help
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
I trying some stuffs with android as i am learning android development, now i have a scenario here.
I want to change the android phone's system date through my application( first i would like to know is this doable? )
Layout is as below
Now what i want is when the user clicks the button the date should increase by say 20 days
how can i do this.
i am unable to start...please help
As I already said that's impossible. You need the SET_TIME permission and that permission is granted by system only to applications that are in the Android system image. If You are able to gain that privilege you can easily change with the AlarmManager. SystemClock.setCurrentTimeMillis write the /dev/allarm file
adb shell ls -l /dev/alarm
crw-rw-r-- system radio 10, 46 2013-06-12 10:46 alarm
c stays for Character special file (stored in /dev).
system is the owner of the file
radio is the group
system and radio have read and write permissions (rw-, tree bits, int value 6), the others have only the read permission (r, int value 4). So the file permission is 664. If you can get root user (running su), you can change the permission of this file and wrote in it a new value. A bug report has been filled in order to ask google to allow apps to modify programmatically the mobile date but it has been declied. Here the reference
On Android, the only way for an application do have write access to the time&date is to get the SET_TIME permission, which is only possible for "applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission." (see signatureOrSystem protection level).
The only way for your application to reach this protection level is to run on a rooted device, or build and sign your own android rom.
If this is your case, you can easily use the AlarmManager or simply the Calendar instance.
Good luck!
Normal user applications does not have permission to change the device time. Read the answer by cashbash in the following post for the alternate option.
Unfortunately, blackbelt is right; android lets us do a lot of cool things, but changing system time programmatically is not one of them.
Since I see that you are looking for more credible/official sources, I suggest you check out this open ticket with Google, which suggests this is an open problem--it ought to work, but doesn't, and it doesn't seem Google is going to fix it anytime soon. The gist of it is that the SET_TIME protection level is set higher than it ought to be. (for more information on permissions, see here)
Although this is not quite the same as changing the time programmatically, you can still make the user change the system time for you if for some reason you do need system time to be changed. This thread will explain how to go about implementing that if you want to go that route.
Hope this was helpful information!
When you want to change the mobile system date or time in your application, how do you go about doing it?
You cannot on a normal off the shelf handset, because it's not possible to gain the SET_TIME permission. This permission has the protectionLevel of signatureOrSystem, so there's no way for a market app to change global system time (but perhaps with black vodoo magic I do not know yet).
You cannot use other approaches because this is prevented on a Linux level, (see the long answer below) - this is why all trials using terminals and SysExecs gonna fail.
If you CAN gain the permission either because you rooted your phone or built and signed your own platform image, read on.
Short Answer
It's possible and has been done. You need android.permission.SET_TIME. Afterward use the AlarmManager via Context.getSystemService(Context.ALARM_SERVICE) and its 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)
Long Answer
As it has been pointed out in several threads, only the system user can change the system time. This is only half of the story. SystemClock.setCurrentTimeMillis() directly writes to /dev/alarm which is a device file owned by system lacking world writeable rights. So in other words only processes running as system may use the SystemClock approach. For this way android permissions do not matter, there's no entity involved which checks proper permissions.
This is the way the internal preinstalled Settings App works. It just runs under the system user account.
For all the other kids in town there's the alarm manager. It's a system service running in the system_server process under the - guess what - system user account. It exposes the mentioned setTime method but enforces the SET_TIME permission and in in turn just calls SystemClock.setCurrentTimeMillis internally (which succeeds because of the user the alarm manager is running as).
Cheers
According to this thread, user apps cannot set the time, regardless of the permissions we give it. Instead, the best approach is to make the user set the time manually. We will use:
startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));
Unfortunately, there is no way to link them directly to the time setting (which would save them one more click). By making use of ellapsedRealtime, we can ensure that the user sets the time correctly.
A solution for rooted devices could be execute the commands
su
date -s YYYYMMDD.HHMMSS
You can do this by code with the following method:
private void changeSystemTime(String year,String month,String day,String hour,String minute,String second){
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
String command = "date -s "+year+month+day+"."+hour+minute+second+"\n";
Log.e("command",command);
os.writeBytes(command);
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Just call the previous method like this:
changeSystemTime("2015","04","06","13","09","30");
I didn't see this one on the list anywhere but it works for me. My device is rooted and I have superuser installed, but if superuser works on non-rooted devices, this might work. I used an AsyncTask and called the following:
protected String doInBackground(String... params){
Runtime.getRuntime().exec("su && date -s " + params[0]);}
In our application case, the dirty workaround was:
When the user is connected to Internet, we get the Internet Time (NTP server) and compare the difference (-) of the internal device time (registederOffsetFromInternetTime). We save it on the config record file of the user.
We use the time of the devide + registederOffsetFromInternetTime to consider the correct updated time for OUR application.
All GETHOUR processes check the difference between the actual time with the time of the last comparission (with the Internet time). If the time over 10 minutes, do a new comparission to update registederOffsetFromInternetTime and mantain accuracy.
If the user uses the App without Internet, we can only use the registederOffsetFromInternetTime stored as reference, and use it. Just if the user changes the hour in local device when offline and use the app, the app will consider incorrect times. But when the user comes back to internet access we warn he about the clock changed , asking to resynchronize all or desconsider updates did offline with the incorrect hour.
thanks penquin. In quickshortcutmaker I catch name of date/time seting activity exactly. so to start system time setting:
Intent intent=new Intent();
intent.setComponent(new ComponentName("com.android.settings",
"com.android.settings.DateTimeSettingsSetupWizard"));
startActivity(intent);
`