Starting from Android 6.0, there are some permissions that are considered dangerous. All the permissions that fall into this category are no longer requested at install time, but at Run Time.

Android Lollipop and lower

630630

Android Marshmallow and greater

630630

Requesting permissions at runtime.

MOCA SDK requires the ACCESS_FINE_LOCATION permission for bluetooth scanning, location tracking and geofencing.

🚧

Explicit background location permission

Since Android 10. It is necessary to explicitly request the ACCESS_BACKGROUND_LOCATION permission at run time. If this permission is not explicitly requested, the permission request prompt will only show a "when in use" permission. This prevents MOCA SDK from detecting geofences or bluetooth beacons in the background or when the app is not running.

This is an example of how to request these permissions.

private final static String FINE_LOCATION_PERM = Manifest.permission.ACCESS_FINE_LOCATION;
    private final static String BACKGROUND_LOCATION_PERM = "android.permission.ACCESS_BACKGROUND_LOCATION";
    private static final String[] NEEDED_PERMISSIONS = {FINE_LOCATION_PERM, BACKGROUND_LOCATION_PERM, BACKGROUND_LOCATION_PERM};
    private final static int REQUEST_PERMISSION_GEO = 101; //any identifier

    public static void requestLocationPermissions(final Activity activity) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return;
        }
        if (activity.shouldShowRequestPermissionRationale(BACKGROUND_LOCATION_PERM)) {
            final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
            builder.setMessage("The application uses your location in order to help " +
                    "you find closest promotions")
                    .setTitle("MOCA")
                    .setNeutralButton("ok",
                            (dialog, which) -> activity.requestPermissions(NEEDED_PERMISSIONS,
                                    REQUEST_PERMISSION_GEO))
                    .show();
        } else {
            // No explanation needed, we can request the permission.
            activity.requestPermissions(NEEDED_PERMISSIONS, REQUEST_PERMISSION_GEO);
        }
    }

Once the user allows or denies the permission, Android will send you this information using the Activity's onRequestPermissionsResult method. Override it so you can handle the response.

Below you will find an example of how to implement this method, and how to initialize the permission-affected MOCA Services:

/**
     * Callback received when a permissions request has been completed.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, 
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if ((requestCode != REQUEST_PERMISSION_GEO) {
            return;
        }
        if ((grantResults[0] != PackageManager.PERMISSION_GRANTED)) {
            Log.e(TAG, "Location permissions denied");
        }
        if (!MOCA.initialized()) {
            return;
        }
        MOCA.setProximityEnabled(true);
        MOCA.setGeoTrackingEnabled(true);
    }

Learn more about requesting permissions at Run Time. (external link).