3

I recently updated an app to a targetSdkVersion of 23, and implemented a request for various permissions. My initial attempt using ActivityCompat.requestPermissions() caused an IllegalArgumentException to be thrown from the internals of FragmentActivity:

int REQUEST_CODE_A = 9001;
ActivityCompat.requestPermissions(new String[ {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_A); // crashes

java.lang.IllegalArgumentException: Can only use lower 8 bits for requestCode

However, if the request code is between 0-255, everything is fine and the permission request works as expected.

int REQUEST_CODE_B = 101;
ActivityCompat.requestPermissions(new String[ {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_B); // works correctly

So the question is, what reasons are there for restricting the possible values of an integer in an API like this? The same information could be supplied using a byte, but a conscious decision has (apparently) been made to use an integer instead. Is this simply a case of allowing future extensibility?

fractalwrench
  • 4,028
  • 7
  • 33
  • 49
  • 1
    Possible duplicate of [Android: what to choose for requestcode values?](http://stackoverflow.com/questions/33331073/android-what-to-choose-for-requestcode-values) – Damian Kozlak Jan 07 '16 at 20:02

1 Answers1

5

Quoting the source code to FragmentActivity where this exception appears to be thrown:

    // We use 8 bits of the request code to encode the fragment id when
    // requesting permissions from a fragment. Hence, requestPermissions()
    // should validate the code against that but we cannot override it as
    // we can not then call super and also the ActivityCompat would call
    // back to this override. To handle this we use dependency inversion
    // where we are the validator of request codes when requesting
    // permissions in ActivityCompat.

startActivityForResult() has a 16-bit limit on the request code, at least in FragmentActivity.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Are the 8-bit and 16-bit limits optimisations in that case? I'm unsure as to why two "separate" values would be stored in one variable. – fractalwrench Jan 07 '16 at 20:14
  • 1
    @fractalwrench: "I'm unsure as to why two "separate" values would be stored in one variable" -- because `startActivityForResult()` is IPC, as is `onActivityResult()`. And, the protocol says that the request code is a single value, supplied in `startActivityForResult()` and returned in `onActivityResult()`. A more flexible approach would have us pass an arbitrary `Parcelable` of stuff, and get that `Parcelable` (or, technically, a copy) back, but, for whatever reason, they didn't implement it that way a decade ago. – CommonsWare Jan 07 '16 at 20:21