Why does the permissions dialog not appear when I ask for background location?
Asked Answered
B

3

5

I am attempting to request background location permission for my app, but the locations permission dialog doesn't appear at all if I ask for background location. If I just ask for coarse location and fine location, the permissions dialog appears as it should.

Manifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"  />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

code:

    requestPermissionsIfNecessary(new String[]{
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_BACKGROUND_LOCATION,
            Manifest.permission.RECEIVE_BOOT_COMPLETED

    });

    ...
    ...
    private void requestPermissionsIfNecessary(String[] permissions) {
    ArrayList<String> permissionsToRequest = new ArrayList<>();
    for (String permission : permissions) {
        if (ContextCompat.checkSelfPermission(this, permission)
                != PackageManager.PERMISSION_GRANTED) {
            // Permission is not granted
            permissionsToRequest.add(permission);
        }
    }
    if (permissionsToRequest.size() > 0) {

        ActivityCompat.requestPermissions(
                this,
                permissionsToRequest.toArray(new String[0]),
                REQUEST_PERMISSIONS_REQUEST_CODE);
    }
}

No permissions dialog appears with this code. But if I comment out the 'background' permission lines, the dialog appears and the user can choose permissions. Same result whether targeting Android 11 or 12. So what am I missing here?

Bobbette answered 19/7, 2022 at 10:6 Comment(0)
R
5

In order to request ACCESS_BACKGROUND_LOCATION, you first need to ask for ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION. After obtaining these permissions, you can then request ACCESS_BACKGROUND_LOCATION, which redirects you to the location permission settings. If you accept the ALLOW_ALL_THE_TIME option, the background location permission is granted.

Look at the code below for more info:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Check and request location permissions when the activity is created
    checkLocationPermissions()
}

private fun checkLocationPermissions() {
    if (ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        // Location permission already granted
        checkBackgroundLocation()
    } else {
        // Location permission not granted, request it
        showLocationPermissionDialog()
    }
}

private fun showLocationPermissionDialog() {
    // Display a dialog to explain why the app needs location permission
    val dialogBuilder = AlertDialog.Builder(this)
    dialogBuilder
        .setMessage("This app requires location permission for XYZ reasons.")
        .setPositiveButton("Grant Permission") { dialog, which ->
            requestLocationPermission()
        }
        .setNegativeButton("Cancel") { dialog, which ->
            // Handle cancellation
        }
        .show()
}

private fun requestLocationPermission() {
    // Request location permission
    ActivityCompat.requestPermissions(
        this,
        arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
        LOCATION_PERMISSION_REQUEST_CODE
    )
}

private fun checkBackgroundLocation() {
    // Check for background location permission on Android Q (API level 29) and above
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
        ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.ACCESS_BACKGROUND_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // Request background location permission
        requestBackgroundLocationPermission()
    } else {
        // Background location permission not required or already granted
        // Do further processing or start location updates
        startLocationUpdates()
    }
}

private fun requestBackgroundLocationPermission() {
    // Request background location permission
    ActivityCompat.requestPermissions(
        this,
        arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
        BACKGROUND_LOCATION_PERMISSION_REQUEST_CODE
    )
}

@RequiresApi(Build.VERSION_CODES.M)
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    when (requestCode) {
        LOCATION_PERMISSION_REQUEST_CODE -> {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Location permission granted
                checkBackgroundLocation()
            } else {
                // Handle when location permission is denied
                handlePermissionDenied()
            }
        }
        BACKGROUND_LOCATION_PERMISSION_REQUEST_CODE -> {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Background location permission granted
                // Do further processing or start location updates
                startLocationUpdates()
            } else {
                // Handle when background location permission is denied
                handlePermissionDenied()
            }
        }
        else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }
}

private fun startLocationUpdates() {
    // Code to start location updates
}

private fun handlePermissionDenied() {
    // Display a toast indicating that permission is denied
    Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()

    // Check if the denial is not permanent
    if (ActivityCompat.shouldShowRequestPermissionRationale(
            this,
            Manifest.permission.ACCESS_FINE_LOCATION
        )
    ) {
        // Show a rationale or redirect to app settings
        showRationaleOrRedirectToSettings()
    }
}

private fun showRationaleOrRedirectToSettings() {
    // Show rationale or redirect to app settings
    // This is where you can display a message explaining why the permission is necessary
    // and provide an option to open app settings for manual permission grant
}

First grant foreground location permissions

Then request for ACCESS_BACKGROOUND_LOCATION.

Romilda answered 10/11, 2023 at 14:20 Comment(2)
This should be the accepted answer.Sansbury
After the user selects an option on the Location permission screen, is there any way to go back to the app automatically? I would like to avoid that extra tap on the back button for the userElectroscope
R
1

This is expected behavior from android 10. Background location permission can not be granted from application as user permission. Instead you should tell user with some kind of pop up and redirect user to setting page.

Resurrect answered 19/7, 2022 at 10:29 Comment(2)
OK, understood. I have now added Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(intent); but this only gives options for coarse and fine, not background. Background is enabled in the manifest.Bobbette
@Resurrect that's absolutely not true. Requesting background location permission on its own doesn't give you any location permissions. developer.android.com/reference/android/…Petrie
B
1

OK, with help from @alokHarman and other threads here I have arrived at the following (in OnCreate):

    if (ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.fromParts("package", getPackageName(), null));
        startActivity(intent);
    }
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    if (!pm.isIgnoringBatteryOptimizations(getPackageName())) {
        Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
        startActivity(intent);
    }

I have also directed the user to change the power settings for this app, because if the app is allowed to go into deep sleep than it matters not whether background location is activaed or not.

Bobbette answered 24/7, 2022 at 12:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.