Android 30+中的视频捕获意图-只有所有者能够与待定项目交互

b5lpy0ml  于 2022-12-28  发布在  Android
关注(0)|答案(1)|浏览(149)

我尝试在我的应用程序上捕捉视频。它在Android API 30以下工作,但在30+上不工作。似乎在SDK 30之后,Android不允许完全读取外部存储(作用域存储)。我目前有这个错误:

  • java.lang.非法状态异常:只有所有者才能与挂起项目内容交互://media/external_primary/video/media/57*

现在我有三个问题:
1.如何创建将视频保存到应用内部存储的视频捕获Intent?(因为作用域存储限制适用于外部存储)
1.我可以在onActivityResult得到内容URI,如何使这个URI可访问和可读?(读完这个文件后,我将用它创建一个临时文件并编辑这个临时文件。)
1.在存储范围受限的情况下,捕获视频的正确方法是什么?

视频捕获意图

private fun dispatchTakeVideoIntent() {
    Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takeVideoIntent ->
        takeVideoIntent.resolveActivity(packageManager)?.also {
            startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE)
        }
    }
}

活动结果

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == RESULT_OK){

        when(requestCode){
            
            REQUEST_VIDEO_CAPTURE -> {
                val videoUri: Uri? = data?.data
                setVideo(videoUri)
            }
        }
    }
}

videoUri看起来像这样:* 内容://媒体/外部主/视频/媒体/57*
setVideo函数通常获取内容uri,从中创建一个临时文件,压缩,并从这个文件中获取一个缩略图,然后我将这个文件上传到服务器。

nbewdwxp

nbewdwxp1#

感谢@CommonsWare的建议,我用File provider创建了一个文件,并用EXTRA_OUTPUT提供了这个文件的uri。现在我可以用videoUriForAddingCaptureVideovideoPathForAddingCaptureVideo变量做一些事情了。我把这个答案贴出来是为了给其他开发人员给予一个线索。

private fun dispatchTakeVideoIntent() {

    val videosFolder = File(
        Environment
            .getExternalStorageDirectory(), application.applicationContext.resources
            .getString(R.string.app_name)
    )

    try {
        if (!videosFolder.exists()) {
            val isCreated: Boolean = videosFolder.mkdirs()
            if (!isCreated) {
                Log.e(TAG,"dispatchTakeVideoIntent : storage error")
                return
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }

    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
    val videoFileName = "VID_" + timeStamp + "_"
    val storageDir: File? = application.applicationContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES)

    try {
        val video = File.createTempFile(
            videoFileName,  /* prefix */
            ".mp4",  /* suffix */
            storageDir /* directory */
        )
        videoUriForAddingCaptureVideo = FileProvider.getUriForFile(application.applicationContext, application.applicationContext.packageName + ".provider", video)
        videoPathForAddingCaptureVideo = video.absolutePath //Store this path as globe variable

        Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takeVideoIntent ->
            takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUriForAddingCaptureVideo)
            takeVideoIntent.resolveActivity(packageManager)?.also {
                startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE)
            }
        }

    } catch (e: ActivityNotFoundException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    }

}

相关问题