I am trying to capture video on my app. It works below android API 30 but does not work on 30+. Seems like after sdk 30, android does not allow to read external storage entirely (scoped storage). I am currently having this error:
java.lang.IllegalStateException: Only owner is able to interact with pending item content://media/external_primary/video/media/57
Now I have three questions:
onActivityResult
, how to make this uri accessible and readable? (After I read this file, I will create a temporary file with it and edit this temp file.)video capture intent
private fun dispatchTakeVideoIntent() {
Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takeVideoIntent ->
takeVideoIntent.resolveActivity(packageManager)?.also {
startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE)
}
}
}
onActivityResult
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 looks like this: content://media/external_primary/video/media/57
setVideo
function normally gets the content uri, creates a temporary file from it, compresses, and gets a thumbnail from this file. And then I upload this file to the server.
Thanks to @CommonsWare s advice, I created a file with File provider and supply uri of this file with EXTRA_OUTPUT
. Now I am able to do stuff with videoUriForAddingCaptureVideo
and videoPathForAddingCaptureVideo
variables. I am posting this answer to give a clue to fellow developers.
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()
}
}