Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Jetpack Compose の動画表示対応 をまとめてみた
Search
nagayan
September 01, 2023
Programming
0
1.2k
Jetpack Compose の動画表示対応 をまとめてみた
Android Jetpack Compose で動画表示対応 をまとめました。
nagayan
September 01, 2023
Tweet
Share
Other Decks in Programming
See All in Programming
それ、本当に安全? ファイルアップロードで見落としがちなセキュリティリスクと対策
penpeen
7
4k
Unicodeどうしてる? PHPから見たUnicode対応と他言語での対応についてのお伺い
youkidearitai
PRO
1
2.6k
Oxlintはいいぞ
yug1224
5
1.4k
MUSUBIXとは
nahisaho
0
140
AIエージェントのキホンから学ぶ「エージェンティックコーディング」実践入門
masahiro_nishimi
6
680
生成AIを活用したソフトウェア開発ライフサイクル変革の現在値
hiroyukimori
PRO
0
110
20260127_試行錯誤の結晶を1冊に。著者が解説 先輩データサイエンティストからの指南書 / author's_commentary_ds_instructions_guide
nash_efp
1
1k
OSSとなったswift-buildで Xcodeのビルドを差し替えられるため 自分でXcodeを直せる時代になっている ダイアモンド問題編
yimajo
3
630
AWS re:Invent 2025参加 直前 Seattle-Tacoma Airport(SEA)におけるハードウェア紛失インシデントLT
tetutetu214
2
120
LLM Observabilityによる 対話型音声AIアプリケーションの安定運用
gekko0114
2
440
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
AgentCoreとHuman in the Loop
har1101
5
250
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.4k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
80
Believing is Seeing
oripsolob
1
59
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1k
Agile that works and the tools we love
rasmusluckow
331
21k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
140
Making Projects Easy
brettharned
120
6.6k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.1k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.4k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
830
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
110
Transcript
株式会社 Gunosy テクノロジー本部 永山 雄 2023年9月1日 Jetpack Compose の動画表示対応 をまとめてみた
(C) Gunosy Inc. All Rights Reserved. PAGE | 2 ▪
名前:nagayan / 永山 雄 ▪ 所属:株式会社Gunosy – Android エンジニア auサービスToday を担当 ▪ X:@nagayan_dev 自己紹介
(C) Gunosy Inc. All Rights Reserved. PAGE | 3 アジェンダ
背景・方針 Jetpack Compose の動画実装 • Exoplayer、AndroidViewを使った、基本実装 • デフォルトの動画パーツを OFF にする • VideoStateの定義と実装 • 動画パーツの実装 • 動画の進捗とシークバーを連動させる • ライフサイクルで再生・停止・解放 まとめ
(C) Gunosy Inc. All Rights Reserved. PAGE | 4 ▪
auサービスTodayでは Compose 実装への置き換えを随時進めて います ▪ Jetpack Compose の動画実装を調べていましたが、情報が散見 されていました ▪ 動画部分のCompose化をしたため、その対応をまとめました ▪ 既存のデザインを踏襲するため、デフォルトの動画パーツは使用し ない方針です 背景・方針
(C) Gunosy Inc. All Rights Reserved. PAGE | 5 ▪
Android Jetpack Compose で動画表示 – https://tech.gunosy.io/entry/android_compose_video_player 今回の内容
(C) Gunosy Inc. All Rights Reserved. Jetpack Compose の動画実装
(C) Gunosy Inc. All Rights Reserved. PAGE | 7 dependencies
{ implementation "androidx.media3:media3-exoplayer:1.1.1" 使用するライブラリ Jetpack Compose の動画実装
(C) Gunosy Inc. All Rights Reserved. PAGE | 8 val
exoPlayer = remember(context) { ExoPlayer.Builder(context).build().apply { setMediaItem(MediaItem.fromUri(Uri.parse(url))) prepare() seekTo(0L) } } Exoplayer、AndroidViewを使った、基本実装 Jetpack Compose の動画実装 ▪ 動画を再生する Exoplayerを 作成します
(C) Gunosy Inc. All Rights Reserved. PAGE | 9 Exoplayer、AndroidViewを使った、基本実装
Jetpack Compose の動画実装 ▪ 作成したExoplayerを、 AndroidView の PlayerView に設定します val exoPlayer = remember(context) ~~~ Box(~~~) { AndroidView( modifier = ~~~, factory = { context -> PlayerView(context).apply { this.player = exoPlayer } })}
(C) Gunosy Inc. All Rights Reserved. PAGE | 10 パーツがデフォルトのもの
→パーツを自前実装する Jetpack Compose の動画実装 Exoplayer、AndroidViewを使った、基本実装
(C) Gunosy Inc. All Rights Reserved. PAGE | 11 val
exoPlayer = remember(context) ~~~ Box(~~~) { AndroidView( modifier = ~~~, factory = { context -> PlayerView(context).apply { useController = false this.player = exoPlayer } })} デフォルトの動画パーツを OFF にする Jetpack Compose の動画実装 ▪ PlayerView の useController を false に指定することで、デ フォルトの動画パーツを非表 示にできます
(C) Gunosy Inc. All Rights Reserved. PAGE | 12 ▪
UIを更新するため、独自の VideoState を定義します ▪ remember で State を保持します VideoStateの定義と実装 Jetpack Compose の動画実装 var videoState by remember { mutableStateOf(VideoState.LOADING) } enum class VideoState { LOADING, PAUSE, START, ENDED }
(C) Gunosy Inc. All Rights Reserved. PAGE | 13 ▪
onPlaybackStateChan ged で VideoState の 更新をします。 VideoStateの定義と実装 Jetpack Compose の動画実装 exoPlayer.addListener(object : Player.Listener { override fun onPlaybackStateChanged(playbackState: Int) { videoState = when { playbackState == Player.STATE_READY && playWhenReady -> VideoState.START playbackState == Player.STATE_ENDED && playWhenReady -> VideoState.ENDED ~~~ -> VideoState.LOADING ~~~ --> VideoState.PAUSE
(C) Gunosy Inc. All Rights Reserved. PAGE | ▪ 再生停止ボタンを実装します
▪ 先ほどの State を元に、Start と Pause を切り替えます 14 動画パーツの実装 Jetpack Compose の動画実装 var videoState by remember { ~~~ } ~~~ if (videoState == VideoState.START) { Image( painter = ~中断ボタン画像~, contentDescription = ~~~, ) } else { Image( painter = ~再生ボタン画像~, contentDescription = ~~~, ) } ~~~
(C) Gunosy Inc. All Rights Reserved. PAGE | 15 動画パーツの実装
Jetpack Compose の動画実装 var currentTime by remember { mutableStateOf(0L) } ~~~ Slider( ~~~ value = currentTime.toFloat(), valueRange = 0f..exoPlayer.duration.~~~, colors = SliderDefaults.colors( ~~~ ))} ▪ シークバーの実装です ▪ Slider を用いて実装します ▪ 動画の進捗度として currentTime を定義します ▪ Slider の value に指定し、 valueRange は 0 から 動画 の長さを設定します
(C) Gunosy Inc. All Rights Reserved. PAGE | 16 ▪
シークバーの操作を反映させ ます ▪ onValueChange はシーク バー操作時に通知される Callback で、ここで通知され た値を currentTime に設定し ます 動画の進捗とシークバーを連動させる Jetpack Compose の動画実装 var currentTime by remember { mutableStateOf(0L) } ~~~ Slider( ~~~ value = currentTime.toFloat(), onValueChange = { timeMs -> val time = timeMs.toLong() exoPlayer.seekTo(time) currentTime = time }, valueRange = 0f..exoPlayer.duration.~~~, ~~~
(C) Gunosy Inc. All Rights Reserved. PAGE | 17 ▪
動画が再生されてても、シーク バーが動いてくれません ▪ 再生状態の時に LaunchedEffect 内で repeat をし、動画時間を取得して currentTime に反映させます。 動画の進捗とシークバーを連動させる Jetpack Compose の動画実装 var currentTime by remember { mutableStateOf(0L) } ~~~ if (videoState == VideoState.START) { LaunchedEffect(Unit) { repeat(Int.MAX_VALUE) { delay(1000) currentTime = exoPlayer.contentPosition }}}
(C) Gunosy Inc. All Rights Reserved. PAGE | 18 ▪
アプリがバックグラウンドに行っ た時に再生しっぱなしになってし まう ▪ DisposableEffect を用いて、ラ イフサイクルに合わせて処理を 実行 – onResume:再生 – onPause:停止 ライフサイクルで再生・停止・解放 Jetpack Compose の動画実装 DisposableEffect(lifecycleOwner) { val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { if (videoState == VideoState.START) { exoPlayer.play() } } else if (event == Lifecycle.Event.ON_PAUSE) { exoPlayer.pause() } } lifecycleOwner.lifecycle.addObserver(observer) ~~~
(C) Gunosy Inc. All Rights Reserved. PAGE | 19 ▪
DisposableEffect の onDispose で解放処理を実行 します ライフサイクルで再生・停止・解放 Jetpack Compose の動画実装 DisposableEffect(lifecycleOwner) { ~~~ onDispose { exoPlayer.run { playWhenReady = false ~~~ release() } lifecycleOwner.lifecycle.removeObserver(observer) } }
(C) Gunosy Inc. All Rights Reserved. PAGE | 20 完成
Jetpack Compose の動画実装
(C) Gunosy Inc. All Rights Reserved. PAGE | 21 ▪
Jetpack Compose で基本的な動画表示の実装について紹介しま した ▪ デフォルトの動画パーツを表示するだけなら簡単に実装できます が、カスタマイズしたパーツを表示するとなるとちょっと工夫が必要 になります ▪ 動画再生が一定時間経過した後に動画パーツを非表示にしたり、 動画終了時に End Screen を表示できるようになれば、より高機 能な動画が実現できると思います まとめ Jetpack Compose ライフを楽しみましょう!
中表紙 情報を世界中の人に最適に届ける (C) Gunosy Inc. All Rights Reserved.