当前位置: 首页 > 知识库问答 >
问题:

AndroidResults合同。TakePicture()返回布尔值而不是位图

暴绪
2023-03-14

契约已更改为返回布尔值,而不是从androidx开始的位图。活动版本1.2.0-alpha05。如何使用内置的AndroidResultContracts返回的布尔值。TakePicture()contract访问和显示用户刚刚拍摄的照片?

共有2个答案

贺君浩
2023-03-14

我一直在努力解决这个问题,只是刚刚提出了一个(某种程度上)可行的解决方案,涉及ContentResolver

这些文档让人难以想象。这种方法的一个主要问题是,捕获的图像URI必须在ActivityResultContract外部进行管理,正如最初的问题已经指出的那样,这似乎违反了直觉。

我不知道还有什么方法可以将媒体插入到图库中来解决这部分问题,但我绝对希望看到这个解决方案。

// Placeholder Uri
var uri: Uri? = null

// ActivityResultContract for capturing an image
val takePicture =
    registerForActivityResult(contract =
        ActivityResultContracts.TakePicture()) { imageCaptured ->
            if (imageCaptured) {
                // Do stuff with your Uri here
            }
        }

...

fun myClickHandler() {
    // Create a name for your image file
    val filename = "${getTimeStamp("yyyyMMdd_HHmmss")}-$label.jpg"

    // Get the correct media Uri for your Android build version
    val imageUri =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        MediaStore.Images.Media.getContentUri(
            MediaStore.VOLUME_EXTERNAL_PRIMARY)
    } else {
        MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    }
        val imageDetails = ContentValues().apply {
        put(MediaStore.Audio.Media.DISPLAY_NAME, filename)
    }

    // Try to create a Uri for your image file
    activity.contentResolver.insert(imageUri, imageDetails).let {
        // Save the generated Uri using our placeholder from before
        uri = it

        // Capture your image
        takePicture.launch(uri)
    } ?: run {
        // Something went wrong
    }
}
封烈
2023-03-14

我正在用

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

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

注意:我的解决方案使用视图绑定

MainActivity的布局XML包括(1)一个按钮,该按钮将onTakePhotoClick定义为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" />

在我的Main Active中,我完成了以下操作:

  1. 定义imageUri:Uri将设置为TakePicture()合同拍摄的图像的uri
    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?当给定上下文。请注意,我使用外部文件目录作为我的文件提供商的存储目录。

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

不要忘记将使用权限使用功能提供程序标记添加到AndroidManifest

还要确保提供给权限属性

<?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>

我的res/xml/file_paths如下所示。因为我正在使用getExtranalFilesDir(),所以我正在使用

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

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

结果将在ImageView中显示imageUri

 类似资料:
  • 问题内容: 不出所料,空元组不包含1 但是返回的值不等于 换一种方式来看,运算符返回的a既不是也不是: 但是,如果对原始表达式加上括号,则会恢复正常行为 或其值存储在变量中 在Python 2和Python 3中都观察到此行为。 你能解释发生了什么吗? 问题答案: 您正在遇到比较运算符链接;也 没有 意思。 相反,比较是链接在一起的,该表达式的真正含义是: 因为已经为false,所以将完全忽略链接

  • 所以我试着从一行中获取数据,看起来像这样: 现在,我这里是我的代码与正则表达式: “/某物”是我需要得到的,在实际使用中它永远是不同的东西。代码总是打印出“true”,而不是字符串中应该有的东西。我做错了什么?

  • 问题内容: 关于以下原因为何的任何想法。 当我将request_url粘贴到浏览器中时,我会获取json数据,但是如果我在php中尝试,则var_dump就是bool(false); 有任何想法吗?? 更新并修复 OK伙计们,感谢您的所有帮助。是的,我帮助我追踪了这一情况。事实证明,php.ini配置为禁止打开url,因此file_get_contents无法正常工作。我在各个站点上发现了以下方便

  • 好的,我的问题是关于布尔返回。对于我的Comp-Sci作业,我必须使用多种方法制作一个课程注册程序,其中之一就是添加课程方法。基本上,在目录中搜索类,如果匹配,则将其添加到学生计划中,并返回布尔值true。我这么做了,但出于某种原因,这给了我一个错误。以下是代码: 为什么它不能识别布尔返回值?是因为我把它们放在了一个圈里吗?

  • 问题内容: 查看javadoc,我看到ArrayList有一个重载的add方法: public boolean add(E e) 将指定的元素追加到此列表的末尾。 和 public void add(int index,E元素) 将指定的元素插入此列表中的指定位置。将当前在该位置的元素(如果有)和任何后续元素右移(将其索引添加一个)。 我注意到第一个返回了一个,而第二个返回了一个。事实证明,第一个

  • 我想写返回true的Python函数一个字符串s是回文,也就是等于它的反。例如,“赛车”和“abba”是回文。到目前为止,这是我不成功的尝试。 当我告诉我的函数返回相反的结果时,我没有问题,但是,我不知道应该如何进行比较才能返回一个布尔值。 使用上面的函数会产生以下错误 现在我完全理解为什么会产生上述错误。这是因为一些递归函数返回一个boool并尝试将其添加到字符串中;但是我做不到的是如何避免这个