ActivityResultContracts 使用户选择图库或相机上传图片的方式

Jim*_*Jim 2 android android-intent kotlin

我可以找到很多答案,比如这个,关于如何使用 Java 和旧 API 创建一个意图,让用户在相机和图库之间进行选择。

然而,虽然通过 Kotlin 使用新的API来完成其中任何一个都相对简单ActivityResultContracts,但我无法理解如何让用户在这两个功能之间进行选择,而不为这两个功能创建单独的按钮(我宁愿避免)。

我应该如何编辑后一个链接答案的代码以使用户从系统菜单中选择是否使用相机或图库?

小智 6

您需要创建自定义 ActivityResultContract:

class TakePicturefromCameraOrGalley: ActivityResultContract<Unit, Uri?>() {

        private var photoUri: Uri? = null

        override fun createIntent(context: Context, input: Unit?): Intent {
            return openImageIntent(context)
        }

        override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
            if (resultCode != Activity.RESULT_OK) return null
            return intent?.data ?: photoUri
        }

        private fun openImageIntent(context: Context): Intent {
            val camIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            photoUri = createPhotoTakenUri(context)
            // write the captured image to a file
            camIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)

            val gallIntent = Intent(Intent.ACTION_GET_CONTENT)
            gallIntent.type = "image/*"

            // look for available intents
            val info = ArrayList<ResolveInfo>()
            val yourIntentsList = ArrayList<Intent>()
            val packageManager = context.packageManager

            packageManager.queryIntentActivities(camIntent, 0).forEach{
                val finalIntent = Intent(camIntent)
                finalIntent.component = ComponentName(it.activityInfo.packageName, it.activityInfo.name)
                yourIntentsList.add(finalIntent)
                info.add(it)
            }

            packageManager.queryIntentActivities(gallIntent, 0).forEach {
                val finalIntent = Intent(gallIntent)
                finalIntent.component = ComponentName(it.activityInfo.packageName, it.activityInfo.name)
                yourIntentsList.add(finalIntent)
                info.add(it)
            }

            val chooser = Intent.createChooser(gallIntent, "Select source")
            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, yourIntentsList.toTypedArray())

            return chooser

        }

        private fun createFile(context: Context): File {
            val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
            val imageFileName = "IMG_" + timeStamp + "_"
            val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) ?: throw IllegalStateException("Dir not found")
            return File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",  /* suffix */
                storageDir /* directory */
            )
        }

        private fun createPhotoTakenUri(context: Context): Uri {
            val file = createFile(context)
            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file)
            } else {
                Uri.fromFile(file)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

并且您必须授予相机权限并创建文件提供程序才能正常工作