I have implemented code for setting time on a rooted device in android.I have made it an in-built app and it works fine in the sample application.But when I tried to use the same code into my application which is also in-built it is NOT able to set the time.
Below is the code
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setTime(date.getTime());
with the permissions....
<uses-permission android:name="android.permission.SET_TIME"></uses-permission>
<uses-permission android:name="android.permission.SET_TIME_ZONE"></uses-permission>
Instead it gives the following error:
"Neither user 10042 nor current process has SecurityException:android.permission.SET_TIME
unable to open Alarm Driver:Permission Denied.
android.OS.Parcel.readException
android.app.AlarmManagerStubProxy.setTime(AlarmManager.java)".
Any advice would help.
Related
I am trying to follow this answer However, it is not working in simulator nor on my phone so I have questions on the simulator logs and phone and rebooting to simulate this and debug
I have very interesting notes at the bottom that are VERY confusing to me
I am using API 24 and pixel 3 simulator and real samsung 8 phone
I do the typical adds to manifest of
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
and
<receiver android:name=".biz.alarm.BootupReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I however never see this log statement...
public class BootupReceiver extends BroadcastReceiver {
private final static String TAG = "BootupReceiver";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "booted. action="+action);
}
}
For the simulate, I click the play button and watch my app come up. I then hold the power button and it only gives me a "power off" option when I really just want to restart...odd, so I power off. That seems to exit the simulate completely such that when I click play again on the simulator in Android Studio, it then logs
08/06 19:17:40: Launching 'app' on Pixel 3 API 24.
$ adb shell am start -n "app.mykeepintouch.kit/app.mykeepintouch.kit.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
...
D/MainActivity: onCreate: starting
There is no bootup log for me to reregister notifications. QUESTION 1: Can the simulator not simulate this correctly?
Next, my real phone- Well, the same thing I guess but perhaps there are some logs I can view on the phone itself at least? The post I ran into talked about dumping to sd card but I am plugged into android studio so I would think I could dump logs somehow to android studio?
EDIT: I am using the sample link in that post as well. I did a git clone imported the project, picked API 24 and added a single log in PollReceiver. It worked when I went to bed and did not work the 2nd run when I ran this morning. I will add more info as I debug random scenarios I think of.
WEIRD SCENARIO 1: If I have TWO android studio projects open and open my personal app and then open the sample link app AFTER my project, I see a Toast "Alarms scheduled". I however can find no logs on PollReceiver until that alarm goes off 5 seconds later. I was expecting to see a log from PollReceiver on start but never see that until 5 seconds. Another run of this later yielded no logs (except the toast message popped up so I know it ran that code...very weird). I added a log message then to ScheduledServiceDemoActivity and now I can't reproduce 0 logs like that one time.
WEIRD SCENARIO 2: I REBOOT the phone(or it keeps launching my app and scenario 1 keeps working). Then I ONLY boot the sample link app, nothing ever happens. I wait for 90 seconds and nothing.
This may be why it worked last night before I went to bed as I was in scenario 1.
FINAL GUESSES: I can never get PollReceiver to fire on startup. ScheduledServiceDemoActivity seems to be the true entry point and I never added a service to my above code as I didn't want one...just wanted to be notified of being booted up to reschedule alarms. This then leads me to the possible conclusion the ScheduledServiceDemoActivity is there to fire on certain devices on bootup and the PollReceiver is for other devices on bootup? If so, what simulators can simluate this other bootup scenario?
EDIT (I had another thought) On my samsung phone, I checked the permissions and there is only THREE even though I added these 4 lines in my manifest
<!-- So we can make a phone call out -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- so we can send a text -->
<uses-permission android:name="android.permission.SEND_SMS" />
<!-- So we can reschedule alarms that went off while powered off -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- read contacts so they can easily choose their friends -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
The receive boot is not in there. is this the issue? OR do phones not list the receive boot completed to users as it might be confusing?
thanks,
Dean
Try to add this to your intent-filter in your manifest:
<receiver android:name=".biz.alarm.BootupReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
It helped me when I got similar issue with some devices.
You should look into setExactAndAllowWhileIdle
From what I understand it will execute regardless of if the phone is in doze or not and exactly at the specified time.
You answered their own question here but because that answer utilizes the WorkManager API which "is intended for work that is deferrable—that is, not required to run immediately—and required to run reliably even if the app exits or the device restarts" (source) I feel that utilizing AlarmManager is the best way to handle what it seems that you are trying to do.
However, it should be noted that this will still require the alarms to be re-registered on every boot, which may seem difficult given OP's questions and concerns, but I have addressed those below. Though, you should be careful about what you do if you boot after an alarm was supposed to trigger. For example, suppose you are making an reminder app that you would like to be able to schedule notifications to go of and happen stance your phone powers off just before a reminder was supposed to be triggered and it powers on 5 minutes after it was supposed to be triggered. Do you still trigger the notification? Do you reschedule it with AlarmManager? Do you just ignore it all together? If you do trigger it, do you want it to be triggered before the user unlocks there device or is after they unlock the device acceptable?
The above questions are things that would change the exact implementation, however the basics are the same across the board.
Register an intent receiver with the system
<application>
<!-- ... -->
<receiver android:name="RECEIVER_NAME">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<!--<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/> this action is sent before the user unlocks their device-->
</intent-filter>
</receiver>
<!-- ... -->
</application>
Re-register alarms with the AlarmManager in the BroadcastReceiver
public class PollReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
if (intent.getAction() != null) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, PollReceiver.class);//this will send the intent back to this class, you can make another broadcast receiver for handling the alarm going off though
i.setAction("ALARM_ACTION");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, i, 0);
long triggerTime = System.currentTimeMillis() + 60000; //replace this with when you want your alarm to go off (this will trigger 1 minute from now)
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
} else if (intent.getAction().equals("ALARM_ACTION")) {
//Show notification or make noise, whatever you are supposed to do when the alarm goes off
}
}
}
}
Addressing the various questions/concerns throughout the question
QUESTION 1: Can the simulator not simulate [reboots] correctly?
It can, however, the issue is that you are running the project to start the emulator, which is not how a phone is powered on. Rather than pressing the run button in Android Studio to start the emulator, you should start the emulator by itself via Tools > AVD Manager > Play Button (under the actions column for the corresponding AVD) or see below for a way to restart the AVD while it is running.
I would think I could dump logs somehow to android studio?
Yes, you can, at the bottom of Android Studio there should be a tab named Logcat. This tab is where any connected virtual devices or physical devices will output logs (you will have to specify which device you would like to view if there are multiple connected). Also, there is the option to use the command line, via adb logcat, or it is also possible via the command line to trigger a reboot via adb reboot. You can also combine the two so that as soon as the phone is able to have adb connected you start listening to logcat, via adb reboot && adb wait-for-device logcat. This works for both physical devices as well as the emulator, the only issue is that this outputs the logs for everything, if you want to search for specific text you can use adb reboot && adb wait-for-device logcat | grep "string-to-search-for" (Windows can replace "grep" with "findstr")
WEIRD SCENARIO 1: If I have TWO android studio projects open and open my personal app and then open the sample link app AFTER my project, I see a Toast "Alarms scheduled". I however can find no logs on PollReceiver until that alarm goes off 5 seconds later. I was expecting to see a log from PollReceiver on start but never see that until 5 seconds. Another run of this later yielded no logs (except the toast message popped up so I know it ran that code...very weird). I added a log message then to ScheduledServiceDemoActivity and now I can't reproduce 0 logs like that one time.
The behavior you describe in the first part is correct and should happen regardless of how many Android Studio projects you have open and which app is run first. The application makes a repeating alarm that will go off in 5 seconds and then every 15 minutes after. If you added the log to the onReceive method, you won't see it until that method is called, which it isn't until the alarm goes off. As for the second part, where you didn't get any logs, you may not have let the application run for 5 seconds so no logs would be printed. It should be noted that when you run the application through Android Studio it is not exactly the same as if you run it from the phone by clicking on the icon. Which would also explain why you were unable to recreate it after adding the log into the activity.
WEIRD SCENARIO 2: I REBOOT the phone(or it keeps launching my app and scenario 1 keeps working). Then I ONLY boot the sample link app, nothing ever happens. I wait for 90 seconds and nothing.
The sample application should trigger a log approximately every 15 minutes, not 90 seconds (900,000ms not 90,000ms). However, the sample application should trigger a log 5 seconds (not exactly 5 seconds though because of the way Android works) after starting the app, or after a reboot.
I can never get PollReceiver to fire on startup. ScheduledServiceDemoActivity seems to be the true entry point and I never added a service to my above code as I didn't want one...just wanted to be notified of being booted up to reschedule alarms. This then leads me to the possible conclusion the ScheduledServiceDemoActivity is there to fire on certain devices on bootup and the PollReceiver is for other devices on bootup? If so, what simulators can simluate this other bootup scenario?
You should really familiarize yourself with the application lifecycle and activity lifecycle. ScheduledServiceDemoActivity is there to be what opens when you start the application via running in Android Studio or by pressing its icon on the launcher, but the BroadcastReceiver is also another entry point for the application. In this case, it is triggered when Android sends an Intent with the action ACTION_BOOT_COMPLETED. ScheduledServiceDemoActivity will never be started on boot. The bundled AVD can properly simulate the bootup scenario and it will trigger PollReceiver.
EDIT (I had another thought) On my samsung phone, I checked the permissions and there is only THREE even though I added these 4 lines in my manifest
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- so we can send a text -->
<uses-permission android:name="android.permission.SEND_SMS" />
<!-- So we can reschedule alarms that went off while powered off -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- read contacts so they can easily choose their friends -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
The receive boot is not in there. is this the issue? OR do phones not list the receive boot completed to users as it might be confusing?
Most variants of Android (if not all) that come on devices will not display the permissions that are considered "normal" by Google. Essentially the only permissions that will be displayed there are the ones that are not automatically granted at install time and are considered "dangerous" as they can impact the user's stored data or the behavior of other apps.
Well, I found the answer
Android 8/9 Notification scheduling
I had no idea you have to google for versions.
I am using Notifications.local.scheduleNotification to schedule a notification. However, if the phone is rebooted before the fire event, the notification does not fire.
I would like to have the app start when the phone boots up so that I can add the notification to the alarm manager again. In the android manifest I would be asking for the following permission.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
How can this be implemented in smartface?
Today, this is not supported by Smartface, but there will be plugin support soon, you can write your own plugin and use it.
Also for licenced users, there is an option to ask for new implementations. If they need some new features, they can report them to Smartface team, and these features will be added to road map.
My app set PenddingIntent in AlarmManager.I kown this PenddingIntent will be keep in AlarmManger and the PendingIntentRecord is saved in ActivityManagerService.So when my app
be killed,it has nothing to do with the AlarmManager calling the ActivityManagerService do
the penddingIntent in the future.But the fact is not.I find the logcat would output the log
03-13 09:32:43.149 462-475/? I/AlarmManager﹕ Remove <my package> from mIntentHisRW
03-13 09:32:43.159 462-475/? I/AlarmManager﹕ record removed
I just can't find where does the log produced in source code.And How does AlarmManager works when app killed?
Thanks in advance.
If your app is killed by the user(stop app in the settings),the Android OS will think that it is the user's desire that this app should not be working any more.So the Android OS will remove the AlarmManager record.
I have not found this log too,maybe your ROM's developers added it.
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
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().