Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
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
270
Other Decks in Programming
See All in Programming
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
240
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
370
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
240
[DroidKaigi 2026] Bring your own phones to Gradle Managed Devices
f2lk
0
120
Claude Codeを組織的に動かして月400PRを実現した話
happy_ryo
0
280
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
330
Heart of Swift Concurrency
koher
0
740
Go のフラットな パッケージに 「ファイル単位の private」を 〜Linter “declscope” を作った話〜
mpyw
0
320
スマート反転とウェブアクセシビリティ
camiha
0
210
そのリトライ、死んだコネクションを使い回していませんか ── GoのHTTPクライアントとHTTP/2を実プロダクト障害から学び直す
myus4a
0
140
「新人AI禁止のその先へ ― 参加と協働のステップアップ」Vibe TOKYO, AI & CRAFT / 2026年8月21日
kentarowada
0
100
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
460
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
540
Designing Powerful Visuals for Engaging Learning
tmiket
1
550
Facilitating Awesome Meetings
lara
57
7.1k
Exploring anti-patterns in Rails
aemeredith
4
510
Paper Plane (Part 1)
katiecoart
PRO
2
11k
Six Lessons from altMBA
skipperchong
29
4.5k
GraphQLとの向き合い方2022年版
quramy
50
15k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
840
Music & Morning Musume
bryan
48
7.4k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
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 ご清聴ありがとうございました