ActivityResultLauncher with RequestMultiplePermissions contract doesn't show permissions UI on launch
Asked Answered
S

2

32

I am trying to request permissions using ActivityResultLauncher with ActivityResultsContract.RequestMultiplePermissions.

import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.Manifest;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

public class MainActivity extends AppCompatActivity {

    final String[] PERMISSIONS = {
            Manifest.permission.FOREGROUND_SERVICE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_BACKGROUND_LOCATION,
            Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
    };

    private ActivityResultContracts.RequestMultiplePermissions multiplePermissionsContract;
    private ActivityResultLauncher<String[]> multiplePermissionLauncher;    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        multiplePermissionsContract = new ActivityResultContracts.RequestMultiplePermissions();
        multiplePermissionLauncher = registerForActivityResult(multiplePermissionsContract, isGranted -> {
            Log.d("PERMISSIONS", "Launcher result: " + isGranted.toString());
            if (isGranted.containsValue(false)) {
                Log.d("PERMISSIONS", "At least one of the permissions was not granted, launching again...");
                multiplePermissionLauncher.launch(PERMISSIONS);
            }
        });

        askPermissions(multiplePermissionLauncher);
    }

    private void askPermissions(ActivityResultLauncher<String[]> multiplePermissionLauncher) {
        if (!hasPermissions(PERMISSIONS)) {
            Log.d("PERMISSIONS", "Launching multiple contract permission launcher for ALL required permissions");
            multiplePermissionLauncher.launch(PERMISSIONS);
        } else {
            Log.d("PERMISSIONS", "All permissions are already granted");
        }
    }

    private boolean hasPermissions(String[] permissions) {
        if (permissions != null) {
            for (String permission : permissions) {
                if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                    Log.d("PERMISSIONS", "Permission is not granted: " + permission);
                    return false;
                }
                Log.d("PERMISSIONS", "Permission already granted: " + permission);
            }
            return true;
        }
        return false;
    }
}

I also included the necessary dependencies in build.gradle:

implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.activity:activity:1.2.0'
implementation 'androidx.fragment:fragment:1.3.0'

When I launch the app on the device, the UI for allowing permissions is not shown. I cleared cache and removed the app from the device prior to launching. The logs:

15:02:43.584 D/PERMISSIONS: Permission already granted: android.permission.FOREGROUND_SERVICE
15:02:43.586 D/PERMISSIONS: Permission is not granted: android.permission.ACCESS_FINE_LOCATION
15:02:43.586 D/PERMISSIONS: Launching multiple contract permission launcher for ALL required permissions
15:02:43.753 D/PERMISSIONS: Launcher result: {android.permission.ACCESS_FINE_LOCATION=false, android.permission.ACCESS_BACKGROUND_LOCATION=false}
15:02:43.753 D/PERMISSIONS: At least one of the permissions was not granted, launching again...
15:02:43.857 D/PERMISSIONS: Launcher result: {android.permission.ACCESS_FINE_LOCATION=false, android.permission.ACCESS_BACKGROUND_LOCATION=false}
15:02:43.857 D/PERMISSIONS: At least one of the permissions was not granted, launching again...
15:02:43.939 D/PERMISSIONS: Launcher result: {android.permission.ACCESS_FINE_LOCATION=false, android.permission.ACCESS_BACKGROUND_LOCATION=false}

The last two lines repeat until I close the app. However, when I use ActivityResultContracts.RequestPermission and request each permission separately, it works as expected, showing all the necessary UI.

Why ActivityResultsContract.RequestMultiplePermissions is not working in this case?

Saponaceous answered 4/3, 2021 at 12:27 Comment(0)
S
26

I found an answer to my question. It turned out that since Android 11 ACCESS_BACKGROUND_LOCATION permission shouldn't be requested before the general location permission was granted (ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION). Otherwise, the system will just ignore the request. So the right way is to request the general location permission (ACCESS_FINE_LOCATION in my case), and then, if it was granted, request ACCESS_BACKGROUND_LOCATION permission.

Also, if at first request user decided not to give this permission, all the following requests for this permission will be ignored, so the settings page for it won't be shown (in this case you should probably prompt user to allow the permission manually).

Saponaceous answered 5/3, 2021 at 8:33 Comment(2)
to be more correct it can be requested only after you requested a general location permissionSalutary
@Salutary Thanks, edited the answer according to your comment.Saponaceous
H
0

You have to add a library "import android.Manifest;" in the java file.

import android.Manifest;

when writing a word Manifest in the code

You will see two options:

  1. Manifest (of the project)

  2. Manifest (include in library android.Manifest)

Pick number 2

Headrick answered 31/7, 2023 at 21:56 Comment(1)
It is important to use android.Manifest for the code to run, but it doesn't solve the problem. Thanks anyway, I added import statements to the code in question.Saponaceous

© 2022 - 2024 — McMap. All rights reserved.