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
Chromecast対応を始めてみる
Search
takathemax
June 26, 2023
Programming
300
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Chromecast対応を始めてみる
takathemax
June 26, 2023
More Decks by takathemax
See All by takathemax
ComposeでのPicture in Picture
takathemax
0
260
Other Decks in Programming
See All in Programming
AI時代、エンジニアはどう育つのか -未経験エンジニアの成長を間近で見て考えたこと-
thasu0123
0
220
PostgreSQL 18で考えるUUID主キー
kazuhiro1982
0
460
React本体のコードリーディング
high_g_engineer
1
140
AI時代のPHPer生存戦略 ~「言語、もうなんでもよくない?」に本気で向き合う~
vivion
0
240
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.9k
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
1
1.5k
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
4k
源内ハンズオン概要編
hideg
0
100
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
750
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.3k
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
180
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
210
Featured
See All Featured
Accessibility Awareness
sabderemane
1
170
The Language of Interfaces
destraynor
162
27k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
230
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
250
YesSQL, Process and Tooling at Scale
rocio
174
15k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
830
Optimising Largest Contentful Paint
csswizardry
37
3.9k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
330
Ethics towards AI in product and experience design
skipperchong
2
340
Crafting Experiences
bethany
1
240
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
480
Transcript
© DMM Chromecast対応を始めてみる #dmm_android勉強会
© DMM 自己紹介 正木清駿 2020年中途入社 動画配信事業部所属 Android歴四年目くらい
© DMM 目次 1. Chromecast対応の概要 2. Senderの簡単な実装 3. まとめ
© DMM Chromecast対応の概要 https://developers.google.com/cast/docs/overview?hl=ja より引用
© DMM Chromecast対応の概要 モバイルエンジニア が開発するとなるとま ずはこっちが多い https://developers.google.com/cast/docs/overview?hl=ja より引用
© DMM Chromecast対応の概要 モバイルエンジニア が開発するとなるとま ずはこっちが多い AndroidTVアプリや、 Webレシーバーで対応 対応デバイスはGoogle Homeなどもあるので多
種多様 https://developers.google.com/cast/docs/overview?hl=ja より引用
© DMM Senderアプリの実装の流れ 1. Cast Application Framework(CAF)の導入 2. CastContextの初期化とOptionsProviderの準備 3.
キャストボタンの表示 4. 動画をChromecastで再生させる
© DMM ライブラリの導入 dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.mediarouter:mediarouter:1.4.0' implementation
'com.google.android.gms:play-services-cast-framework:21.3.0' }
© DMM CastContextとOptionsProvider • CastContext • ApplicationContextをもとに生成され、アプリ内でシングルトンで管理される • CAFのあらゆる処理に使用される •
OptionsProvider • CastContextの作成と初期化に必要 • ここでReceiverをGoogle Cast SDK Developer Consoleで登録した際にえられ るIDを設定する
© DMM OptionsProvider import android.content.Context import com.google.android.gms.cast.CastMediaControlIntent import com.google.android.gms.cast.framework.CastOptions import
com.google.android.gms.cast.framework.OptionsProvider import com.google.android.gms.cast.framework.SessionProvider class CastOptionsProvider : OptionsProvider { override fun getCastOptions (context: Context): CastOptions { return CastOptions.Builder() .setReceiverApplicationId(CastMediaControlIntent. DEFAULT_MEDIA_RECEIVER_APPLICATION_ID) .build() } override fun getAdditionalSessionProviders (context: Context): MutableList<SessionProvider>? { return null } }
© DMM OptionsProvider <meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME" android:value="org.takathemax.castsample.ui.player.CastOptionsProvider" />
© DMM CastContextの初期化 CastContext.getSharedInstance( context, Dispatchers.IO.asExecutor() ) .addOnSuccessListener { castContext
-> //TODO: CastContextを使用してやりたいこと } .addOnFailureListener { exception -> //TODO: error handling }
© DMM ボタンの表示 • お手軽にやりたいならCastButtonFactoryを使用すればOK • ダイアログをカスタムしたものにする場合はMediaRouterを使用してルー トの選択状態を更新したりするのを自前で実装する必要がある • 今回はCastButtonFactoryの方法を紹介
© DMM ボタンの表示 @Composable fun CastButton( modifier: Modifier = Modifier
){ AndroidView( modifier = modifier, factory = ::MediaRouteButton , update = { CastButtonFactory .setUpMediaRouteButton( it.context, it) }, ) } Scaffold( modifier = Modifier .fillMaxSize(), topBar = { TopAppBar( title = { Text("CastSample") }, actions = { CastButton() } ) }, content = { PlayerBlock() } )
© DMM 動画をキャストする 1. キャストセッションを監視 • SessionManagerListener 2. セッションが繋がったら動画情報を送る •
RemoteMediaClient
© DMM 動画をキャストする class CastViewModel : ViewModel() ,SessionManagerListener<CastSession> { //
説明しやすい様にViewModelにExoPlayerにMediaItemを持っているとする val mediaItem = MediaItem.fromUri( "streaming url" ) override fun onSessionStarted (session: CastSession , sessionId: String) { // ここでRemoteMediaClient に情報を渡す } } // CastContext にアクセスできるところ castContext .sessionManager .addSessionManagerListener(viewModel , CastSession::class.java)
© DMM 動画をキャストする class CastViewModel : ViewModel() ,SessionManagerListener<CastSession> { val
mediaItem = MediaItem.fromUri( "streaming url" ) override fun onSessionStarted (session: CastSession , sessionId: String) { val mediaInfo = MediaInfo .Builder( mediaItem.localConfiguration ?.uri.toString()) .setStreamType(MediaInfo. STREAM_TYPE_BUFFERED) .setContentType( "videos/mp4") .build() val options = MediaLoadOptions.Builder() .setAutoplay( true) .build() session. remoteMediaClient?.load(mediaInfo , options) } } これで完了
© DMM 動画をキャストする //再生 session.remoteMediaClient?.play() //一時停止 session.remoteMediaClient?.pause() //任意の場所にシーク val targetPosition
= 1000L val mediaSeekOptions = MediaSeekOptions.Builder() .setPosition(targetPosition).build() session.remoteMediaClient?.seek(mediaSeekOptions) // 倍速 session.remoteMediaClient?.setPlaybackRate( 2.0) // 一秒ごとに再生位置を取得する session.remoteMediaClient?.addProgressListener( { progressMs, _ -> // 特定の再生位置になったら何かするとか }, 1000L ) ExoPlayerを利用している場合は CastPlayerを利用できる
© DMM ご清聴ありがとうございました