What you will learn

This tutorial will teach you how to manage location permission with the mobile SDK.

Pre-requisites - What you need to get started

  • A Nexus Account: the SDK is available through a private Nexus. You must have received an email with your user account, including a link to create a password
  • Your SDK user information: in order to initialize the Mobile SDK, you must have received a User Name, a Password and a Company
  • A BLE beacon: a BLE beacon configured on your account is mandatory to test the application
  • An Android Device: you need a compatible Bluetooth Low Energy Android device with Android 6.0 or above
  • The Android Studio application: you must have downloaded Android Studio from the Android Developpers’ website

About location permission

Android 6 introduces a new set of permissions for specific features, which must be explicitly granted by the user upon first launch. This is the case when an application wants to access the location of a user.
The Bluetooth scanning process has been associated with the location feature, including GPS and Wi-Fi network triangulation.

If your application targets Android 6 devices or above, and does not ask for location authorization, the bluetooth scanning process cannot start.

If your application does not target Android 6 devices or above, you do not need to implement this feature, but the bluetooth scanning process won't return result when the application is in background on Android 6 devices or above.

Requesting location permission

Find out more about location permission in the official Android permission tutorial.

Reminder:

It is necessary to have an Android device with Android 6 or above to complete this tutorial.

Step 1: clone the sdk-tutorial repository

  • Clone the beacon-tutorial repository
git clone https://github.com/Connecthings/sdk-tutorial.git
  • Open the project android>beacon>11-Permission-Location>Starter with Android Studio

Step 2: Configure the SDK

  • Open the class ApplicationAlert
  • Configure the SDK with:
    • the UUID of your beacon
    • the appropriate Adtag Environment
    • your login, password, and company details you received from Connecthings

Step 3: Request permission

  • Starting with Android 6, the Android Activity class provides the requestPermission method, which allows to make on permission request for a group of permissions.

Note:

  • this method is only available on Android 6 or above. On Android 5 and below, calling this method will make the application crash.
  • this method automatically shows a dialog to request permission
  • this method will not show the permission dialog if the user has denied permission definitively.
  • Open the MainActivity class
  • Create a requestLocationPermission method
private void requestLocationPermission() {
}
  • Test if the device is compatible with Android 6 or above before calling the requestPermissions method
private void requestLocationPermission() {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  }
}
  • Request permission
private void requestLocationPermission() {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    //this method shows the permission dialog.
    //Note that the permission dialog will not be displayed if the user denies permission definitively
    requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
  }
}

Step 4: Retrieve the user's choice

Starting with Android 6, the Android Activity class provides the onRequestPermissionsResult method in order for an application to be notified about the user's choice from the permission dialog.

  • Override the onRequestPermissionsResult method
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
}
  • Check that the requestCode in the result is identical to the requestCost used to request location permission
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  if(requestCode == PERMISSION_REQUEST_COARSE_LOCATION){
  
  }
}
  • Check the permission status
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  if(requestCode == PERMISSION_REQUEST_COARSE_LOCATION){
    if (grantResults.length > 0){
      boolean isGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
      if (isGranted) {
        
      }else{
        // permission was denied -> ask for it again
        
      }
    }else{
      // no result ? ask again for permission
    
    }
  }
}
  • Implement the right behavior for the following situations:
    • if permission is granted, provide bluetooth access and launch the bluetooth scanning process
    • if permision is refused, ask the user again for permission
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  if(requestCode == PERMISSION_REQUEST_COARSE_LOCATION){
    if (grantResults.length > 0){
      boolean isGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
      if (isGranted) {
        switchToBeaconTv();
        testToGrantBluetoothAccess();
      }else{
        // permission was denied -> ask for it again
        requestLocationPermission();
      }
    }else{
      // no result ? ask again for permission
      requestLocationPermission();
    }
  }
}

Step 5: Test if location permission has been granted

  • Starting with Android 6, the Android Activity class provides the checkSelfPermission method, which returns permission status (Granted, Refused)

  • Create a testLocationPermission method in the MainActivity class

private void testLocationPermission(){

}
  • Use the native checkSelfPermission method to test the current permission status
  • Use the previously developed requestLocationPermission method to request location permission
private void testLocationPermission(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
            boolean isGranted = checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
            if (isGranted) {
                //launch the scan
                switchToBeaconTv();
                testToGrantBluetoothAccess();
            }else{
                //request permission
                requestLocationPermission();
            }
        }
    }
  • Add the testLocationPermission method to the onResume method of the MainActivity class.
protected void onResume(){
  super.onResume();
  [...]
  testLocationPermission();
}

Step 6: Request permission depending on the user's previous action

  • Starting with Android 6, the Android Activity class provides the shouldShowRequestPermissionRationale method, which returns:

    • true if permission has been asked before and refused by the user
    • false if permission has never been asked, or if the user does not want to see the permission dialog again
  • Create an onRequestLocationPermission method in the MainActivity class

private void onRequestLocationPermission(){

}
  • Use the native shouldShowRequestPermissionRationale method:
    • to ask permission if it has never been asked before
    • to display a message explaning why the application requests location permission if the user has denied it before
private void onRequestLocationPermission(){
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ) {
    if(shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_COARSE_LOCATION)){
      //permission has been asked before and the user refused it
      showLocationTv(R.string.tv_error_location_permission);
    }else{
      //permission has never been asked or has been asked and the user refused it definitively...
      requestLocationPermission();
      //show a message if never the user has denied it definitively
      locationPermissionIsDefinitivelyDenied = true;
      showLocationTv(R.string.tv_error_location_permission_definitive);
    }
  }
}

Note:

In the tutorial app you are currently working on, if the native shouldShowRequestPermissionRationale method returns 'false' - i.e. the user has permanently denied permission -, a informative message is displayed to encourage the user to grant the location permission. This informative message is automatically hidden once the user grants permission.

  • Now that you have implemented the onRequestLocationPermission method, which offers a better user experience than the requestLocationPermission method, replace the direct call to the latter with the former in:
    • the testLocationPermission method
    • the onRequestPermissionsResult method

Step 7: Generate a log about permission status

Generating logs about permission status is important because it allows the Adtag platform to calculate on how many devices the SDK is working.

This can be done in a single code line with the sendLogLocationPermissionAccepted method from the AdtagBeaconManager class

adtagBeaconManager.sendLogLocationPermissionAccepted(isPermissionGranted);

In the application tutorial, this code line must be added in:

  • the testLocationPermission
  • the onRequestPermissionsResult to send the "isPermissionGranted" parameter back to the Adtag platform.

Step 8: test location permission

  • Connect an Android Device with Android 6.0 or above to your computer

  • Activate your beacon

  • In Android Studio, click on "Play" to launch the installation process on your phone.

  • When the application starts, a permission dialog appears. Test the various cases. For example, start to deny permission, then allow it.

  • When location permission is granted, the following message will appear:

"BACKEND_SUCCESS, 1 beacon(s) detected, 1 content(s) attached to the beacon(s) on Adtag downloaded"

Note 1:

If you granted location permission in the application and do not get this message, check that the location feature is enabled on your smartphone.

The location feature must be enabled to detect beacons on some Android 6 devices, such as Nexus 5 ou Samsung S6.

Note 2:

Some libraries exist to help you with permission management. E.g. EasyPermissions.