android - ActivityResultContracts 使用户在画廊或相机之间选择上传图片的方式

标签 android kotlin android-intent

我可以找到很多答案,such as this one ,关于如何使用 Java 和旧版 API 创建让用户在相机和画廊之间进行选择的 Intent 。

然而,虽然它是 relatively simple to do either of them via Kotlin with the new ActivityResultContracts API ,我无法理解如何让用户在不为这两个功能制作单独的按钮的情况下在两者之间进行选择(我宁愿避免这样做)。

我应该如何编辑后者链接的答案代码,让用户从系统菜单中选择是使用相机还是图库?

最佳答案

您需要创建自定义 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)
            }
        }
    }

并且您必须获得相机许可File provider为了正常工作而创建

关于android - ActivityResultContracts 使用户在画廊或相机之间选择上传图片的方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66441651/

相关文章:

java - 从线程外部、线程运行内部设置 boolean 值

android - onBackPressed 可以设置并返回 Intent 结果吗?

android - 如何在 Android 中通过 Intent 传递具有不同数据的 Activity 的单个实例?

android - 在使用 Android NDK r10e 构建静态库时“无效使用 'auto'”

android - Kotlin 数据类的扩展函数

java - Kotlin: [内部错误] java.lang.ArrayIndexOutOfBoundsException: 446

android - 编辑/删除谷歌日历事件并获取事件 ID

android - Intent 发送不是 Intent 接收

java - 安卓和谷歌地图 : Fading pulse animation

kotlin - 为后端应用程序设置 kotlin 协程范围的正确方法