This is more of a general question, but to what extent can we use the Nearby Connections API in services?
I noticed that discovery and pairing is still working while the app is out of focus, so is it possible to extract the whole connections client into a foreground- or even a background service which is running while the app itself doesn't have to?
There are no restrictions on using Nearby Connections from a service. However, Android has always somewhat aggressively killed background services (and is more aggressive since Android Oreo). There's also no way to limit the power, so advertising, scanning, and maintaining a connection for a long period of time will adversely effect battery life. There's a plan to expose a low power flag, but there's no ETA.
Disclaimer: I work on Nearby Connections
On devices running Android Q or higher, an ACCESS_FINE_LOCATION permission has to be requested to use Nearby Connections. When an app runs a background service, like a JobService, using Nearby Connections on a device running Android Q or higher, the app will not be able to discover nor to advertise, unless the ACCESS_BACKGROUND_LOCATION permission has been granted to the app by Google. To get it granted by Google, you have to explain in detail why your app needs it, and there is no guarantee that you will get it. This said, on Android versions lower that Q, an app can successfully discover and advertise in a background service, as long as it has requested all the nedded permissions (BLUETOOTH, BLUETOOTH_ADMIN, ACCESS_WIFI_STATE, CHANGE_WIFI_STATE and ACCESS_COARSE_LOCATION).
Related
I have a security system where moving a Bluetooth LE device causes my android application to do some work. After some of the newer Android updates, I believe API 26, I could no longer get these updates if the Android device's screen was off. I was trying to think of a way around this and came up with an idea:
What if I paired the Android device and the Bluetooth device - would this allow for the message to be received when the Android screen is off?
Previously, all my BLE devices were part of a mesh, so I would regularly have the Android app check for changes in the mesh and turn the screen on to notify the user if needed. Now, because of the background execution limits introduced, I must require the Android device to have the screen on at all times, which leads to the death of display over time.
I'm not that great at programming in C, which is the language the BLE chips are programmed in, so I wanted to ask this first before spending hours just to see this NOT work. So, just to repeat the question: Will having a BLE device paired with the Android device allow a message through these restrictions when the Android screen is off?
If not - is there a way I can make this work?
Thank you for any info!
Use notifications instead of advertisements. This will deliver data instantly and works even if the screen is off. Newer versions of Android have introduced more restrictions for BLE scanning when the screen is off.
Use connectGatt with autoConnect set to true to automatically connect and reconnect in case the connection drops.
Use a Foreground Service in your app process to prevent the app process from being killed. If your app process exits, all Bluetooth connections are dropped as well.
You could use CompanionDeviceManager to gain some extra permissions.
You don't really need to be paired but it has some benefits such as faster connection setup and correctly remembering the address type (flaw in the API that this is missing).
Some surveys and analytics showed that users very often turn down Location Permission request appearing in the mobile app even if this permission is crucial for the app, e.g. the app performs automatic scan for devices in a venue that handle business logic and exchange data with the mobile app. The permission request turn down rate is so high that it becomes problematic for business. Is there any way in Android to avoid this, e.g. to declare some verified devices that can be scanned without permission request? I thought of https://developer.android.com/guide/topics/connectivity/companion-device-pairing but it also means popping up requests for manual work for the user. Is there any way today to do it behind the scenes?
Unfortunately this is not possible for privacy and security reasons. Enabling BLE on Android devices goes hand in hand with the location permission. The only possible workaround for this is potentially if you use classic Bluetooth instead of BLE. I am not 100% sure about this one, but it is mentioned in this article:-
No one can use BLE scan API without having Location Permissions, and,
on most devices, it is useless without active Location Services.
However, Bluetooth Low Energy is an extension to so-called Bluetooth
Classic and interestingly enough Google decided this API does not need
location permissions to be called.
This is an OS requirement which cannot be overcome. You might've already seen this on the Android developer page for BLE:-
In order to use Bluetooth features in your application, you must
declare two permissions. The first of these is BLUETOOTH. You need
this permission to perform any Bluetooth communication, such as
requesting a connection, accepting a connection, and transferring
data.
The other permission that you must declare is ACCESS_FINE_LOCATION.
Your app needs this permission because a Bluetooth scan can be used to
gather information about the location of the user. This information
may come from the user's own devices, as well as Bluetooth beacons in
use at locations such as shops and transit facilities.
You can find more info about this here:-
The Ultimate Guide to Android BLE Development
Location needs to be enabled for BLE on Android
Bluetooth versus Location Permission
I'm working on an Android app that needs to detect if other users of the app are close to each other (lets say within the same room or Bluetooth range). The app needs to be able to detect this without any user interaction.
Geolocation is not an option as this is too inaccurate indoors.
The app runs only on company owned phones that stay on company ground, privacy is not a concern.
All devices are always connected to the same wifi network and BT is always enabled.
My idea is to detect if users are within a close distance of eachother by periodically Bluetooth scanning and checking the results against a list of MAC adresses that contain all the devices that have the app installed.
The MAC adresses of all devices are send to a server, the devices then grab this list of mac adresses from the server to compare to the results of a BT scan.
Problem is, BT and Google's seem to use Advertisement / Discovery patterns where one device acts as the server and one device acts as the client. For this to work properly i feel like the devices need to always be discoverable.
Will an implementation based on Google's Nearby or BT work for my needs ?
Is it possible to detect the presence of a nearby device without it being discoverable ?
As battery life is a concern (need to be able to do this for atleast 8 hours a day) is BLE an option?
You can almost certainly handle 8 hours a day if the phones aren't really used for much else. There are a lot of variables, however.
Many older phones require a different type of scanning using infinite scanner restarts in order to properly report "seeing" a peripheral. This can dramatically decrease battery life.
If the phones are running Marshmallow or later, they have a doze mode which interrupts scanning. This can be circumvented using an AlarmManager, JobService/Dispatcher, or WorkManager. This can dramatically decrease battery life.
If the phones are running Oreo or later, they require a foreground service (persistent notification) in order to prevent the app from being automatically killed by the OS to save battery. The app should also be whitelisted from battery optimization because even with the foreground service, the app will still be killed off by the OS.
Finally, scanning and broadcasting and using location services is pretty expensive battery-wise. If you're attempting to cluster phones and guess their position based upon what other phones are nearby, at some level you'll still need the location data off of the phones to figure out where they're at.
You're much better off just scanning. You could carpet your company property with beacons, where each individual beacon's location is recorded. When the phone "enters a region" (comes within range of a beacon), it should send something to your api reporting which beacon it just found. This will tell you what room/area it's in.
Another less flashy (and potentially less accurate) way to track everything would be via the IP addresses of the wireless access points they're connected to. Use a WorkManager to periodically update an api with some unique ID for the phone and the IP address of the AP. Your IT department should know the locations of each of them. This way you get reasonably good tracking and virtually no battery drain.
google play store monitor the bad behavior of Excessive Wi-Fi Scanning in the Background.
not able to identify the issue
i have add bellow permission in manifest
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
please suggest appropriate response.
thanks
Assuming your app is using FusedLocationProvider. If you subscribe to retrieve location from GooglePlayServices in background more often than once per 15 minutes, your app will be blamed for excessive WiFi scanning.
https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest.html
Activities should strongly consider removing all location request when
entering the background (for example at onPause()), or at least swap
the request to a larger interval and lower quality.
If device is setup in high accuracy location mode, the device will attempt to use wifi scans in order to resolve its location. Hence you have to consider increasing active interval for retrieving location updates.
public LocationRequest setInterval (long millis)
Excessive Wi-Fi Scanning in the Background occur, Android vitals considers Wi-Fi scanning excessive when an app performs more than 4 scans per hour. Normally this issue can be reported by Android vital via play console. Otherwise we can use Battery historian tool to find background wifi scanning for each application.
We rectify this problem
If possible, your app should be performing Wi-Fi scans while the app is running in the foreground. Foreground services automatically present notifications; performing Wi-Fi scans in the foreground thus makes the user aware of the why and when Wi-Fi scans take place on their device.
My question is fairly simple. I would like to know what it is the best practice for my app so that it can be "Doze-proof". This is getting even more relevant as Android N will be applying Doze in more case scenario.
While reading Doze Documentation there is a part mentioning network access :
In Doze mode, the system attempts to conserve battery by restricting
apps' access to network and CPU-intensive services. It also prevents
apps from accessing the network and defers their jobs, syncs, and
standard alarms.
I believe Buetooth falls under Network Access, is that correct?
Since I do not own a Marshmallow (or Android N) enabled-device and since Emulator does not allow Bluetooth interaction I cannot really test my app behavior in Doze Mode.
Will Doze Mode kill any ongoing Bluetooth connexion? Does the same apply either for Bluetooth Classic and LE ? What about headsets with Bluetooth A2DP ?
My app must maintain this connection or else the core functionality will be broken.
Surely there is some kind of exceptions for such case where your device needs to be connected to a Bluetooth remote device for as long the user whishes too.
I know there exists a Doze Whitelist but it would seem it might not, in some cases, let the app behave as it would on a device below API 23.
Thank you for your help!
Looks like doze doesn't have any restriction on bluetooth per se but to do anything meaningful, you would need to keep the cpu on and wake locks are ignored in deeper doze.
If it's a core functionality of your app, you can try to ask users to whitelist your app. This can grant partial wake locks and keep the cpu on.
Foreground services are also exempted from any doze restrictions so that's another transparent way.