2

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.

Francis Toth
  • 1,595
  • 1
  • 11
  • 23
  • I have encountered a similar problem. Requesting a permission when loaded a dev version of my app. I think it minizies the app as it is booted up and causes this crash. I'm not sure if it will still be an issue in production. – Culzean Mar 09 '18 at 10:27

1 Answers1

1

So I finally found the problem. Whenever the permission request dialog appear, if the user minimizes the app, and then goes back to it by clicking on the app's icon in from the home menu, the results is empty which makes the app crashing.

This seems to be quiet a simple issue, and I've decided to monkey patch React-Native in order to prevent an unstable upgrade (Now I check if the results array is empty or not, and if it is, then deny the request). I still don't know if this is a common issue or something that comes from my app.

Francis Toth
  • 1,595
  • 1
  • 11
  • 23