is there any way to keep a BeaconTransmitter instance sending forever?
The Problem:
I want a RPi detect when I am coming home independent of Wifi running or the RPi even having access to the internet (e.g. it could then turn on all routers etc., when it detects the phone).
I have a minimalistic app on my android phone sending out an iBeacon running and the beacontools Library on the RPi detects it. This is working well, in principle. (Although I know it's supposed to be the other way around, but I again, I want the RPi to be able to do "stuff" without having access to the internet, what the phone cannot do).
However, the power management(?) on the Android phone seems to stop the transmission, the latest after a few hours (even if the App is "not optimized" for battery usage). I am not even sure if this is because of the battery optimization or something else.
Solution so far:
I am using a PeriodicWorkRequest that checks every 30 minutes (I read somewhere this is the minimum time), if the beacon is still running and relaunches it, if it is not.
This also works as expected, but of course, I keep coming home in the time slot when the beacon transmission has stopped and before it is kicked off again by the WorkManager. ;)
A cleaner way would be to "intercept" when the BeaconTransmitter is killed by PowerManagement/BatteryManager(??) or something. Is that possible?
Those covid tracking apps are using something (I hope) that ensures continuous transmission, but I know that Google/Apple had to implement something fundamental to allow those to work, and of course, I cannot use the covid-tracking itself because it is anonymous by design.
A precise answer will vary by phone manufacturer as many OEM's fork Android to kill long-running apps in the background. See here for a summary of challenges by OEM.
For vanilla Android (Pixel phones, many Nokia Android Once devices), Motorola and even most Samsung devices, it is sufficient to keep a foreground service active and have Location always runtime permission. My BeaconScope app uses this foreground service technique, and I typically see a transmitter keep going for weeks on a Pixel or Samsung device. Be sure you grant "Always" location permission to the app for this to work.
You can see the code needed to set up the foreground service in the Kotlin reference app for the Android Beacon Library. The comments indicate that the foreground service is useful for continuous beacon scanning, but it is equally true that it is useful for long-term beacon transmission.
Without the foreground service, the beacon transmission will only last about 10 minutes after the app is put to the background on vanilla Android, at which time the app will be killed.
The problem with a periodic work request or a job service is that they can run at most every 15 +/- 10 minutes on Android. So if the transmitter is killed every 10 minutes you will end up with gaps of up to 15 minutes without transmission. On Android 8+ you have no choice but to use a foreground service.
Related
I have been following https://developer.android.com/guide/topics/connectivity/wifi-scan guide in order to create a Wi-Fi scanner. I am using a foreground service with a handler to call wifiMananger.startScan(); every 30 seconds (I tried with 15 minutes).
Everything works great for about 2 hours then suddenly WifiManager.EXTRA_RESULTS_UPDATED boolean returns false and the wifiManager.getScanResults() are not getting updated. Then as soon as the phone is plugged in it starts sending results again. (No, it is not low on battery)
I have battery optimization turned off. I have all of the required permissions allowed. Locations is turned on with Wi-Fi scanning enabled. The device I'm testing on is a Samsung S7 Edge running Android 8. So I know it's not the new OS. (I also tested with a Nokia 5.1 running Android 10 with pretty much the same results).
Does anyone know why this is happening or has anyone encountered this issue before?
Thanks in advance.
Updated: In case of your problem, since you are using exactly 30 seconds due to some problem there might be more than 4 time in a 2 minutes period, make it like 35 seconds and test the result.
Original Answer: From this WifiManager startScan throttled in P Beta (Developer Preview 2) :
"Call Limitations - Throttling
We are further limiting the number of scans apps can request to improve network performance and improve battery life.
The WifiManager.startScan() usage is limited to:
Each foreground app is restricted to 4 scans every 2 minutes.
All background apps combined are restricted to one scan every 30 minutes."
It is said that this restriction is due to the battery drain, so it is normal to remove the restriction while charging.
Read more about throttling in official documentation.
This is because Android OS enters the infamous "Doze mode". I recommend you to look through the official documentation/explanation.
Unfortunately, there is no way around this. It will also affect any kind of a foreground service and pause it for longer periods. Doze mode will only trigger if the screen is locked and the device is not plugged in.
I encountered the same issue on my project and we implemented a periodic check. If the screen is locked and device not plugged in for a longer period of time, we show a notification asking the user to either plug the device in or open the app so the service could keep working. The implementation is a bit lengthy, but if it is what you decide to go with, I can update the answer with some of the code (using the AlarmManager within a BroadcastReceiver to achieve this).
Google added restrictions of not broadcasting the Bluetooth switch states to the app when the app in the background. This effectively blocks the optimized Bluetooth beacon scanning in the background. How to get around this issue other than periodic job scheduling?
Any help is appreciated.
You have several options for background BLE Beacon Scanning on Android 8+
A regular background service. You can use these just like on Android 4.3-6.x, but you are generally limited to 10 minutes of running time in the background, after which time Android will kill your app and it won't be able to scan anymore.
Use a foreground service. These work much like Android background services except they display an even-present notification with an icon of your choice to indicate that your app is running in the background. With a foreground service, you can effectively scan for beacons in the background with no restrictions just like on Android 4.3-6.x.
Use Intent-based scans. If you simply need to know when a beacon appears or disappears, you can set up an Intent-based scan for BLE devices with a bluetooth packet filter that filters on the presence of the byte pattern of the beacon, or the absence of the byte pattern of the beacon. When the beacon appears or disappears, Android will send an Intent to a BroadcastReceiver in your app that will wake it up in the background and let it run for about 10 minutes before killing it. During this time you can keep scanning for beacons.
Use the job scheduler (also known as WorkManager). You can schedule a job to run at most every ~15 minutes in the background to do scanning. A job is generally limited to 10 minutes of running time in the background. Since start times vary by +/- 10 minutes, you'll have gaps of up to 0-15 minutes where you won't be scanning.
Play games with (3) and (4) to bend the rules. While this goes against the spirit of Android's restrictions, you can play games with the job scheduler by starting an immediate job, cancelling it before 10 minutes is up, then restarting it. You can do similar things with an intent based scan by simply triggering it over and over. Be forewarned, however, doing these things will drain the users' batteries, perhaps leading them to uninstall your app. This rule bending may be blocked in future Android releases.
You can read my blog post about the merits of these techniques here. The open source Android Beacon Library uses techniques 3 and 4 on Android 8+ devices by default, and also supports configuring a foreground service if you wish to choose option 2.
Currently i reading in official google doc news about Android 7.0
I can not understand a few things.
They wrote Doze improve battery life by turn off network and CPU when user block the screen.
But how this works ?
1.I have Marshmallow in my device, and when my phone is blocked, i still get notifications from app with network (e.g. Messenger).
2.Second thing they wrote Nougat have improved this more by again CPU and network. So what is exacly differet ?
I have Marshmallow in my device, and when my phone is blocked, i still get notifications from app with network (e.g. Messenger).
SMS does not usually go over the Internet, assuming that is what you mean by "Messenger" (many apps use that name). Plus, high-priority FCM push messages work despite Doze mode.
Second thing they wrote Nougat have improved this more by again CPU and network. So what is exacly differet ?
There is a "Doze on the go mode" that kicks in even if the device is moving. This is covered in the documentation and in the documentation.
Push Notifications will still get through, but most services will stop running after a while if you leave your phone sitting on a table with the screen off.
For example Spotify still keeps running smoothly because it has a foreground notification. The battery savings come from when the OS can shut down most systems such as internet and geolocation as well as avoiding running other services for increasingly longer periods of time,for example reaching stretches of hours by the end of a typical user's sleep at night.
Now they're mainly doing what they were saying for a long time: background services have no guarantees of how long they will run. The biggest unintended consequence is that sometimes when they wake up there's no internet or geolocation is not available. And the time they run is less predictable.
There's still ways to wake up and perform tasks with perfect predictability using exact alarms or push notifications, depending on where the event is generated. But for most cases the recommended solution is using job schedulers.
How can I start iBeacon while my app is not running.
I mean there must me some broadcast receiver which can be placed in my app's Manifest.
Edit:
As this question is misleading, let me rephrase it again:
I've created a project which detects the iBeacon
1. In activity running state.
2. In service.
If I want be get notified whenever an iBeacon gets detected, when application is not running I've got one option that is through Service. But that will drain the battery. So is there any broadcast receiver which an notify my app as soon as any iBeacon is detected.
The Demo code which I've written for this is:
https://github.com/Vinayrraj/Android-iBeacon-Demo
You simply have to run a service in the background to do this. Code has to run to detect iBeacons (e.g. Radius Networks' Android iBeacon Library). If you don't have a service running, then what is going to do the background detection?
Yes, anything running in the background will drain the battery, but it won't drain the battery much if it is sleeping most of the time. Reducing the scan frequency can save battery life. iOS7, for example, the OS only does a bluetooth scan once every few minutes when no foreground app is ranging for iBeacons.
So the solution to the battery problem is to reduce the frequency of the bluetooth scans in the service so they give you an acceptable trade-off between battery life and iBeacon detection speed. If you are using my company's Android iBeacon Library, then. you can adjust the constant for this to your liking.
EDIT: My company has released a "Pro" version of the Android iBeacon Library with a built-in ability to launch an app when one or more iBeacons are seen. It also includes an automatic battery saver to slow down bluetooth scans whenever your app is in the background. See code examples here: http://developer.radiusnetworks.com/ibeacon/android/pro/download.html
In order to do something on Android, you have to create an Application. In order to make something work, something that you coded, you need to run your app. So it is not possible to do something like what you want.
Sorry, mate.
Background:
Ideally I would like my Android device to be scanning for Bluetooth Low Energy devices all the time an the ability to start an application whenever a new device with specific properties appears.
So the broadcast packet in BLE will for instance enumerate a set of services provided by the broadcasting device. An app would then be able to register an interest for certain services and automatically be started when a device with this services comes into range.
From what I understand this is not how the Android BLE API works? So how can I get something similar?
Simplest possible example:
I have a BLE sensor that logs ambient temperature over time. Whenever my Android phone is close enough I want to connect and download all the data, sending it to some cloud storage solution. This app would not need any GUI (at least not after configuration is done). But how should it run in the background without draining the battery, but still give me a fairly good chance of connecting the device quickly once it is in range?
Question:
Do I need to set a timer and wake the app every once in a while and then manually start scanning? What kind of intervals should I then choose. How long can I leave the scanner running without adversely affecting the battery?
Possible solution:
This is what I've come up with so far.
A configuration activity to set the intervals and devices to scan for
The configuration activity will set up an WakefulBroadcastReceiver similar to the Scheduler example
When the receiver get's the onReceive event I start a BLE scan service (that I've written) as a wakeful service.
The scan service starts scanning (with a registered callback).
The service might get adv reports that it can act upon
After a timeout the service will stop the scanner and end the wakeful service.
This works, but I'm not sure it's the best way. I also don't know how small intervals I can have and still avoid destroying the battery life. What I would want is to start scanning every two minutes, scanning for 10-20 seconds. But I'm afraid that would be rather frequently to wake up the device?
This functionality has all been moved to the open source Android Beacon Library which will:
wake up/launch your app when iBeacons matching a desired pattern are detected
perform beacon scanning in the background even if the user has not launched your app yet
reduce the scan rate automatically in the background to 30 seconds every five minutes to save battery. (Timing configurable.)
Code examples are show here
If your BLE device is not a beacon you could still use this library to accomplish this by having your sensor also transmit as a beacon then after it is detected connect to the main service.