Android: Disabling/enabling connections (network, bluetooth) at a given time - android

in order to save battery I'd like to switch off all connections (bluetooth, wifi, mobile network) and other power-consuming features at a given time (say 11 pm).
What is the best way to do this? I am thinking of a service that is started after booting so I do not have to restart the service manually. For the beginning I even don't need an app for the UI - I can hardcode the time for switching off. Maybe later it would be nice to be able to change the time via GUI but this is not really necessary.
So the only time the service needs to do something is at my desired time, however in order to detect the time it needs to run continously in the background without consuming too much energy.
What is the best way for this kind of job?

I guess this is what you're looking for:
https://developer.android.com/reference/android/app/AlarmManager.html
You can send a repeating alarm that will trigger a service on a specific time of the day to do (or any actions you want). Please refer below for setting the time on a specific time:
Intent myIntent = new Intent(AndroidAlarmService.this, KillNetworkService.class);
pendingIntent = PendingIntent.getService(AndroidAlarmService.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 23); //23 for 11pm
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
for my example, it will start the KillNetworkService.class everyday at 11pm, and from that service, you can now turn off your network.
Reference for alarm manager tutorial:
http://android-er.blogspot.com/2010/10/simple-example-of-alarm-service-using.html

Related

How to trigger the same action on 3 android emulators and 1 iOS emulator at the same time?

Currently I'm trying to set up a testing environment for researching purposes. What I'm trying to achieve is the following situation:
I would like to run 3 Android apps and 1 iOS app using emulators on my macbook. They are apps with a similar UI, but a different code behind. I would like to start the same action on all emulators at the same time, like pressing a button or calling a method.
I already tried to run the apps on the emulators and let them listen to a changing value in a realtime database on Firebase, so every time I changed the value in Firebase, all the apps would call the method. The problem with this set up is the delay between the apps because they rely on a stable internet connection.
Is there any other solution to trigger the action on all emulators at the same time? I would really appreciate the help!
Thanks
Edit based on answers and comments:
- I would like to choose whenever I want to run the action on the apps. This means that e.g. an alarm manager is a less preferable solution.
- I would like to avoid external network calls.
1)Try to use GCM/FCM and send command from server to all the emulators/devices and call the method on that GCM command.
2) Set the alarm using alarm manger for the particular time and call a method on that time.
You can achieve this in android using AlarmManager.
It will run at 18:32 (Set the time to future and run code on 3 android emulators, make sure all devices have same time)
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR));
cal.set(Calendar.HOUR_OF_DAY, 18);
cal.set(Calendar.MINUTE, 32);
cal.set(Calendar.SECOND, cur_cal.get(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
cal.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
cal.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
Intent intent = new Intent(ProfileList.this, IntentBroadcastedReceiver.class);
PendingIntent pintent = PendingIntent.getService(ProfileList.this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);

Why setInexactRepeating in alarm manager trigger inappropriately

This is strange, what is the reason method setInexactRepeating trigger approximately at given time rather then exact time.
I need to trigger alarm on every day basis at one particular time, i have said
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// Set the alarm's trigger time to 8:30 a.m.
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
I have set time 8:30 am in the calendar, when i shift device day to next day, alarm get trigger immediately even before i shift device time to 8:30am.
What is happening here, why i can't make exact trigger using this api, if any of you have experience this, could you share your experience. Thanks!
According to documentation (here) there is text:
As described above, choosing the alarm type is often the first step in
creating an alarm. A further distinction is how precise you need your
alarm to be. For most apps, setInexactRepeating() is the right choice.
When you use this method, Android synchronizes multiple inexact
repeating alarms and fires them at the same time. This reduces the
drain on the battery.
For the rare app that has rigid time requirements—for example, the
alarm needs to fire precisely at 8:30 a.m., and every hour on the hour
thereafter—use setRepeating(). But you should avoid using exact alarms
if possible.
With setInexactRepeating(), you can't specify a custom interval the
way you can with setRepeating(). You have to use one of the interval
constants, such as INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, and so on.
I hope it could help You bit. There is also small example for it in previous link I gave You.

AlarmManger malfunctioning in android ?

I have to call a service in every day on a particular time.obviously i had choose AlarmManager for waking up my service.and all working well other than AlarmManager triggering immediately when i set the past time.but it's working fine when i set time after current time.
For better clarification i will say an example.
WORKING ATTEMPT : Current time is 09.00 AM am setting schedule as
10.00 AM.And AlarmManager doing his job perfectly.
FAILURE ATTEMPT :Current time is 10.00 AM am setting schedule as
09.00 AM.And AlarmManager calls the services immediately.
Actually i need to invoke my service tomorrow 09.00 AM as the scheduled time is past.
I referred some query almost matching this one but it wasn't good enough.What i am doing wrong ?
My Code
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY,10);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
myIntent.putExtra(ACTION, ACTION_SC_1);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, REQUEST_CODE_SC_1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pendingIntent);
Dont use alarm manager use GcmNetworkManager which was introduced in the last IO. It will work like a charm and you will have the ability to set in to inexact alarm so u wont need to wakeup the device. From the google IO site : Google Play Services has added the GCM Network Manager which functions mostly like JobScheduler, but extends to prior releases before Lollipop.
From the documentation
Like set(int, long, PendingIntent), except you can also supply a period at which the alarm will automatically repeat. This alarm continues repeating until explicitly removed with cancel(PendingIntent). If the stated trigger time is in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval.
It is working intentionally like this.
As Bonatti said above, this is documented behaviour of the API when you set a time in the past.
You will need logic in your app to push out the alarm by 24hrs if it is already past 10am at the time when you want to set the alarm.
The easiest way to do this is probably to use the Calendar object as you have, then query
if (calendar.after(SystemClock.currentTimeMillis()) {
// Push alarm out til tomorrow.
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
If you need the alarm to be triggered at 9AM sharp, don't use setRepeating() as it will not launch at the exact time since Android KitKat (this is also documented, you should really read the docs).
Use Calendar to build the timestamp from your desired alarm time. Check if the result timestamp is smaller than the current timestamp System.currentTimeMillis(), in that case it's in the past so add 24 hours to it to schedule it for the next day.
Finally, use AlarmManager.set() on older versions or AlarmManager.setExact() on newer versions of Android to schedule your alarm. Once the alarm goes off, you can schedule the next one using the same technique.

Scheduling repeating alarms

I'm scheduling repeating alarms in order to execute service one a period of time.
// Set the alarm to start at approximately 24:05 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 24);
calendar.set(Calendar.MINUTE, 5);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, );
Some question about the implementation :
What happens if user delete the application (including the service), will something crash on the next alarm ?
Again if user delete the application, the alarms will continue running ? If so, how can I cancel any repeating alarms ?
Where/When is the best place/time to initiate the repeating alarms ? Should I wrap it with "only once" block ?
I'm not completely sure but I can give answers for your questions;
1- If user deletes your application and service, I think anything crash on the next alarm because I think your application is running on the service. (if there is no service, alarm does not works i think)
2- If user deletes your app, alarm will works but if service doesn't works, alarm does not works.
3- I think there is some options for repeating alarms and user can select one of this options.

Will AlarmManager work if my application is not running?

I have an alarm that works fine if i am interacting(using) with my application but it dose not works if I set it for next day and not interacting with my app.Therefore I am getting doubt is this because my application process is not running at that time.
here is what I am doing
Calendar calSet = Calendar.getInstance();
calSet.set(Calendar.HOUR_OF_DAY, selectedhour);
calSet.set(Calendar.MINUTE, selectedminute);
calSet.set(Calendar.YEAR, year);
calSet.set(Calendar.MONTH, monthOfYear);
calSet.set(Calendar.DATE, dayOfMonth);
alarm = new Intent(ActivityA.this, Service.class);
pendingIntent = PendingIntent.getService(getApplicationContext(), i++,alarm, 1);
alarmanager.set(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(),pendingIntent);
From AlarmManager
AlarmManager provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running. Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.
In simple way, it will work until your device has been rebooted.
You can read Android AlarmManager after reboot where #CommonsWare has been given a link of his sample application which persists Alarm even after device reboot.
Please ignore below section, it seems not valid. I will remove in future
You can read more about application kill at How to create a persistent AlarmManager, and How to save Alarm after app killing? can give you the idea about how to handle such issue (to persist alarm if application has been killed).
Yes it worked but proper understanding see doc.
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
see here http://developer.android.com/reference/android/app/AlarmManager.html
Looking at the AlarmManager documentation..
http://developer.android.com/reference/android/app/AlarmManager.html
I don't see anywhere where it states that killing your app will remove all alarms that have been scheduled by that app. More specifically it states if your app is not started, it will start it for you.
I have done my own testing and can validate this by..
Setting an alarm 5 sec in the future.
Then closing app from recents.
Then watching logs for my broadcast to be received.
Keeping in mind this was done with a signed apk.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MILLISECOND, 5000);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
I would also keep in mind what Pankaj Kumar said about the restarting alarms on boot. That is the one place you need to cover yourself, because AlarmManager does clear all alarms on device restart.
We need to enable our app in autostart manager in app manager, some handsets like Vivo v5,
In Vivo v5, we can find out this menu in
iManager > App Manager > Auto Start Manager > Enable our app here.
Then your alarm / alarm manager will trigger alarm if the app is killed or closed.

Categories

Resources