Android 仅抛出 11 个 ActivityResult RESULT_CANCELED

Android 11 ActivityResult throwing only RESULT_CANCELED

我们正在使用此代码选择 image/video 个文件

//Pick an image from storage
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.setType(type); //Can be image/* or video/*
        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        activityResultLauncher.launch(Intent.createChooser(intent, "Select Item"));

然后在新的ActivityResult上获取文件UriAPI

protected final ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                Log.wtf("WTF", result.toString());
                if (result.getResultCode() == Activity.RESULT_OK) {
                    // There are no request codes
                    Intent data = result.getData();

                    if (data == null) {
                        Toast.makeText(getContext(), R.string.unknown_error, Toast.LENGTH_SHORT).show();
                        return;
                    }

                    activityResult(true, data);
                }
                else
                    activityResult(false, null);
            });

不幸的是,在更新到 Android 11 之后,我们得到的只是 RESULT_CANCELED

E/WTF: ActivityResult{resultCode=RESULT_CANCELED, data=null}

正如 Ian 所说,您不应该使用 Intent.createChooserACTION_OPEN_DOCUMENT,尽管它在 Android 11.

之前有效

这是一个帮助程序 class,您使用 select image/video/pdf 使用 Activity 结果 API 作为合同 return 您Uri 的列表。它可以配置为单个或多个 selection 文件。

在 android 10 和 11 中测试。

class SelectFileContract : ActivityResultContract<Pair<SELECTION_TYPE, Boolean>, List<Uri>?>() {
    var TAG = this.javaClass.simpleName
    override fun createIntent(context: Context, input: Pair<SELECTION_TYPE, Boolean>): Intent {

        var intent: Intent? = null
        intent = when (input.first) {
            SELECTION_TYPE.IMAGE -> Intent(
                Intent.ACTION_PICK,
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI
            )
            SELECTION_TYPE.VIDEO -> Intent(
                Intent.ACTION_PICK,
                MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            )
            SELECTION_TYPE.PDF -> {
                Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
                    type = "application/pdf"
                    addCategory(Intent.CATEGORY_OPENABLE)
                }
            }
        }
        if (input.second == true) {
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
        }

        return intent!!
    }

    override fun parseResult(resultCode: Int, intent: Intent?): List<Uri>? = when (resultCode) {

        Activity.RESULT_OK -> {
            val uriList = mutableListOf<Uri>()
            /**
             * in case of single selection the Uri will be inside [intent.data]
             */
            intent?.data?.let { uriList.add(it) }


            /**
             * in case of multiple selection the Uri will be inside [intent.clipData]
             */
            intent?.clipData?.let { clipData: ClipData ->
                for (i in 0 until clipData.itemCount) {
                    uriList.add(clipData.getItemAt(i).uri)
                }
            }

            Log.d(TAG, uriList.toString())
            uriList
        }
        else -> null


    }
}

enum class SELECTION_TYPE {
    IMAGE,
    VIDEO,
    PDF
}

然后在activity具体合同:

 private val simpleContractRegistration =
        registerForActivityResult(SelectFileContract()) { result: List<Uri>? ->
            result?.let {
                Log.d(TAG, result.toString())
            }
        }

然后启动注册:

binding.button.setOnClickListener {
            simpleContractRegistration.launch(
                Pair(
                    SELECTION_TYPE.IMAGE,
                    false
                )
            )
        }