React-Native (Android) : ArrayIndexOutOfBoundsException thrown when requesting for permissions

Viewed 994

Recently I have encountered a very strange issue while working with a React-Native app. Here's my environement:

  • Rect-Native 0.42.3
  • Samsung Galaxy Note 5
  • Android 6.0

As you may know, the Android permission model has changed since Marshmallow, but some days ago, I got his exception:

java.lang.RuntimeException:
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4156)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4250)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1839)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:158)
    at android.app.ActivityThread.main(ActivityThread.java:7229)
    at java.lang.reflect.Method.invoke(Native Method:0)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.ArrayIndexOutOfBoundsException:
    at com.facebook.react.modules.permissions.PermissionsModule$1.invoke(PermissionsModule.java:119)
    at com.facebook.react.modules.permissions.PermissionsModule.onRequestPermissionsResult(PermissionsModule.java:207)
    at com.facebook.react.ReactActivityDelegate$1.invoke(ReactActivityDelegate.java:211)
    at com.facebook.react.ReactActivityDelegate.onResume(ReactActivityDelegate.java:131)
    at com.facebook.react.ReactActivity.onResume(ReactActivity.java:66)
    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1286)
    at android.app.Activity.performResume(Activity.java:6987)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4145)

First, I thought I was missing a check in the code, as explained here but this is not the case as otherwise I would have a message like this instead:

java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{fac49ea 4674:com.gospacesmobile/u0a65} (pid=4674, uid=10065) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS

I looked at React-Native's code and found this:

// com.facebook.react.modules.permissions.PermissionsModule.java
int[] results = (int[]) args[0];
if (results[0] == PackageManager.PERMISSION_GRANTED) { // <- the exception happens when results is empty
    promise.resolve(GRANTED);
} else {
    PermissionAwareActivity activity = (PermissionAwareActivity) args[1];
    if (activity.shouldShowRequestPermissionRationale(permission)) {
        promise.resolve(DENIED);
    } else {
        promise.resolve(NEVER_ASK_AGAIN);
    }
}

According the documentation, the grantResults variable may be empty whenever the permission request has been canceled:

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

Unfortunately, I do not have the client code (as the crash report in the google console dev does not mention it). In any case, shouldn't React-Native check for empty grantResults? Is this a bug? If yes, how could this be reproduced? I don't see any way this could be done, except by canceling the promise responsible for ensuring if a permission has been enabled or not (which is impossible considering react-native permissions API).

Any thought is very welcome. Thank you in advance.

1 Answers
Related