How to handle permission requests outside Activity and Fragment?

You can't work with permissions without the instance of the activity, but you can do your code prettier. If you want to send a request and handle it in one place, then you can use the example below.

Just create something looks like BaseActivity and put there such code

public class PermActivity extends Activity {

    interface OnPermissionCallback{
        void requestResult(String[] permissions, int[] grantResults);
    }

    private SparseArray<OnPermissionCallback> permissionCallback = new SparseArray<>();

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        permissionCallback.get(requestCode).requestResult(permissions, grantResults);
    }

    public void addPermissionCallback(int requestCode, OnPermissionCallback  callback){
        permissionCallback.put(requestCode, callback);
    }
}

And now in our client code, we can do something like that

class SomeClasThatWorksWithPerms{

    private PermActivity activity;

    public SomeClasWorksWithPerms(PermActivity activity) {
        this.activity = activity;
    }

    void foo(){
        if (ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
            // do something
        }else {
            activity.addPermissionCallback(0, (perms, grantResults) -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    foo(); // try one more
                }
            });
            activity.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 0);
        }
    }
}

I have used spareArray and indexation by the request code but you can use another way of storing callbacks.

It's very simple example, you can see something more serious there https://github.com/mrizyver/Fl_Launcher/blob/master/app/src/main/java/com/izyver/fllauncher/presentation/activity/FlActivity.kt - as you can see, it is activity https://github.com/mrizyver/Fl_Launcher/blob/master/app/src/main/java/com/izyver/fllauncher/presentation/loaders/WallpaperLoader.kt - our client code that works with permissions


I'm developing a custom compound View that needs to access external storage

IMHO, that's an architecture bug. A View is for displaying stuff to the user, and sometimes for collecting low-level input events and turning them into higher-order constructs (e.g., clicks, swipes). A View should not have any connection to files, databases, etc. See the MVC, MVP, MVVM, and similar GUI architecture patterns.

WebView, which does not abide by this, causes problems (e.g., doing disk I/O on the main application thread) as a result.

How can I implement the permission handling without involving outside parties, i.e. Activity or Fragment?

You can't. It is the responsibility of the activity or fragment to request the permission, presumably before your view needs this data.

what would be the most elegant solution to handle something like this?

Extract the data-access portion of this View into something else that is managed by the activity or fragment, where the threading, permissions, and other work associated with that data access can be managed.