본문 바로가기

LANGUAGES, METHODLOGY/Kotlin

[안드로이드 | ExoPlayer] EventListener를 활용해 여러개의 동영상 연달아 재생하기

ExoPlayer를 동영상 재생에 쓰던 중에

 

여러개의 영상을 연달아 보여줘야 하는 요구사항이 생겼다.

 

이를 위해 일전에 에셋을 리스트 형태로 만들어 다른 용도로 썼던 것을 떠올려 구현을 해보기로 했다.

 

 


 

< 차례 >

 

1. ExoPlayer Initialize

2. 비디오 에셋 resourceList 설정

3. ProgressiveMediaSource ArrayList에 차례대로 resourceList를 로딩해 add

4. Player.EventListener Initialize

5. ExoPlayer에 listener add

6. ExoPlayer.setShutterBackgroundColor(Color.TRANSPARENT)

7. 영상을 차례대로 재생하는 플레이어 감상

 

< 단계별 설명 >

 

- 기본 설정 -

  • 먼저 ExoPlayer를 위한 기본 implementation을 마친 상태
  • 뷰를 가져오는 데 Data binding을 사용하였음.
  • Kotlin 기반
  • Data binding을 쓰지 않는다면, exoPlayerView를 참조하는 과정만 findViewById로 대체해 사용하면 무방함.

1. ExoPlayer Initialize

val player = ExoPlayerFactory.newSimpleInstance(context)

player.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
binding.exoPlayerView.player = player
binding.exoPlayerVIew.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL

 - scalingMode나 resizeMode의 경우 View에 꽉 찬 영상을 보여주기 위해 설정해주었음.

 

 

2. 비디오 에셋 resourceList 설정

val resourceList = listOf(
  R.raw.sample_01,
  R.raw.sample_02,
  R.raw.sample_03
)

 

3. ProgressiveMediaSource ArrayList에 차례대로 resourceList를 로딩해 add

val dataSoruceFactory = DefaultDataSourceFactory(context, 
                          Util.getUserAgent(context, "앱이름"))

val videoResourceList = ArrayList()

var tempSource: RawResourceDataSource

for (i in resourceList.indices) {
    tempSource = RawResoruceDataSource(context)
    tempSource.open(DataSpec(RawResourceDataSource
                    .buildRawResourceUri(resourceList[i])
    videoResourceList.add(ProgressiveMediaSource.Factory(dataSourceFactory)
              .createMediaSource(rawDataSource.uri)
 }

 - 비디오 리소스를 만들기 위해 별도로 dataSourceFactory를 생성해야 하며, 생성에는 인자로 context와 앱 이름을 필요로 함.

 

4. Player.EventListener Initialize

val eventListener : Player.EventListener

var videoIndex = 0

eventListener = object: Player.EventListener {
   
    override fun onPlayerStateChanged(playWhenReady: Boolean, playBackState: Int) {
          if (playBackState == Player.STATE_ENDED) { 
              player.prepare(videoResourceList[videoIndex])
          }
          
          videoIndex++
          
    }
    
    super.onPlayerStateChanged(playWhenReady, playBackState)
}

- EventListener의 onPlayerStateChanged를 사용해 ExoPlayer가 한개의 영상 재생을 마칠 때(player.STATE_ENDED)

다음 영상을 로딩하도록 구성.

 

** 여기에서 super.onPlayerStateChanged 를 수행하면서

 

... interfaces are prohibited in JVM target 1.6. ..  라는식의  컴파일 오류가 발생했고

 

이를 해결하기 위해 app레벨의 gradle에 아래 옵션을 추가하였음.

android {

...

kotlinOptions {     
     jvmTarget = '1.8'
}

...

}

 

5. ExoPlayer에 listener add

player.addListener(eventListener)

 

6. ExoPlayer.setShutterBackgroundColor(Color.TRANSPARENT)

binding.exoPlayerView.userController = false
binding.exoPlayerView.setShutterBackgroundColor(Color.TRANSPARENT)

- 컨트롤러를 필요로 하지 않았기 때문에 userController를 false로 설정

- 동영상이 바뀔 때 플레이어의 화면이 까맣게 깜박이는 현상이 있었고, 이를 제거하기 위해 setShutterBackgroundColor를 투명으로 설정.

 

7. 영상을 차례대로 재생하는 플레이어 감상

 

 

< 참조 >

 

https://github.com/google/ExoPlayer/issues/2843 

 

Provide option to keep the last frame of a previous source visible when switching sources · Issue #2843 · google/ExoPlayer

First of all, congrats on the io'17 ExoPlayer presentation! Issue description I would like to implement a "hold picture" (or freeze) functionality in the app, where a player would hol...

github.com

https://stackoverflow.com/questions/48601549/why-kotlin-gradle-plugin-cannot-build-with-1-8-target

 

Why kotlin gradle plugin cannot build with 1.8 target?

I have the simplest gradle project configured using intellij for kotlin 1.2.10. Here is my build.gradle file: buildscript { ext.kotlin_version = '1.2.10' repositories { mavenCentr...

stackoverflow.com