'Play video from URI in Jetpack Compose android
I am trying to play a video which user selects from file explorer. Then it should open and start video as expected and as shown in below tutorial. But there is below error just after it. Can anyone help me out?
Tutorial: https://proandroiddev.com/learn-with-code-jetpack-compose-playing-media-part-3-3792bdfbe1ea
Code:
@Composable
fun VideoView(context: Context, mediaUri: Uri) {
val exoPlayer = remember(context) {
SimpleExoPlayer.Builder(context).build().apply {
val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(context,
Util.getUserAgent(context, context.packageName))
val source = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(mediaUri)
this.prepare(source)
this.playWhenReady = true
}
}
DisposableEffect(
AndroidView(
modifier =
Modifier.testTag("VideoPlayer"),
factory = {
PlayerView(context).apply {
player = exoPlayer
layoutParams =
FrameLayout.LayoutParams(
ViewGroup.LayoutParams
.MATCH_PARENT,
ViewGroup.LayoutParams
.WRAP_CONTENT
)
}
}
)
) {
onDispose {
// relase player when no longer needed
exoPlayer.release()
}
}
}
Manifest:
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Photoeditorjetpack.NoActionBar">
Error:
022-01-09 16:46:55.247 9796-10228/android.process.media E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/video:114 from pid=13515, uid=10098 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:634)
at com.android.providers.media.MediaDocumentsProvider.enforceReadPermissionInner(MediaDocumentsProvider.java:184)
at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:503)
at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:494)
at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:422)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:302)
at android.os.Binder.execTransact(Binder.java:731)
Solution 1:[1]
Use below method to call video in ExoPlayer and when Exit from screen then onDispose(
) call to stop your existing video :
@Composable
fun VideoPlayerScreen() {
val context = LocalContext.current
var playWhenReady by remember { mutableStateOf(true) }
val exoPlayer = remember {
ExoPlayer.Builder(context).build().apply {
setMediaItem(MediaItem.fromUri("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"))
repeatMode = ExoPlayer.REPEAT_MODE_ALL
playWhenReady = playWhenReady
prepare()
play()
}
}
DisposableEffect(
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = {
PlayerView(context).apply {
player = exoPlayer
useController = true
FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
}
)
) {
onDispose {
exoPlayer.release()
}
}
}
If you wants to hide controls then use: useController = false
// Exoplayer Dependency
implementation 'com.google.android.exoplayer:exoplayer:2.16.1'
Solution 2:[2]
I tried one solution, the main problem was I don't know why this happens, when I pass Uri from One screen to another screen via Navigation & navController.
I used mutableStateOf()
as string on first screen and then using it in another screen by updating when I am getting Uri from Action Open document.
First Screen:
val videoValue = mutableStateOf("")
Second Screen:
Uri.parse(videoValue.value)
This way I was able to get access it properly
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Dishant Gandhi |