Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question : How to wrap an IOS component (AVPlayer) in Jetpack Compose Multiplatform #3114

Open
kodoct opened this issue Apr 30, 2023 · 8 comments
Labels
bug Something isn't working submitted

Comments

@kodoct
Copy link

kodoct commented Apr 30, 2023

Hello,

I am currently working on a multiplatform project using Jetpack Compose and Kotlin Multiplatform, and I am looking for a way to implement a video player for both Android and iOS. I have successfully implemented the video player for Android side using ExoPlayer and Jetpack Compose, but I am facing some challenges with the iOS side.

I would like to wrap AVPlayer in a composable for the iOS implementation and overlay the UI controls using Composables. But I'm not sure if it's possible to wrap AVPlayer directly inside a composable and overlay UI controls using Composables.

As I have no experience with iOS development, I am very interested in using Jetpack Compose Multiplatform to minimize platform-specific code. I understand that iOS support is in Alpha now, so I would like to ask if it is already possible to achieve this with the current implementation. If yes, could you please guide me on how I should approach this? Any documentation or examples would be greatly appreciated.

Thank you in advance for your help!

@kodoct kodoct added bug Something isn't working submitted labels Apr 30, 2023
@kodoct
Copy link
Author

kodoct commented Apr 30, 2023

Thank you for your quick response! In fact, I have already come across that code, but it seems that the most challenging part is missing. It doesn't cover the view, only the controls and state, which is enough for an audio player but not for a video player. Essentially, I would like to know if there is a Composable to wrap an AVPlayer instance, similar to how AndroidView does for ExoPlayer.

@alexzhirkevich
Copy link
Contributor

The similar one for ios is UIKitView. Check how guys from JetBrains wrap camera with it

@m-sasha
Copy link
Contributor

m-sasha commented Apr 30, 2023

We're not providing it at the moment, but you could ask in our Slack #compose-ios channel: https://kotlinlang.slack.com/archives/C0346LWVBJ4
Maybe someone else wrote one.

@kodoct
Copy link
Author

kodoct commented Apr 30, 2023

Ok, perfect! Thank you both for your answers. I'm going to look into it. Do you have any idea when it will be available?

@kodoct
Copy link
Author

kodoct commented May 15, 2023

Hello,

I have implemented a video player for iOS using AVPlayer in a multiplatform project using Jetpack Compose and Kotlin Multiplatform. Here is the Kotlin code for the video player:

And here is the Composable where I'm using the player:

actual fun  MyPlayerComposable(videoPlayerViewModel: VideoPlayerViewModel){
    UIKitView(
        modifier = Modifier.fillMaxSize(),
        background = Color.Black,
        factory = {
            videoPlayerViewModel.player.getPlayerView()
        }
    )
}

The above code works well - the player is functional and the sound from the video plays fine. However, there is an issue. After a recomposition, the UIKitView appears to be white, even though the player is still working (as evidenced by the sound from the video and by selection change).

Interestingly, I do not encounter this problem when I use AndroidView with ExoPlayer for Android app or SwingPanel with VlcJ for desktop app.

I'm unsure why this is happening and I'm looking for help to understand this behavior. Any insights or guidance would be highly appreciated.

In addition, I have a related question regarding integrating Swift objects into Kotlin code. I have a Swift class PlayerView which I would like to use:

class PlayerView: UIView {
    override static var layerClass: AnyClass { AVPlayerLayer.self }
    
    var player: AVPlayer? {
        get { playerLayer.player }
        set { playerLayer.player = newValue }
    }
    
    private var playerLayer: AVPlayerLayer { layer as! AVPlayerLayer }
}

However, when I try to create an instance of this class in my Kotlin codeof iosMain like private var playerView = PlayerView() , it doesnt work, so is it possible to do ? if yes how can I do ?

Thank you in advance for your help!

@alexzhirkevich
Copy link
Contributor

alexzhirkevich commented May 15, 2023

I guess it is because of #3119. Hope it will be fixed soon.

To workaround this issue right now you can remember factory lambda of the UIKitView:

val factory = remember(videoPlayerViewModel) {
    { videoPlayerViewModel.player.getPlayerView() }
} 

UIKitView(
    modifier = Modifier.fillMaxSize(),
    background = Color.Black,
    factory = factory
  )

@kodoct
Copy link
Author

kodoct commented May 16, 2023

I guess it is because of #3119. Hope it will be fixed soon.

To workaround this issue right now you can remember factory lambda of the UIKitView:

val factory = remember(videoPlayerViewModel) {
    { videoPlayerViewModel.player.getPlayerView() }
} 

UIKitView(
    modifier = Modifier.fillMaxSize(),
    background = Color.Black,
    factory = factory
  )

Thanks yes with workaround it works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working submitted
Projects
None yet
Development

No branches or pull requests

4 participants