Location services permissions in Android

To enable MobileFirst location services for Android, you must define the proper permissions.

The permissions that you require differ for versions earlier than Android 6.0 Marshmallow and versions starting from Android 6.0 Marshmallow onwards.

Before Android 6.0 Marshmallow

In versions of Android earlier than Android 6.0 Marshmallow, the following permissions are required:

For Geo acquisition:
  • ACCESS_COARSE_LOCATION
  • ACCESS_FINE_LOCATION (when enableHighAccuracy=true)
For WiFi acquisition:
  • ACCESS_WIFI_STATE
  • CHANGE_WIFI_STATE

For Android 6.0 Marshmallow and later

In Android 6.0 Marshmallow and later, geo acquisition (location) permissions require additional runtime permissions.

Overview of runtime permissions

According to the Android 6.0 Marshmallow permissions model, in addition to defining permissions at installation, users must also allow or deny access to different features at runtime. Before an app accesses location services, it must check whether permission has already been granted and, if needed, request permission. Developers are responsible to perform the check before accessing any of the following methods in the WLDevice interface:

  • startAcquisition
  • acquireGeoPosition
  • stopAcquisition

If permissions have not been requested or not granted, the MobileFirst API does not get a provider and returns an error, WLGeoErrorCodes.PERMISSION_DENIED, along with a message about the requested accuracy level.

Checking and requesting permissions from the Android 6.0 Marshmallow API
Checking if permissions have been granted
Two levels of access permission are available from android.Manifest.permission:
  • android.Manifest.permission.ACCESS_FINE_LOCATION
  • android.Manifest.permission.ACCESS_COARSE_LOCATION
In the examples that follow and in the sample that is provided, these methods are inherited by the MainActivity from the android.app.Activity class. To check the status of the permissions, call checkSelfPermission with the appropriate access level, as follows:
getContext().checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
If permission has already been granted, the method returns the value PackageManager.PERMISSION_GRANTED.
Requesting permissions
To ask the user for permission for the appropriate level of access, use the inherited requestPermissions method, as follows:
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0);
Calling this Android method displays a dialog box that prompts the app to grant permission and invokes onRequestPermissionsResult when the choice is made. Once this permission has been granted to the system, startAcquisition, stopAcquisition, and acquireGeoPosition are granted access to the location services. If the user denies access, these methods return the WLGeoErrorCodes.PERMISSION_DENIED error. See the sample at https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-7-1/foundation/advanced-client-side-development/location-services-hybrid-applications/ for a full demonstration of how to handle the new Android 6.0 Marshmallow permissions model.
Using Android location services in a hybrid Android application environment
Android 6.0 Marshmallow requires user permissions to be granted at runtime. Because runtime JavaScript code in the web framework of the hybrid app does not have access to the Android API, these permissions must be requested and checked by the native code before launching Apache Cordova. The file <application name>.java in the native folder is responsible for loading the web resources. The code for requesting and checking permissions for location services can be called within the onInitWebFrameworkComplete API or within any other startup API in the class.
public void onInitWebFrameworkComplete(WLInitWebFrameworkResult result){
    if (result.getStatusCode() == WLInitWebFrameworkResult.SUCCESS) {
        super.loadUrl(WL.getInstance().getMainHtmlFilePath());
	 } else {
	     handleWebFrameworkInitFailure(result);
}

if (!(WLClient.getInstance().getContext().checkSelfPermission
    (android.Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED))
{
requestPermissions(new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, 0);

    }
}
This code requests permission if the permission has not already been granted. If the permission is still not granted, all requests for location services from the web framework fail.