AndroidResultContracts.TakePicture() 返回布尔值而不是位图

2024-05-22

合同已变更为退货Boolean代替Bitmap从 androidx.activity 版本 1.2.0-alpha05 开始。我怎样才能使用Boolean由内置返回AndroidResultContracts.TakePicture() https://developer.android.com/reference/kotlin/androidx/activity/result/contract/ActivityResultContracts.TakePicture访问并显示用户刚刚拍摄的照片的合同?


我在用

    implementation 'androidx.activity:activity-ktx:1.2.0-alpha07'
    implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha07'

这是我的完整示例代码,展示了如何使用内置的 Android 结果合约从应用程序中拍摄照片并将其显示在 ImageView 中。

Note:我的解决方案使用视图绑定 https://developer.android.com/topic/libraries/view-binding

MainActivity的布局 XML 包括 (1) 定义按钮onTakePhotoClick as the onClick事件和(2)和ImageView来显示拍摄的照片。

        <Button
            android:id="@+id/take_photo_button"
            style="@style/Button"
            android:drawableStart="@drawable/ic_camera_on"
            android:onClick="onTakePhotoClick"
            android:text="@string/button_take_photo"
            app:layout_constraintTop_toBottomOf="@id/request_all_button" />

        ...

        <ImageView
            android:id="@+id/photo_preview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            app:layout_constraintTop_toBottomOf="@id/take_video_button" />

In my MainActivity我做了以下事情:

  1. Defined imageUri: Uri?它将被设置为所拍摄图像的 uriTakePicture()合同。
  2. 实施的onTakePhotoClick()在启动之前检查必要的相机权限TakePicture()合同。
  3. Defined takePictureRegistration: ActivityResultLauncher这实际上会启动在设备上拍照的请求。什么时候isSuccess返回为true然后我知道imageUri我之前定义的现在引用了我刚刚拍摄的照片。
  4. 定义了一个takePicture: Runnable只是为了代码重用。请注意,第 2 个String参数传递给FileProvider.getUriForFile(context, authority, file)方法需要匹配authorities属性提供给<provider>在你的应用程序中AndroidManifest.xml.
  5. 为了完全透明,我还添加了显示如何使用的代码ActivityResultContracts.RequestPermission() https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts.RequestPermission请求用户访问相机的运行时权限。
    private var imageUri: Uri? = null

    /**
     * Function for onClick from XML
     *
     * Check if camera permission is granted, and if not, request it
     * Once permission granted, launches camera to take photo
     */
    fun onTakePhotoClick(view: View) {
        if (!checkPermission(Manifest.permission.CAMERA)) {
            // request camera permission first
            onRequestCameraClick(callback = takePicture)
        } else {
            takePicture.run()
        }
    }

    private val takePicture: Runnable = Runnable {
        ImageUtils.createImageFile(applicationContext)?.also {
            imageUri = FileProvider.getUriForFile(
                applicationContext,
                BuildConfig.APPLICATION_ID + ".fileprovider",
                it
            )
            takePictureRegistration.launch(imageUri)
        }
    }

    private val takePictureRegistration =
        registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
            if (isSuccess) {
                mBinding.photoPreview.setImageURI(imageUri)
            }
        }

    /**
     * Function for onClick from XML
     *
     * Launches permission request for camera
     */
    fun onRequestCameraClick(view: View? = null, callback: Runnable? = null) {
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
            // update image
            mBinding.iconCameraPermission.isEnabled = isGranted

            val message = if (isGranted) {
                "Camera permission has been granted!"
            } else {
                "Camera permission denied! :("
            }

            Toast.makeText(this, message, Toast.LENGTH_SHORT).show()

            if (isGranted) {
                callback?.run()
            }
        }.launch(Manifest.permission.CAMERA)
    }

为了完全透明ImageUtils实用程序类有createImageFile()方法定义如下并返回一个File?当给定上下文时。请注意,我使用外部文件目录作为 FileProvider 的存储目录。

object ImageUtils {
    lateinit var currentPhotoPath: String

    @Throws(IOException::class)
    fun createImageFile(context: Context): File? {
        // Create an image file name
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
        val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        return File.createTempFile(
            "JPEG_${timeStamp}_", /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            currentPhotoPath = absolutePath
        }
    }
}

不要忘记添加uses-permission, uses-feature and provider标签到AndroidManifest.

还要确保authorities属性提供给<provider>匹配传递给的第二个字符串参数FileProvider.getUriForFile(context, authority, file)方法。在我的示例中,我已将权限设置为包名称+“.fileprovider”。阅读更多关于FileProvider来自谷歌的文档 https://developer.android.com/reference/androidx/core/content/FileProvider.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.captech.android_activity_results">

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-feature android:name="android.hardware.camera" />

    <application
        ...

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="com.captech.android_activity_results.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>
</manifest>

My res/xml/file_paths如下所示。因为我正在使用getExternalFilesDir(),我正在使用<external-files-path>XML 中的标签。

Note:如果您不使用外部文件目录,您可能需要查找要在 XML 标记中指定的 FileProvider 存储目录.

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path
        name="my_images"
        path="/" />
</paths>

结果将显示imageUri在图像视图中:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AndroidResultContracts.TakePicture() 返回布尔值而不是位图 的相关文章

随机推荐