Request Permission in Android Cordova plugin does

2020-07-17 07:34发布

问题:

I am trying to write a Cordova Plugin to have a Facebook chat head like floating icon for ionic hybrid apps which requires SYSTEM_ALERT_WINDOW Permission.

Since Android M onward requires the user to grant the permission at the first time the app starts, I am trying to use Cordova plugin's cordova.requestPermission(CordovaPlugin plugin, int requestCode, String permission) method to prompt the user to grant permission (as in the documentation).

public class Floatie extends CordovaPlugin {

    public static final String ACTION_START_FLOATIE = "startFloatie";
    public static final int REQUEST_CODE = 0;
    public static final String DRAW_OVER_OTHER_APPS = Manifest.permission.SYSTEM_ALERT_WINDOW;
    private CallbackContext callbackContext;

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

        if (action.equals(ACTION_START_FLOATIE)) {
            String message = args.getString(0); 
            this.callbackContext = callbackContext;

            if(cordova.hasPermission(DRAW_OVER_OTHER_APPS)) {
                Log.i("Floatie", "Has Permission");
            }
            else
            {
                getPermission(REQUEST_CODE);
            }

            return true;
        }
        return false;
    }

    protected void getPermission(int requestCode)
    {
        cordova.requestPermission(this, requestCode, DRAW_OVER_OTHER_APPS);
    }

    public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException
    {
        for(int r:grantResults)
        {
            if(r == PackageManager.PERMISSION_DENIED)
            {
                Log.i("Floatie", "Permission Denied");
                return;
            }
        }
        Log.i("Floatie", "Permission Granted");
    }
}

At the first launch, the app does not prompt permission request activity and instead the log prints "Permission Denied".

I am new to Ionic and Cordova and still couldn't work this out after spending hours on this. Any help will be highly appreciated.

Thanks in advance.

回答1:

Seems that SYSTEM_ALERT_WINDOW is a special case which has its own permission request mechanism starting with API 23. There's a mention of this in the System Permissions documentation:

There are a couple of permissions that don't behave like normal and dangerous permissions. SYSTEM_ALERT_WINDOW and WRITE_SETTINGS are particularly sensitive, so most apps should not use them. If an app needs one of these permissions, it must declare the permission in the manifest, and send an intent requesting the user's authorization. The system responds to the intent by showing a detailed management screen to the user. For details on how to request these permissions, see the SYSTEM_ALERT_WINDOW and WRITE_SETTINGS reference entries.

And the corresponding reference entry for SYSTEM_ALERT_WINDOW says:

Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user's approval by sending an intent with action ACTION_MANAGE_OVERLAY_PERMISSION. The app can check whether it has this authorization by calling Settings.canDrawOverlays().

So, in a nutshell, you can't use cordova.requestPermission() to request SYSTEM_ALERT_WINDOW, you've gotta send that custom intent:

cordova.getActivity().startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));