8

For handling permissions in android M+, I want to write a single class, namely PermissionHandler class, to handle all the permission-related work so that I can easily use the same class in any project without making changes to the calling activity by calling only the constructor:

           new PermissionHandler(CallingActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE, new PermissionHandler.PermissionGranted() {
                @Override
                public void onPermissionGranted() {
                    doWhatever();
                }
            });

My PermissionHandler is:

public class PermissionHandler implements ActivityCompat.OnRequestPermissionsResultCallback{
.
.
.
public PermissionHandler(AppCompatActivity callingActivity, String permission, PermissionGranted permissionGranted) {
        this.permission = permission;
        this.permissionGranted = permissionGranted;
        this.callingActivity= callingActivity;
        askForPermission();

}

private void askForPermission() {

            if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
                    showAlertDialog();
                } else {
                    ActivityCompat.requestPermissions(callingActivity,permissionsArray, PERMISSION_REQUEST);
                }
            } else {
                permissionGranted.onPermissionGranted();
            }
}

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                permissionGranted.onPermissionGranted();
            } else {
                onPermissionIsNotGranted();
            }
            break;
        }
    }
}

My problem here is that onRequestPermissionsResult which is supposed to be invoked when ActivityCompat.requestPermissions(callingActivity,permissionsArray, PERMISSION_REQUEST) is called is never invoked. What I found out is that this is due to android calling callingActivity.onRequestPermissionsResult which does not exist in the callingActivity and is passed to PermissionHandler. I also considered using Reflection and Proxies to resolve this issue at runtime, but no success.

Ali Nem
  • 5,252
  • 1
  • 42
  • 41

4 Answers4

1

As far as i searched i found that its a bug in android. You can see the live issue here. onRequestPermissionsResult() will not be called in any other class then the activity it is called by.

For more details refer this question : onRequestPermissionsResult not being called in dialog fragment. this user having the same problem as yours.

Creating a Common class for requesting permissions is a really good attempt but my friend, we need to find an alternative for handling onRequestPermissionsResult()

Community
  • 1
  • 1
Janki Gadhiya
  • 4,492
  • 2
  • 29
  • 59
0

according Janki Gadhiya answers, I write procedure like

public static WhatYouWould fCustomRequestPermissionsResult(AppCompatActivity appCompatActivity, @NonNull String[] permissions, @NonNull int[] grantResults,...)

in My PermissionHandler class and do what I would, then in for example MainActivity.java, I call that in onRequestPermissionResult :

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    ActiveUtility.CheckPermission.fCustomRequestPermissionsResult(...)
Hossein Vatani
  • 1,381
  • 14
  • 26
0

This is what I am using for requesting single permission on Android 11. compileSdk=30, minSdk=30, targetSdk=30

PermittedTask.java

public abstract class PermittedTask {
    private ActivityResultLauncher<String> launcher;
    private String permission;
    private AppCompatActivity activity;

    public PermittedTask(AppCompatActivity activity, String permission) {
        this.activity = activity;
        this.permission = permission;
        this.launcher =  activity.registerForActivityResult(
                new ActivityResultContracts.RequestPermission(),
                new ActivityResultCallback<Boolean>() {
                    @Override
                    public void onActivityResult(Boolean result) {
                        if(result) {
                            granted();
                        } else {
                            denied();
                        }
                    }
                }
        );
    }

    protected abstract void granted();

    protected void denied() {}

    private void showRequestPermissionRationale() {
    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    builder.setTitle("Permissions needed")
            .setMessage("App needs permissions to do that. You can allow or deny in next screen. Proceed?")
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    launcher.launch(permission);
                }
            })
            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    denied();
                }
            })
            .show();
    }

    public void run() {
        if(ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED) {
            granted();
        } else if(activity.shouldShowRequestPermissionRationale(permission)) {
            showRequestPermissionRationale();
        } else {
            launcher.launch(permission);
        }
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    //...
    
    private PermittedTask scanTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);     
        
        //...       
        
        scanTask = new PermittedTask(this, Manifest.permission.ACCESS_FINE_LOCATION) {
            @Override
            protected void granted() {
                startDiscovery();
            }
        };
        
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {                
                scanTask.run();
            }
        });
        
        //...
    }
    
    private void startDiscovery() {    
        //...    
    }
    
    //...
}



    
smk
  • 301
  • 6
  • 13
-1
 if (checkPermission(PERMISSION_WRITE_EXTERNAL_STORAGE)) {

            addToneToStorage();

        } else {

            requestForPermission(PERMISSION_WRITE_EXTERNAL_STORAGE);

        }

BaseActivity

public static final int PERMISSION_RECORD_AUDIO = 1;
public static final int PERMISSION_READ_EXTERNAL_STORAGE = 2;
public static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 3;

public boolean checkPermission(int permission) {

    if (ActivityCompat.checkSelfPermission(this, getPermission(permission)) != PackageManager.PERMISSION_GRANTED) {
        Debug.e("PERMISSION_CHECK_PERMISSION_FALSE", "-" + permission);
        return false;
    } else {
        Debug.e("PERMISSION_CHECK_PERMISSION_TRUE", "-" + permission);
        return true;
    }

}

public void requestForPermission(final int permission) {

    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            getPermission(permission))) {

        Debug.e("PERMISSION_NEEDED", "-" + permission);

        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

        // Setting Dialog Message
        alertDialog.setMessage(getString(R.string.text_permission_rationale));

        // Setting Positive "Yes" Button
        alertDialog.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {

                ActivityCompat.requestPermissions(BaseActivity.this, new String[]{getPermission(permission)}, permission);

            }
        });

        alertDialog.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // Write your code here to invoke NO event
                dialog.dismiss();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    } else {

        Debug.e("PERMISSION_ALLOW", "-" + permission);

        ActivityCompat.requestPermissions(this, new String[]{getPermission(permission)}, permission);

    }
    // END_INCLUDE(camera_permission_request)
}

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {


    if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // Camera permission has been granted, preview can be displayed

        Debug.e("PERMISSION_ALLOWED", "-" + requestCode);

        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

        // Setting Dialog Message
        alertDialog.setMessage(getString(R.string.text_permission_granted));

        // Setting Positive "Yes" Button
        alertDialog.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {

                dialog.dismiss();

            }
        });
        // Showing Alert Message
        alertDialog.show();

    } else {

        Debug.e("PERMISSION_DENIED", "-" + requestCode);

        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

        // Setting Dialog Message
        alertDialog.setMessage(getString(R.string.text_permission_not_granted));

        // Setting Positive "Yes" Button
        alertDialog.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {

                dialog.dismiss();

            }
        });
        // Showing Alert Message
        alertDialog.show();
    }

}

public String getPermission(int permis) {

    String permission = null;

    switch (permis) {
        case PERMISSION_RECORD_AUDIO:
            permission = Manifest.permission.RECORD_AUDIO;
            Debug.e("PERMISSION", "-" + permission);
            return permission;
        case PERMISSION_READ_EXTERNAL_STORAGE:
            permission = Manifest.permission.READ_EXTERNAL_STORAGE;
            Debug.e("PERMISSION", "-" + permission);
            return permission;
        case PERMISSION_WRITE_EXTERNAL_STORAGE:
            permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
            Debug.e("PERMISSION", "-" + permission);
            return permission;
    }
    return permission;
}

}

Narendra Sorathiya
  • 3,770
  • 2
  • 34
  • 37