Today I switched to the new ResultAPI
and I faced this error:
java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode
at androidx.fragment.app.FragmentActivity.checkForValidRequestCode(FragmentActivity.java:715)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:673)
at androidx.core.app.ActivityCompat.startActivityForResult(ActivityCompat.java:234)
at androidx.activity.ComponentActivity$2.onLaunch(ComponentActivity.java:207)
at androidx.activity.result.ActivityResultRegistry$3.launch(ActivityResultRegistry.java:147)
at androidx.activity.result.ActivityResultLauncher.launch(ActivityResultLauncher.java:42)
at .MainActivity.getVideo(MainActivity.kt:61)
at .MainActivity.access$getVideo(MainActivity.kt:18)
at .MainActivity$onCreate$2.onClick(MainActivity.kt:42)
at android.view.View.performClick(View.java:5232)
at android.view.View$PerformClick.run(View.java:21289)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:168)
at android.app.ActivityThread.main(ActivityThread.java:5885)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
When executing these lines:
private val takeFile = registerForActivityResult(GetContent()) {
Log.e("MainActivity", "fileName: $it")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
btn_get_video.setOnClickListener {
getVideo()
}
}
private fun getVideo() {
takeFile.launch("video/*")
}
There is no way to declare REQUEST_CODE
manually with this new result API.
NOTICE:
It sometimes works!
[UPDATE]
I registered multiple contracts (TakeVideo & GetContent) and I found that the order of registration is important (the first one works like a charm but the others will crash). maybe we have to register just a single contract for each activity?!
[UPDATE #2]
The problem has been fixed in the latest version of activity (1.2.7-alpha07). now it's warning you about adding both activity and fragment related dependencies.
Add or update to this dependency:
implementation 'androidx.fragment:fragment:1.3.0'
When using ActivityResult
APIs, use this fragment dependency to ensure that FragmentActivity
is compatible.
I think something is wrong with the new API. In ActivityResultRegistry
you can see :
/**
* Generate a random number between the initial value (00010000) inclusive, and the max
* integer value. If that number is already an existing request code, generate another until
* we find one that is new.
*
* @return the number
*/
private int generateRandomNumber() {
int number = mRandom.nextInt((Integer.MAX_VALUE - INITIAL_REQUEST_CODE_VALUE) + 1)
+ INITIAL_REQUEST_CODE_VALUE;
while (mRcToKey.containsKey(number)) {
number = mRandom.nextInt((Integer.MAX_VALUE - INITIAL_REQUEST_CODE_VALUE) + 1)
+ INITIAL_REQUEST_CODE_VALUE;
}
return number;
}
In debugged mode i saw "1388473134" sent for request code. Now lets see what is happening. In this case we are using ActivityResultRegistry
provided
by the framework. This generate a request code hold by the framework and generated by generateRandomNumber
from ActivityResultRegistry
.
See in ComponentActivity
class of google framework androidx.activity
.
private ActivityResultRegistry mActivityResultRegistry = new ActivityResultRegistry() {
@Override
public <I, O> void onLaunch(
final int requestCode,
@NonNull ActivityResultContract<I, O> contract,
I input,
@Nullable ActivityOptionsCompat options) {
...
} else {
// startActivityForResult path
ActivityCompat.startActivityForResult(activity, intent, requestCode, optionsBundle);
}
}
This will call checkForValidRequestCode
from FragmentActivity
and throw an exception (because the request code generate is too "hight").
@Override
public void startActivityForResult(@SuppressLint("UnknownNullness") Intent intent,
int requestCode, @Nullable Bundle options) {
// If this was started from a Fragment we've already checked the upper 16 bits were not in
// use, and then repurposed them for the Fragment's index.
if (!mStartedActivityFromFragment) {
if (requestCode != -1) {
checkForValidRequestCode(requestCode);
}
}
super.startActivityForResult(intent, requestCode, options);
}
To remove the issue you have to update the source of checkForValidRequestCode
provided in androidx.fragment.app
in your build gradele with a fresh version of this method.
In your gradle file
dependencies {
def fragment_version = "1.3.0-beta02"
// Java language implementation
implementation "androidx.fragment:fragment:$fragment_version"
// Kotlin
implementation "androidx.fragment:fragment-ktx:$fragment_version"
// Testing Fragments in Isolation
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With