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
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
540
仕様書を書く前にハーネスを作る - Agent Native開発は「探索を速く、判定を固く」
gotalab555
1
190
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
410
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
180
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
450
作るコストが小さくなった時代 幸せに働くために改めて考えたいこと 〜エンジニアとして価値を出し続けるために注視している二分野〜
yuppeeng
0
130
【やさしく解説 設計編 #1】「ドメイン駆動」と「実装駆動」ってなに? 〜設計の考え方を、たとえ話で学ぼう〜
panda728
PRO
1
140
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
350
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
160
【やさしく解説 設計編・中級 #4】ルールの寿命と、システムの年輪
panda728
PRO
2
170
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
130
Featured
See All Featured
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
340
Building AI with AI
inesmontani
PRO
1
1.1k
The untapped power of vector embeddings
frankvandijk
2
1.8k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1k
Leo the Paperboy
mayatellez
8
1.9k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
430
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
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 ご清聴ありがとうございました