【问题标题】:New result API error : Can only use lower 16 bits for requestCode新结果 API 错误:requestCode 只能使用低 16 位
【发布时间】:2020-10-27 12:22:23
【问题描述】:

今天我切换到新的ResultAPI 并遇到了这个错误:

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)

当执行这些行时:

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/*")
}

无法使用这个新的结果 API 手动声明 REQUEST_CODE

注意:
它有时有效!

[更新]
我注册了多个合同(TakeVideo 和 GetContent),我发现注册的顺序很重要(第一个像一个魅力,但其他的会崩溃)。 也许我们只需要为每个活动注册一份合同?!

[更新 #2]
该问题已在最新版本的活动(1.2.7-alpha07)中得到修复。现在它会警告您添加与活动和片段相关的依赖项。

【问题讨论】:

标签: android android-jetpack onactivityresult startactivityforresult


【解决方案1】:

添加或更新此依赖项:

implementation 'androidx.fragment:fragment:1.3.0'

在使用ActivityResult API 时,使用该片段依赖确保FragmentActivity 兼容。

【讨论】:

  • 从 Activity 1.2.0-alpha07 开始会给出一个 lint 警告
【解决方案2】:

我认为新 API 有问题。在 ActivityResultRegistry 你可以看到:

 /**
 * 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;
}

在调试模式下,我看到为请求代码发送了“1388473134”。现在让我们看看发生了什么。在这种情况下,我们使用 ActivityResultRegistry 提供 由框架。这会生成一个由框架保存并由 generateRandomNumberActivityResultRegistry 生成的请求代码。

参见 ComponentActivity 类 google 框架 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);
        }
}
        

这将从FragmentActivity调用checkForValidRequestCode并抛出异常(因为生成的请求代码太“高”)。

@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);
    }

要消除此问题,您必须使用此方法的新版本更新构建等级中androidx.fragment.app 中提供的checkForValidRequestCode 的源代码。

在你的 gradle 文件中

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"
}

【讨论】:

    猜你喜欢
    • 2012-12-31
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    相关资源
    最近更新 更多