When the battery on my Android device dies what methods in the Activity and Fragment classes (if any) are called during the "Powering Off" stage of the device?
Also, if a user is currently looking at a screen in my app and they hold the power button and choose switch off, do the events called/not called coincide with when the battery is depleted and shuts down automatically?
OnPause?
OnStop?
OnDestroy?
OnDetach?
Bonus:
Will I have enough time to save a small amount of data to a web server?
To clarify "dies" when the device's battery is 'completely' dead, accepts no more input and a message box/loading screen pops up on the screen stating "Powering Off". Shortly there after the device switches off.
I just need enough time to save a forms state before the phone switches off, I have a strategy to clean the saved data should the phone not switch off, but I want to get as close to the phone switching off as possible (any more than a minute is pointless really).
onDestroy is called on everything when the battery reaches 0.5%
EDIT: There is no specified time that you have to do anything in the shutdown process resulting from low/dead battery, that would be dependent on the specific phone battery and not the system, so you may have enough time to save data to a web server on some phones but not others. Experimentally, I have only been able to write a short line to a file I was already writing to before onDestroy was called and nothing more.
The methods you have mentioned is activity life cycle callback, none of them will be called when battery is low. You need to use a broadcast receiver for this
See this How to detect when the Battery's low : Android?
Related
I'm making an app that keeps track of how many times the user uses their phone, meaning how many times they picked up/checked their phone everyday. I've searched through stackoverflow and other sites but I can't find any information that would help me implement this; any ideas? Is there a certain class I can use?
Use BroadcastService and IntentFilter to keep track of when the screen is turned on and off (ACTION_SCREEN_ON and ACTION_SCREEN_OFF). Each time the screen is turned on, increase a counter.
You could register for the ACTION_SCREEN_ON broadcast. Then just increment a counter (saved to disk just in case) each time its received. But you can't do that via the manifest, so you'd need to do it in a foreground service.
I have a bit of a unique issue. I'm collaborating with several other Computer Science Majors at my university on an Android Metronome app that allows two users with the app to sync metronomes. Right now, I can send the desired beats per minute of the metronome from one phone to the other and both phones will start to play their respective metronomes. Due to the latency of Bluetooth, the metronomes are only in sync about 20% of the time.
So, here's where the problem is. We're trying to make it so both of the metronomes will start at the exact same time. One way I've thought of doing this is once the first user presses the send button on their phone, a time stamp will be created. This time stamp will be exactly two seconds after the user presses the send button. The time stamp will then be sent to the second phone and the phone will utilize this time stamp to start it's metronome at the same exact time as the first phone. I've tried accomplishing this by putting UTC time in a while loop and then constantly checking the time, to no avail. Does anyone have any ideas as to how we can go about implementing this? I couldn't find any similar problem on StackOverflow, or any other website for that matter.
It's a bit late probably for your project, but if interested. This is a bit long, it's more like a case study.
If your project was about syncing two device clocks remotely, then this won't help you, but if it was about syncing the metronomes, then this may be a start.
First, getting millisecond accurate timings and callbacks in android using java is next to impossible, since android is not a real time system ( All sleep methods and timer might not execute on the exact millisecond you're expecting ). You may want to go with NDK for triggering your beat events, because native threads in android can achieve that, but if you're happy with your single metronome implementation, then that's good enough to read the rest of this .
Full disclosure :
I am the author of JAM the app referenced in the answer I just published a few days ago.
I ran into the same problem when developing the app.
And whether this answer will help you or not, depending on your situation.
and if you're going down the "clock sync" route ( Which I do plan on exploring to improve my app down the road with more features ) but the solution that I found did not involves time sync.
I will mention my approach and then state what I found as advantages/disadvantages for each of the methods .
Instead of syncing clocks ( A very difficult problem, especially for what the app was supposed to do , and that is trigger ticks on multiple devices at the "same" time ) I opted for a subscribe/publish model, where multiple devices can "subscribe" to a host device via bluetooth, and the host device controls and "publishes" the metronome beats.
most times sending a few hundred bytes ( Enough information about each beat ) via bluetooth takes less than 2ms , it could spike up to 10 and sometimes even 30, but that rarely seems to happen .
That approach took care of the syncing problem, now I can send beat events from one device to another in 2ms , and if some sort of delay happened, it will self correct once the interference is gone, because the other event comes in time.
However that approach does require constant connection, you can't start and separate the devices later on, but it's much easier to implement.
Now the interesting part, the problem I never thought of when starting this, and that was the Android 10 millisecond audio path latency problem. I'm not affiliated with superpowered, but I did use their engine in my app to deal with that problem .
To summarize :
Metronome sync over bluetooth in Android has two issues :
1 - triggering beat events simultaneously ( or within acceptable latency )
2 - The beat event should trigger sound events with minimal delay after the beat event is received
#1 is related to the original question, #2 I thought was an important addition to the original problem this question is asking.
I would use (S)NTP to check the clock drift to a public time server. After that I would just send the interval and a start time and let the devices calculate the interval individually. So you just need to sync changes and relay on the clocks of the individual devices. Together with the now known clock drift you can fix this error.
I've been working on developing an application that interacts with BLE devices. Everything works great, I can scan, connect, and consume services.
I've been reading through all the docs and I do not see anything that gives the developer the option of listening for BLE devices. Basically I would like to trigger a broadcast receiver when the devices enters the range of a BLE device.
I know I could continually scan for this, but battery use is way too high and I would like this to be invoked even when my application is not being used.
Is this feature not supported or am I missing a section of the docs that discuss this?
I have done a project recently, and from what I read in your question it has some similarity to what I did.
I know I could continually scan for this but battery use is way too high and I would like this to be invoked even when my application is not being used.
Regarding battery problem, having Bluetooth on all the time is power consuming, but at the same time you can not detect BLE with out having Bluetooth on.
What I did is two experiments and both are useful but are different and I can not say which one is best, but you need to test it so it fits your requirement.
Having Thread running that turns Bluetooth on and listen to iBeacon and off (with sleeping time) for while programmatically. It can be done many ways.
Using a package called Altbeacon, has a lot of useful features, one of those features is Auto Battery Saving with example code:
public class MyApplication extends Application implements BootstrapNotifier {
private BackgroundPowerSaver backgroundPowerSaver;
public void onCreate() {
super.onCreate();
// Simply constructing this class and holding a reference to it
// in your custom Application class
// enables auto battery saving of about 60%
backgroundPowerSaver = new BackgroundPowerSaver(this);
}
}
We need a broadcast event, that wakes up our app once a BLE-device with a certain Service-UUID is in reach. Maybe now there is a better BLE API available than 2 years ago. The most energy saving and most precise method gets rewarded.
Your other part, it is called triggering actions at a specific distance.
I still use the Altbeacon to check beacon range and triggering action. A sample code is something like
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
for (Beacon beacon : beacons) {
if (beacon.getDistance() < 5.0) {
Log.d(TAG, "I see a beacon that is less than 5 meters away.");
// Perform distance-specific action here
}
}
}
So when that said, you can also get distance of specific UUID I build a method based on Altbeacon, looks like this (Look inside the for loop and if statement):
private void startRangeNotifier() {
Log.i(TAG, "Starting range notifier...");
beaconManager.setRangeNotifier(new BeaconRangeListener() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
for (Beacon beacon : beacons) {
Log.d(TAG, "uuid's: " + beacon);
Log.d(TAG, "uuid id1: " + beacon.getId1());
if (beacon.getId1().toString()
.equals("b9407f30-f5f8-466e-aff9-25556b57fe6d")) {
Log.d(TAG, "uuid id1 distance: " + beacon.getDistance());
}
}
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(
new Region(BEACON_MONITORING_ID, null, null, null));
} catch (RemoteException e) {
e.printStackTrace();
}
}
My log output:
D/Main activity:: uuid's: id1: b9407f30-f5f8-466e-aff9-25556b57fe6d id2: 31807 id3: 59251
D/Main activity:: uuid id1: b9407f30-f5f8-466e-aff9-25556b57fe6d
D/Main activity:: uuid id1 distance: 0.2108658568686884
In my answer I wanted to present the concept I used, Beacons project need patience in general. As the other answer mentioned it is also possible to combine the solution here with Geofences and ActivityRecognition.
Note: Since the nature of bluetooth beacon, the distance is proximity and not absolute, and some time even the bluetooth beacon is 1 meter a way it might show 2 meter or 0.5 meter, so have that in mind
Link reference:
https://altbeacon.github.io/android-beacon-library/distance-triggering.html
https://altbeacon.github.io/android-beacon-library/samples.html
https://altbeacon.github.io/android-beacon-library/eddystone-how-to.html
https://github.com/AltBeacon/android-beacon-library-reference
BLE scanning on Android is pretty battery intensive, and it's definitely not something you want to do in the background all the time. If you are working on a background application with stationary bluetooth devices (à la ibeacons) that you know the location of, you can use Geofences to turn scanning on and off when you think you are in the approximate proximity of a device. If you are not careful geofencing can also drain battery.
If you don't know the location of your bluetooth devices I guess you can also play tricks with ActivityRecognition, i.e only scan periodically when the user is walking and stopping it if the user is stationary/running/biking/in vehicle. Again, the activity recognition stuff also takes battery so you are going to have to be judicious.
We need a broadcast event, that wakes up our app once a BLE-device with a certain Service-UUID is in reach.
You probably know how to filter scan results by Service UUID so I won't go into that. About the waking up: if your app is scanning, it is awake by definition. It may or may not be on the foreground, but it is awake.
Maybe now there is a better BLE API available than 2 years ago.
Since SDK version 21, there is a new API that you can use for BLE scanning. To my knowledge, the only difference is the way you access the API and the underlying functionality (regarding power consumption etc.) has not changed.
About the scanning:
It's true that scanning is battery-intensive. Even the docs say so.
The intensity is relative though. It is intensive compared to not scanning at all, but it is not intensive enough that it will hopelessly drain your battery. It's called low energy after all.
An other answer suggest monitoring Geofences and only scan when you know you are in range of BLE devices. While this will lower the battery consumption of the ble scan, it will need that battery power for the GPS, otherwise it can't monitor the Geofences (well, it can, with cellular/wifi data, but then it won't be nearly as accurate).
Depending on how time critical your scanning is (e.g. if there is a device nearby, must you know it right away? or is it okay if it's delayed a couple seconds?) you can implement a pause inbetween scans.
Say you scan for 5 seconds, pause for 5 seconds, scan for 5 seconds again. That way you will be scanning almost all the time, yet only consume roughly half of the battery power. These intervals can be tweaked to match your situation. Maybe you're okay with scanning 3 seconds and pausing for 10. (note that the maximum time between a device's broadcasts is 10.24 seconds).
I have an app with about 50 users that scans with pauses like this (scan for 3 seconds, pause for 3, repeat) 24/7 in the background, and have not received any complaints about excessive battery usage.
If you have a specific BLE peripheral you want to detect, then figure out its advertisement period. If you have different devices, find the longest advertisement period. Scan longer than the advertisement period of the device, so you get at least one advertisement message. Repeat this scanning periodically with the frequency that is suitable for your use case. E.g. Your peripheral is advertising every second once. You would like to detect the device in 5s when it comes to proximity. Then Scan for 1s (or a bit more). Switch off scanning for 4s. This way you can save battery.
My app is basically is a schedule app, where I'd like to show notifications x minutes before an (user-set) event occurs.
I read the documentation, but it only covers showing a notification at the time the notification code is being executed (which I guess is the only way).
My guess is that if I want to have notifications show up even when my app is closed, I need to somehow make the app run in the background and constantly check for upcoming events, calculate the time left, and show a notification when the time left equals the time before the event the user chose to be notified at.
I read this question (+answers): How to get android notifications when app was closed?.
There is a pretty detailed answer (using services) I could simply implement, but the other answer claims this approach is "crappy".
The second answer also suggest the usage of AlarmManager which, after reading the doc, doesn't sound that bad (executing code at a specific time).
However, since I'm targeting API19 it's "inexact" (according to the doc).
So what exactly is the most efficient (and the right) way to do this?
You need to implement alarm manager with service. Set the time user chose and show notification at that time. The sample shows a Toast, you can use notification/sound/dialog, anything.
Check out this sample.
For my application, I want to have a Notification sent to the user at a specified time. To do this, I have set up a Timer and the corresponding TimerTask.
To be sure the Notification will be sent to the user even if the phone is aslept, I have acquired a PARTIAL_WAKE_LOCK. The problem is that this method draws a lot of power from my battery (my application is responsible for more than 50% of all the power consumption at the end of the day).
Is there another way (a more power efficient one of course) to do what I want to do?
Thanks in advance for the time you will spend trying to help me.
> Is there another way (a more power efficient one of course) to
> [have a Notification sent to the user at a specified time]?
You can use an the android AlarmManager for this.
See Using AlarmManager to Schedule Activities on Android as a tutorial and example.