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.
Related
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.
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.
What I want to achieve
I am building an app for a shopping mall, with large amount of beacons installed not quite far away from each other (assume ~20m distance).
When a user walks in this mall, even without opening the app, the app needs to keep scan for beacons. When a beacon is detected, I will then query the server to ask if I need to and what local notification to push to user.
What I planned to do
My original plan was to create a Service, returns START_STICKY in onStartCommand() in order to make sure that the service will restart itself even the app is killed by a task manager.
This Service will keep scanning for beacons.
In fact, this is the existing approach of my colleague. According to this colleague, the service starts almost immediately after the app was killed by a task manager.
The problem
But soon I found that this approach is problematic.
The above approach has now 2 major problems:
It drains batteries because it keeps scanning;
It does not work on
Android 8 due to new limitations introduced in Android
8.
My next plan
Although I know that JobScheduler can be used to replace Service, which is also the existing approach of Android Beacon Library, perform a scan every 15-25 minutes absolutely cannot fulfill my requirements, where beacons are very close to each other and therefore beacons need to be scanned frequently.
Therefore I come up with another plan:
Use Android Beacon Library to run background detection
Once the
first beacon in filter list has been detected, start a foreground
service (which will not be killed even in Android 8) that
continuously scan for beacons
When all beacons in the filter has been exited, stop the above foreground service. Android Beacon
Library shall resume to its background detection state.
The intentions of this approach are:
Make advantage of Android Beacon Library's background detection which saves battery, according to their documentation
Step away of Android Beacon Library's handling of Android 8 due to its built-in limitation of long scanning interval
Scanning goes on even on Android 8 since I am going to use a foreground service
My major question
By reading documentations, I already know how to scan for beacons in the background.
But how do I make use of Android Beacon Library to scan in a foreground service?
Plus, is there any problem that you can discover in the above approach / Do you have any better suggestions to achieve such requirements?
My other question
In fact according to this post, the background service starts 5 minutes after an app is killed.
But by returning START_STICKY in onStartCommand() of a Service, it is restarted almost immediately.
Then, why will there be a 5 minutes delay, even in pre-Oreo?
This approach is sound. The Android Beacon Library 2.15+ natively supports foreground services as a scan mechanism for supporting cases like this on Android 8. See here for more info.
The tricky part is to switch back and forth between using Job Scheduler and a Service to do scanning. I have not tested this, but my suggestion would be to bind manually to the BeaconManager in a custom Application class.
Then :
On entering a region, stop monitoring and then unbind the BeaconManager.
Start a custom foreground service
In the foreground service, disable Scan Jobs, then bind to the BeaconManager and start ranging
Once no beacons have been ranged for a time, stop ranging, unbind from the BeaconManager, enable Scan Jobs, bind again and then start monitoring.
Finally, exit the foreground service
On the second question, yes, START_STICKY will very quickly restart a service on most platforms. The library uses a 5 minute timer with the AlarmManager as a backup, which will relaunch the service if a START_STICKY restart fails. Indeed, in typical use, the scanning service restarts much more quickly than five minutes.
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.
I have a VOIP app that I would like to always run in the background to make it responsive to incoming calls. Reading through some forums I found running the app in the background would cause a battery drain.
Are there good practices that I should follow so as to run the app in the background?
Reading through some forums I found running the app in the background would cause a battery drain.
It is more that having something run all the time increases your opportunity to drain the battery.
Are there good practices that I should follow so as to run the app in the background?
Being a VOIP app already violates some of the "good practices". For example, you will need to (try to) have a service that runs forever, to maintain your open socket connection to the VOIP server. And, depending upon how your networking is set up, you might need to try maintaining a WifiLock, which will drain the battery.
Generally speaking, then, you just want to make sure that your service is doing as little as possible except when a call is in progress. For example, while you may need to send packets over to the VOIP server periodically to keep your connection alive, try to do that as infrequently as you can.
There are many smart VoIP applications that use Push Notification feature. That will not eat up as much battery, but you must have a consistent internet connection. One such option is Axvoice. Check out their apps at: http://www.axvoice.com/support/mobile-voip-applications.html
They will also run in the background like other apps, but the difference between Axvoice and other apps is you can reduce battery consumption because it will not be communicating with live servers all the time. Please have a look at this: http://www.wikihow.com/Save-Battery-Power-on-an-Android
Use a Broadcast Reciever. It is documented here
http://developer.android.com/reference/android/content/BroadcastReceiver.html
A BroadcastReciever will execute it's code when the specified broadcast is broadcasted through the system. In other words when you receive a call the system sends out a broadcast saying that there is an incoming call. If your receiver is made to pick up on that broadcast than it will react. Think of it like the Android system is broadcasting a lot of different radio stations and a BroadcastReciever is like a radio. You can set it to pick up whatever broadcast you want and execute some code when it does.