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

(Proposal) [#264] media3 integration #266

Merged
merged 46 commits into from
Apr 5, 2024

Conversation

workspace
Copy link

@workspace workspace commented Sep 12, 2023

Issue

Overview

라이브러리 업그레이드

  • agp, kotlin, jetpack, gradle 등 가능한 최신으로 업그레이드

tv, wear-os, automotive app overview

  • 기존 app의 resource 복사 (앱 아이콘, 색상 등)
  • AndroidManifest, Application 정의
  • app 마다 다른 구현체 주입(ex. SessionActivityIntentProvider)
    • Q. 각 앱의 main에서 주입하는게 더 나을까?

tv, wear-os, automotive feature overview

  • 기존 모바일 앱 구현을 위한 feature들의 구조, naming을 그대로 하여 각 폼팩터에 맞춰 변경
  • Q. feature:tv-main vs feature:tv:main

core:playback overview

  • 발표자료 p62-69

발표자료

+) 원래 media3 구현에 맞춰 개인 repo에 가지고 있으려던 것인지라 에잇! 하며 허술한 부분이 있을 수 있습니다. 개선 방향 제시해주시면 감사하게 반영해보겠습니다 ㅎㅎ

- manifestUrl: 재생을 위한 dash manifest url
- thumbnailUrl: 영상의 썸네일 url
- 모든 session에 sample video 추가
core:domain, kotlinx-coroutines-guava, kotlinx-serialization-json 추가
- material-icons-extended 추가
- ServiceScoped로 player와 session을 주입
- player의 listener를 기반으로 playbackState에 재생 상태 정보 저장
- MediaLibraryService를 구현
  - LibrarySessionCallback 구현을 위해 MediaItemProvider를 구현.
  - MediaId는 json을 활용하여 세션, 트랙 뿐만 아니라 태그 등을 자유롭게 표현할 수 있도록 함.
- 외부 모듈에 제공하는 player 컨트롤을 하기 위한 PlayerController
- player는 session id를 선택적인 argument로 가진다.
- argument, 마지막 재생된 세션, 첫번째 세션 순으로 재생할 session의 id를 찾는다.
- PlayerView composable은 실험적인 구현이므로 검증이 더 필요하다.
- 추후 플레이어 알림 클릭 시 사용할 deeplink 추가
- 플레이어 알림 클릭 시 player로 이동
Activity 없이 core:playback module의 PlaybackService만으로 지원.

ref. https://developer.android.com/training/cars/media/automotive-os
- app-tv, feature:tv-main, feature:tv-session 모듈 추가
- 각 모듈은 기존 모바일 앱 구현을 동일하게 tv용으로 구성.
- tv-session feature에서 tv용 compose 라이브러리를 사용하여 tv 맞춤 세션 브라우징 UI를 구현
- 플레이어는 feature:player를 재사용
- app-tv에서 SessionActivityIntentProviderImpl을 구현 후 주입. Now in Playing 카드 클릭 시 플레이어가 열리는 구현을 위함.
- agp, kotlin, compose를 포함하여 대부분의 라이브러리를 최신화
- gradle 8.3
- app-wear-os, feature:wear-main, feature:wear-player, feature:wear-session 모듈 추가
- 각 모듈은 기존 모바일 앱 구현을 동일하게 wear용으로 구성.
- wear-main에서는 wear용 compose-navigation을 이용(SwipeDismissableNavHost). 이 때, NavHost에 destination 추가 시, wear용 라이브러리를 사용 해야한다. (함수 이름도 같고, 크래시도 나지 않음)
- wear-session feature에서 wear용 compose 라이브러리를 사용하여 wear 맞춤 세션 브라우징 UI를 구현(ScalingLazyColumn, onRotaryScrollEvent)
- 플레이어는 wear os에 맞춰 재구현. video 없이 only audio 재생을 하도록 했다.
- app-wear-os에서 SessionActivityIntentProviderImpl을 구현 후 주입. 재생 인디케이터 클릭 시 플레이어가 열리도록 함.
- wear os player 구현에 필요하여 현재 media item의 title, artist, artworkUri를 PlaybackState에 추가
@workspace workspace changed the title (WIP) (Proposal) [#264] media3 integration (Proposal) [#264] media3 integration Sep 14, 2023
@workspace
Copy link
Author

@laco-dev 안녕하세요. 현재 reference-media3에 widget 업데이트가 포함 안되어있는데요, 업데이트 해주시면 다시 싱크 맞추겠습니다. 이제 합치기 위한 준비가 되어 리뷰 부탁드립니다. 변경 사항이 큰 것 같아 overview와 몇몇 comment를 달아뒀습니다.

}
return deepLinkPendingIntent
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

질문) 이 class의 목적이 어떻게 될까요?
PendingIntent를 생성하는거라면 exteions 형태로 만들어도 충분할것 같아보입니다.
객체 형태로 만들어져 있어야할 이유가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/droidknights/DroidKnights2023_App/pull/266/files/7d9204d899004c7b001fd1a4adb74721980fa591#diff-281b1044609ea759a0253956cdbac7889c69d2c1b66a445f36702e59f495c2a4R74-R81

core:playback module에서 MediaLibrarySession.Builder에서 MediaSession 클릭 시 사용자를 이동시키기 위한 setSessionActivity method에 쓰입니다. 각 앱마다 동작이 다르기에 interface를 선언하고 각 앱마다 다른 구현체를 넣어줬습니다.

@@ -12,4 +12,8 @@ interface SessionRepository {
suspend fun getBookmarkedSessionIds(): Flow<Set<String>>

suspend fun bookmarkSession(sessionId: String, bookmark: Boolean)

fun getCurrentPlayingSessionId(): Flow<String?>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sessionId가 null인 케이스가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null인 경우 = 재생을 한번도 안한 상태입니다.

마지막으로 재생된 session id를 data store에 저장합니다.

아래 callback이 불렸을 때 마지막으로 재생하던 미디어를 재생 시키는 구현에 사용됩니다. (position은 저장 안해둠)

약식으로 대응해뒀는데 값이 null일 땐 keynote를 재생하도록 했습니다.

https://developer.android.com/guide/topics/media/session/mediasession#resumption

suspend operator fun invoke(): String? {
return sessionRepository.getCurrentPlayingSessionId().firstOrNull()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NotNull 형태로 던져도 괜찮지 않을까 싶네요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment와 함께 고려했을 때, 아무것도 재생하지 않은 상태를 NonNull로 표현할 수 있을까요? 공백? 사실 명확하게 하고자 typing을 하려고 했었는데 .. ㅎㅎ

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetCurrentPlayingSessionUseCase 이라는 유즈케이스 이름과 반환하는 값으로 볼때 무엇을 반환하는지 잘 예측이 안되지 않을까요?

앞선 non-null 타입을 고려한다명 명확한 타입을 정의하는것도 괜찮아 보입니다.

@@ -101,6 +119,7 @@ turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine

coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutine" }
coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutine" }
coroutines-guava = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-guava", version.ref = "coroutine" }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: ListenableFuture와 coroutine을 함께 쓸 수 있도록 추가했습니다.

https://github.com/Kotlin/kotlinx.coroutines/blob/master/integration/kotlinx-coroutines-guava/README.md

Copy link
Contributor

@laco-dev laco-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

내용이 많아서 아직 모든 부분을 확인하지는 못했습니다. 😭
행사 Session과 미디어 Session이 이름이 중복되서 헷갈리는 상황이 많이 왔는데 이 이름이 일반적으로 미디어쪽의 세션이라고생각하는 상황이 많을까요?

suspend operator fun invoke(): String? {
return sessionRepository.getCurrentPlayingSessionId().firstOrNull()
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetCurrentPlayingSessionUseCase 이라는 유즈케이스 이름과 반환하는 값으로 볼때 무엇을 반환하는지 잘 예측이 안되지 않을까요?

앞선 non-null 타입을 고려한다명 명확한 타입을 정의하는것도 괜찮아 보입니다.

@workspace
Copy link
Author

workspace commented Sep 21, 2023

내용이 많아서 아직 모든 부분을 확인하지는 못했습니다. 😭 행사 Session과 미디어 Session이 이름이 중복되서 헷갈리는 상황이 많이 왔는데 이 이름이 일반적으로 미디어쪽의 세션이라고생각하는 상황이 많을까요?

안녕하세요. 상세한 리뷰 감사드립니다.

발표를 위해 구현했던 사항을 한번에 보내 pr이 너무 커지게 된 점 죄송합니다. pr overview에 남겨둔 방향으로 접근하시면 좀 더 용이한 리뷰가...🥲🥲🥲

미디어 Session으로 쓰이는 이름들은 보통 Player를 초기화 하는 쪽에서만 쓰이고 나머지는 행사 Session으로 봐주시면 됩니다.

저도 오랜만에 보니깐 충분히 헷갈릴 만한 상황 같네요. Session이라는 이름이 겹치는 이번 프로젝트에 한해서는 import alias 등으로 명확히 MediaSession* 이란 접두사를 붙여볼 수도 있을 것 같네요.

리뷰 달아주신 사항들은 개별로 커멘트 남기겠습니다.

@workspace
Copy link
Author

workspace commented Oct 11, 2023

안녕하세요. @laco-dev
여러가지가 겹치며 업데이트가 늦어진 점 사과드립니다. 🥲
마지막으로 리뷰 하신 후 주요 업데이트 사항 요약은 아래와 같습니다.

  • 리뷰사항 반영
  • ReadMe 업데이트
  • bookmark 구현 업데이트에 따른 수정
  • 테스트 깨지는 것 수정

더불어, 현재 json file을 이용하여 api 구현을 해두었기 때문에 pr을 그대로 빌드하면 Video 정보가 조회되지 않아 재생을 할 수 없습니다. 혹시 동작을 확인하시고자 한다면 GithubRawApigetSessions request 경로에서 /owner/repository/branch를 제 folk 것으로 임시로 변경해야 확인할 수 있습니다.

// GithubRawApi.kt

// 변경 전
@GET("/droidknights/DroidKnights2023_App/reference-media3/core/data/src/main/assets/sessions.json")

// 변경 후
@GET("/workspace/DroidKnights2023-app-with-media3/media3/core/data/src/main/assets/sessions.json"

또한, 몇가지 업데이트가 추가될 수 있는데, 이건 그냥 제 folk에서 계속 업데이트 하게될 것 같습니다. 혹시 #265 를 작업하신다면 제 folk repository(https://github.com/workspace/DroidKnights2023-app-with-media3) 도 병기해주시면 감사하겠습니다!

@taehwandev
Copy link
Member

머지합니다.

@taehwandev taehwandev merged commit 05bc31e into droidknights:2023/reference-media3 Apr 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants