I am trying to get user location with low battery consumption and without GPS (location). Milimetric coordinates are not necessary for me. So I decided to use
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
and also at this google developer docs https://developer.android.com/guide/topics/location/strategies.html it says:
Permission for ACCESS_COARSE_LOCATION allows access only to
NETWORK_PROVIDER.
I dont actually understand why this API doesn't give user current coordinates without location being enabled. In my opinion, if I use COARSE_LOCATİON instead of FINE_LOCATION, API should not use location.
I am also trying "Basic Location Sample" at https://github.com/googlesamples/android-play-location/tree/master/BasicLocationSample
You are requesting for user's LOCATION it may be with FINE LOCATION or COURSE LOCATION. User needs to AUTHORIZE the app for doing that.
The only difference is that the device will spend less energy trying to get the user's location and won't get exactly location.
Google is informing by email of changes to the Android location permissions:
We’re making a change on October 15th, 2016 that will affect apps
targeting API version 21 (Android 5.0, Lollipop) or higher that use
ACCESS_FINE_LOCATION but don't explicitly have the
"android.hardware.location.gps" uses-feature. Going forward, these
apps will be available to install on devices that don't have GPS
hardware. In most cases this won't be an issue since Wi-Fi and Cell-ID
based location provides high enough fidelity for the typical operation
of these apps. However, any apps that require GPS hardware, such as
GPS navigators, should explicitly add the
"android.hardware.location.gps" uses-feature to their manifest.
If your app requires GPS to function properly and you do not include
in your manifest declaration, your users may have a poor app
experience.
Also, if you’re using the fused location provider and wish to receive
the most accurate location samples from GPS (i.e. with
PRIORITY_HIGH_ACCURACY), you must include the
"android.hardware.location.gps" feature in your app’s manifest to
ensure that Google Play only distributes your app to devices with GPS
sensors.
You can read more about this change in the Android Developers Help
Center.
From the Android Developers Help Center
In order to receive location updates from NETWORK_PROVIDER or GPS_PROVIDER, you must request the user's permission by declaring either the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission, respectively, in your Android manifest file. Without these permissions, your application will fail at runtime when requesting location updates.
If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then you need to request only the ACCESS_FINE_LOCATION permission, because it includes permission for both providers. Permission for ACCESS_COARSE_LOCATION allows access only to NETWORK_PROVIDER.
Caution: If your app targets Android 5.0 (API level 21) or higher, you must declare that your app uses the android.hardware.location.network or android.hardware.location.gps hardware feature in the manifest file, depending on whether your app receives location updates from NETWORK_PROVIDER or from GPS_PROVIDER. If your app receives location information from either of these location provider sources, you need to declare that the app uses these hardware features in your app manifest. On devices running verions prior to Android 5.0 (API 21), requesting the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission includes an implied request for location hardware features. However, requesting those permissions does not automatically request location hardware features on Android 5.0 (API level 21) and higher.
I am using the fused location provider, targeting API 21, and using ACCESS_FINE_LOCATION. I don't specifically care whether GPS is available, only that the most accurate location is reported.
Based on the first quotation, I think I do not have to make any changes.
Based on the second quotation, I think I need both android.hardware.location.gps and android.hardware.location.network. Or is this only for LocationManager and not fused location?
Do I need android.hardware.location.gps and android.hardware.location.network or not?
The second quotation is telling you that you need either android.hardware.location.network or android.hardware.location.gps, if you specifically need one or the other location provider.
If you want updates via GPS, you need android.hardware.location.gps.
If you want updates via the WiFi and cellular networks, you need android.hardware.location.network.
If you want updates from both the network and GPS, you should include both <uses-feature> elements.
If you don't specify either, your device may be installed on devices without that provider. For example, it may be installed on a device without a GPS, cellular network, or Wi-Fi chip.
In other words, getting location requires either the network location feature or the GPS feature. If you don't declare that your application needs one or the other, you may not get location updates at all.
API 21 vs 20 and below
Note that the above is only true for API 21 and above.
Prior to API 21, requesting the ACCESS_COARSE_LOCATION permission implied the location.network feature, wheras requesting ACCESS_FINE_LOCATION implied the location.gps feature (see <uses-feature>).
The only change right now is that, for API 21+, any app requesting ACCESS_FINE_LOCATION will soon be available to install on devices without GPS. If your app previously assumed GPS was available (and needs GPS), you need to make sure you have the explicit request for android.hardware.location.gps.
Google says that network location providers are now good enough for a fine location, thus, the change.
TL;DR: No, you don't have to add uses-feature to your manifest, but depending, you might.
complete answer:
uses-feature of the manifest is only so that Google Play can filter out devices that does not contain a feature that is necessary for the application to execute correctly. (Examples are GPS for a turn-by-turn navigation app, or Camera for a camera app).
Read carefully this quote:
any apps that require GPS hardware, such as GPS navigators, should explicitly add the "android.hardware.location.gps" uses-feature to their manifest
(...)
and wish to receive the most accurate location samples from GPS
As you mention, you only care that the FusedLocationProvider gives you the best location available to the device is installed. That means, even though you're requesting PRIORITY_HIGH_ACCURACY, your app might get installed on devices that does not contain GPS and will never get a location as accurate as a GPS, or maybe even (in some very rare odd case), be installed on device that does not contain any location provider.
edit:
Based on the second quotation, I think I need both android.hardware.location.gps and android.hardware.location.network. Or is this only for LocationManager and not fused location?
I just went digging on the docs https://developer.android.com/guide/topics/manifest/uses-feature-element.html#hw-features and found it very interesting, there're 3 possibilities:
android.hardware.location
android.hardware.location.gps
android.hardware.location.network
so based on that, if your application cannot work without any form of location you should use the first one android.hardware.location, else, if your app uses location but it's not essential to its funcionality, you can be free to not include anything
Quick and simple solution:
App needs to updates via GPS use android.hardware.location.gps.
If you want updates via the WiFi and cellular networks, you need android.hardware.location.network.
Add below lines to your manifests file based on your location data requirements:
<uses-feature android:name="android.hardware.location.network" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
Hope this helps..
From my understanding, it is sufficient to read the documentation for the uses-feature element to understand how applications are filtered in Google Play based upon implicit and explicit uses-feature entries:
Google Play filters the applications that are visible to users, so that users can see and download only those applications that are compatible with their devices. One of the ways it filters applications is by feature compatibility.
To determine an application's feature compatibility with a given user's device, Google Play compares:
Features required by the application — an application declares features in elements in its manifest
with...
Features available on the device, in hardware or software — a device reports the features it supports as read-only system properties.
...
If a feature is explicitly declared as being required, Google Play adds the feature to the list of required features for the application. It then filters the application from users on devices that do not provide that feature.
If a feature is explicitly declared as not being required, Google Play does not add the feature to the list of required features. For that reason, an explicitly declared non-required feature is never considered when filtering the application. Even if the device does not provide the declared feature, Google Play will still consider the application compatible with the device and will show it to the user, unless other filtering rules apply.
The implicit uses-feature items for location permissions are:
ACCESS_COARSE_LOCATION
android.hardware.location
android.hardware.location.network (Only when target API level is 20 or lower.)
ACCESS_FINE_LOCATION
android.hardware.location
android.hardware.location.gps (Only when target API level is 20 or lower.)
The change described in Google's email message is that the implicit uses-feature items for android.hardware.location.gps will not be present in API 21+ with ACCESS_FINE_LOCATION. The analogous situation appears to be true for ACCESS_COARSE_LOCATION and android.hardware.location.network.
Google encourages explicit enumeration of all uses-feature entries, but still provides implicit entries based on permissions. From the following documentation excerpt, I think there is no difference between omitting a uses-feature and declaring it not required, unless there is an implicit uses-feature entry.
If a feature is explicitly declared as not being required, Google Play does not add the feature to the list of required features.
Your application's use case determines what uses-feature entries should be present. Here are some example use cases, with all uses-feature entries being required unless otherwise stated:
Application uses GPS explicitly from LocationManager or application needs GPS' high accuracy. This is the example given in Google's email.
ACCESS_FINE_LOCATION
android.hardware.location (implicit)
android.hardware.location.gps (implicit up to API 20)
Uses Network location explicitly
ACCESS_COARSE_LOCATION
android.hardware.location (implicit)
android.hardware.location.network (implicit up to API 20)
Uses both GPS and Network
ACCESS_FINE_LOCATION
android.hardware.location (implicit)
android.hardware.location.gps (implicit up to API 20)
android.hardware.location.network
Uses at least one of GPS and Network. This is my FusedLocationProviderApi case in the original question.
ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION
android.hardware.location (implicit)
Uses location if available, still allows application installation if not available
ACCESS_FINE_LOCATION
android.hardware.location required=false (override implicit)
android.hardware.location.gps required=false (override implicit up to API 20)
Yes you need both the permissions if you are using fused provider.
ACCESS_COARSE_LOCATION - To receive location updates from NETWORK_PROVIDER. Adding android.hardware.location.network feature permission is enough.
ACCESS_FINE_LOCATION - To receive location updates from both NETWORK_PROVIDER and GPS_PROVIDER. You should add both android.hardware.location.gps and android.hardware.location.network feature permissions. Applicable for also fused location.
On your first point:
Based on the first quotation, I think I do not have to make any
changes.
You don't need to make any changes because you are using FusedLocation which automatically detects GPS and NetworkProvider as per availability and gives you the best estimate location (You need to add ACCESS_FINE_LOCATION permission to get High Accuracy). So even if you're targeting API above 21 you don't need to change anything in your app -FusedLocation will work as before.
And on your second point:
Based on the second quotation, I think I need both android.hardware.location.gps and android.hardware.location.network. Or is this only for LocationManager and not fused location?
You just need to ignore it because you're using FusedLocation API and you are not using LocationManager API which you replaced by FusedLocation. So second Quotation is only for apps which use LocationManagar.
NETWORK_PROVIDER and GPS_PROVIDER are part of LocationManager Not FusedLocation API
I have a GPS app that already requests ACCESS_FINE_LOCATION permission in the manifest, now I want to add a library (MoPub) that requires ACCESS_COARSE_LOCATION.
Am I correct in assuming that ACCESS_FINE_LOCATION is enough, and I can leave out ACCESS_COARSE_LOCATION from my manifest?
https://developer.android.com/guide/topics/location/strategies.html#Permission
Note: If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then you need to request only the ACCESS_FINE_LOCATION permission, because it includes permission for both providers. (Permission for ACCESS_COARSE_LOCATION includes permission only for NETWORK_PROVIDER.)
In short: yes, you don't need ACCESS_COARSE_LOCATION if you've already defined ACCESS_FINE_LOCATION.
Depends on your needs.
Permission wise, ACCESS_FINE_LOCATION includes ACCESS_COARSE_LOCATION. However, there is a catch:
ACCESS_COARSE_LOCATION gives you last-known location which is battery friendly
https://developer.android.com/training/location/retrieve-current.html#setup
For example, if your app does something like location-based recommendations, last-known location is good enough.
This has a dependency on Google Play Services
However, if you need something like live/ real-time location like Pokemon Go, use ACCESS_FINE_LOCATION
It gives you live/ real-time location. You'll need to use a LocationListener
Last time I checked, this does not require Google Play Services
Update
On Android 12 (API level 31) or higher, users can request that your app retrieve only approximate location information, even when your app requests the ACCESS_FINE_LOCATION runtime permission.
To handle this potential user behavior, don't request the ACCESS_FINE_LOCATION permission by itself. Instead, request both the ACCESS_FINE_LOCATION permission and the ACCESS_COARSE_LOCATION permission in a single runtime request. If you try to request only ACCESS_FINE_LOCATION, the system ignores the request on some releases of Android 12.
Check this url: https://developer.android.com/training/location/permissions#approximate-request
Difference:
https://developer.android.com/training/location/permissions#accuracy
https://developer.android.com/training/location/permissions#approximate-request
You need to ask for both permissions.
Approximate
Provides an estimate of the device's location, to within about 1 mile (1.6 km). Your app uses this level of location accuracy when you
declare the ACCESS_COARSE_LOCATION permission but not the
ACCESS_FINE_LOCATION permission. Precise
Provides an estimate of the device's location that is as accurate as possible, usually within about 160 feet (50 meters) and sometimes
as accurate as within 10 feet (a few meters) or better. Your app uses
this level of location accuracy when you declare the
ACCESS_FINE_LOCATION permission.
If the user grants the approximate location permission, your app only
has access to approximate location, regardless of which location
permissions your app declares.
Your app should still work when the user grants only approximate
location access. If a feature in your app absolutely requires access
to precise location using the ACCESS_FINE_LOCATION permission, you can
ask the user to allow your app to access precise location. ``
Then in Android 12 permission changes
On Android 12 (API level 31) or higher, users can request that your
app retrieve only approximate location information, even when your app
requests the ACCESS_FINE_LOCATION runtime permission.
To handle this potential user behavior, don't request the
ACCESS_FINE_LOCATION permission by itself. Instead, request both the
ACCESS_FINE_LOCATION permission and the ACCESS_COARSE_LOCATION
permission in a single runtime request. If you try to request only
ACCESS_FINE_LOCATION, the system ignores the request on some releases
of Android 12.
My app only needs very rough location data, so I originally set my manifest permissions to ACCESS_COARSE_LOCATION, and set up a location listener for NETWORK_PROVIDER. This gave me exactly the kind of rough location estimate I needed, but only with Google Location Services turned on.
I was expecting that if the user only had GPS enabled, that I would still receive a rough estimate of their location. But it seems like the only way to get ANY location information from the GPS_PROVIDER is by using the ACCESS_FINE_LOCATION permission.
So, is it true that with only GPS enabled, an app cannot receive location information unless it has the ACCESS_FINE_LOCATION permission? In other words, the GPS_PROVIDER can't send rough location estimates if the app only has ACCESS_COARSE_LOCATION permission?
So, is it true that with only GPS enabled, an app cannot receive location information unless it has the ACCESS_FINE_LOCATION permission?
Generally speaking, yes.
Quoting the documentation for LocationManager:
If your application only has the coarse permission then it will not have access to the GPS or passive location providers. Other providers will still return location results, but the update rate will be throttled and the exact location will be obfuscated to a coarse level of accuracy.
In other words, the GPS_PROVIDER can't send rough location estimates if the app only has ACCESS_COARSE_LOCATION permission?
Quoting the Android 4.2 release notes:
Compared to previous versions of Android, user location results may be less accurate if your app requests the ACCESS_COARSE_LOCATION permission but does not request the ACCESS_FINE_LOCATION permission.
To meet the privacy expectations of users when your app requests permission for coarse location (and not fine location), the system will not provide a user location estimate that’s more accurate than a city block.
However, I am assuming that this does not supersede the "will not have access to the GPS" statement from LocationManager. I assume that this means that NETWORK_PROVIDER data might be inhibited, if it is deemed too accurate.
I am trying to figure out if I really need to request ACCESS_FINE_LOCATION or not. I do not need really accurate coordinates. However, if cell towers or WiFi is not available, I want to be able to get a location from GPS (low accuracy is fine). But, I cannot find a clear answer in the Android documentation about this. Below is what the Android Docs say (ACCESS_COARSE_LOCATION). It tells me that requesting the coarse location gives me info from the "Cell-ID, WiFi" source and that requesting the fine permission will use GPS, but it says nothing about GPS being any type of fallback for when only the coarse location permission is requested.
public static final String ACCESS_COARSE_LOCATION
Since: API Level 1
Allows an application to access coarse (e.g., Cell-ID, WiFi) location
Constant Value: "android.permission.ACCESS_COARSE_LOCATION"
public static final String ACCESS_FINE_LOCATION
Since: API Level 1
Allows an application to access fine (e.g., GPS) location
Constant Value: "android.permission.ACCESS_FINE_LOCATION"
I think this other post and the Android documentation it references answers this question. The Android doc says the following.
Note: If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then you need to request only the ACCESS_FINE_LOCATION permission, because it includes permission for both providers. (Permission for ACCESS_COARSE_LOCATION includes permission only for NETWORK_PROVIDER.)
So, if I'm reading that right, requesting ACCESS_COARSE_LOCATION can't pull from GPS because it does not request access for the GPS_PROVIDER.