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
Androidでオーディオアプリを作るということ
Search
rmakiyama
September 26, 2020
Technology
1
3.3k
Androidでオーディオアプリを作るということ
Androidでオーディオアプリを作るときに考慮すべきところなどを簡単に。
rmakiyama
September 26, 2020
Tweet
Share
More Decks by rmakiyama
See All by rmakiyama
UI State設計とテスト方針
rmakiyama
4
1.1k
KMPプロジェクトでマニュアルDIを使う選択
rmakiyama
0
420
Jetpack Composeとデザインシステム
rmakiyama
0
1.1k
TextField theme in Compose
rmakiyama
0
300
Androidエンジニアが1人という不安と向き合う
rmakiyama
6
6.8k
Jetpack Compose Canvas入門
rmakiyama
0
1.5k
HiltはDIをどうやってやっているのか
rmakiyama
1
290
Radiotalk Androidアプリにおけるモジュール分割の課題とこれから
rmakiyama
1
320
getChangePayload in DiffUtil
rmakiyama
0
3.2k
Other Decks in Technology
See All in Technology
ユニットテストに対する考え方の変遷 / Everyone should watch his live coding
mdstoy
0
120
ACA でMAGI システムを社内で展開しようとした話
mappie_kochi
0
160
VCC 2025 Write-up
bata_24
0
150
Azure Well-Architected Framework入門
tomokusaba
0
200
C# 14 / .NET 10 の新機能 (RC 1 時点)
nenonaninu
1
1.4k
From Prompt to Product @ How to Web 2025, Bucharest, Romania
janwerner
0
110
SwiftUIのGeometryReaderとScrollViewを基礎から応用まで学び直す:設計と活用事例
fumiyasac0921
0
120
生成AIで「お客様の声」を ストーリーに変える 新潮流「Generative ETL」
ishikawa_satoru
1
280
AI Agentと MCP Serverで実現する iOSアプリの 自動テスト作成の効率化
spiderplus_cb
0
420
FastAPIの魔法をgRPC/Connect RPCへ
monotaro
PRO
1
660
それでも私はContextに値を詰めたい | Go Conference 2025 / go conference 2025 fill context
budougumi0617
4
1.1k
動画データのポテンシャルを引き出す! Databricks と AI活用への奮闘記(現在進行形)
databricksjapan
0
130
Featured
See All Featured
Facilitating Awesome Meetings
lara
56
6.6k
Visualization
eitanlees
148
16k
How to Ace a Technical Interview
jacobian
280
23k
A better future with KSS
kneath
239
17k
Six Lessons from altMBA
skipperchong
28
4k
Embracing the Ebb and Flow
colly
88
4.8k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Typedesign – Prime Four
hannesfritz
42
2.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
237
140k
Git: the NoSQL Database
bkeepers
PRO
431
66k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
Optimizing for Happiness
mojombo
379
70k
Transcript
"OESPJEͰ ΦʔσΟΦΞϓϦΛ ࡞Δͱ͍͏͜ͱ Zli x ΤΩαΠτ ߹ಉLT 2020/09/26 ryo makiyama
ɹɹࣗݾհ •ࢁྎ •Radiotalkגࣜձࣾ •AndroidΤϯδχΞ • @_rmakiyama • rmakiyama
ԻΛ࠶ੜ͢Δ
ԻΛ࠶ੜ͢Δʹʁ • AudioTrack • SoundPool • MediaPlayer • ExoPlayer •
etc…
ԻΛ࠶ੜ͢Δʹʁ • AudioTrack • ੜͷԻσʔλΛѻ͑Δ • ࠷Ԇ͕গͳ͍ • ѻ͍͕͍͠… •
SoundPool • ͍Իʹద͍ͯ͠Δ • ޮՌԻͳͲ • ෛՙ͕͍ • Ԇ͕গͳ͍
ԻΛ࠶ੜ͢Δʹʁ • MediaPlayer • ࠷Ұൠత • ө૾ʹରԠ • ѻ͍͕؆୯ •
HLSະରԠ • ExoPlayer • GoogleͷϥΠϒϥϦ • ө૾ʹରԠ • ΧελϚΠζੑ͕ߴ͍ • HLSDASHʹରԠ
ExoPlayer val audioUri = Uri.parse(“https:"//sample.jp/media/media1.mp3”) val player = SimpleExoPlayer.Builder(context).build() val
sourceFactory = DefaultDataSourceFactory( context, Util.getUserAgent(context, "sample") ) val extractorsFactory = DefaultExtractorsFactory() val source = ProgressiveMediaSource.Factory(sourceFactory, extractorsFactory) .createMediaSource(audioUri) player.prepare(source)
؆୯
؆୯
ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ͕ࢭ·Δ • ผͷΞϓϦͰԻΛ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ •
etc…
Ͳ͏ͬͯͬͯΔͷ
ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ͕ࢭ·Δ • ผͷΞϓϦͰԻΛ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ •
etc… AndroidͷServiceΛར༻͢Δ
ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ͕ࢭ·Δ • ผͷΞϓϦͰԻΛ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ •
etc… ExoPlayerઌੜ͕ͬͯ͘ΕΔ
ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ͕ࢭ·Δ • ผͷΞϓϦͰԻΛ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ •
etc…
headset watch tv auto
༷ʑͳσόΠε͔Β ૢ࡞͞ΕΔ͜ͱΛ ఆ͢Δඞཁ͕͋Δ
ΦʔσΟΦΞϓϦͷਪΞʔΩςΫνϟ • ΫϥΠΞϯτ/αʔόʔઃܭ • ϝσΟΞίϯτϩʔϥʔ(ΫϥΠΞϯτ) • ϝσΟΞηογϣϯ(αʔόʔ) • UIʹΑΔૢ࡞ͱ ίϯςϯπใɾϓϨΠϠʔૢ࡞Λ͚ͨ
ref. https:"//developer.android.com/guide/topics/media-apps/media-apps-overview
UI/ϝσΟΞίϯτϩʔϥʔ(ΫϥΠΞϯτ) • UIίϯτϩʔϥʔͷΈͱΓͱΓ • ϓϨΠϠʔࣗମͱΓऔΓΛ͠ͳ͍ • ΞΫγϣϯηογϣϯͷίʔϧόοΫʹ • ۂใͷมߋͳͲηογϣϯ͔Β ίϯτϩʔϥʔ͕ίʔϧόοΫܗࣜͰड͚औΔ
ϝσΟΞηογϣϯ/ϓϨΠϠʔ(αʔόʔ) • 1ͭͷηογϣϯͰෳͷίϯτϩʔϥʔ͔Β ίʔϧόοΫΛड͚Δ͜ͱ͕Ͱ͖Δ • ϓϨΠϠʔηογϣϯ͔ΒͷΈૢ࡞͞ΕΔ • ίϯτϩʔϥʔ͔ΒͷίʔϧόοΫʹΑΓૢ࡞
ΦʔσΟΦΞϓϦ֓ཁ ref. https:"//developer.android.com/guide/topics/media-apps/media-apps-overview controller session player ui devices/controller
࣮ฤ%
ΦʔσΟΦΞϓϦ֓ཁʢ࣮دΓʣ ref. https:"//developer.android.com/guide/topics/media-apps/media-apps-overview
MediaBrowserService(session/player) class MyMediaService : MediaBrowserServiceCompat() { private lateinit var mediaSession:
MediaSessionCompat private lateinit var player: Player override fun onCreate() { super.onCreate() mediaSession = MediaSessionCompat(this, "MyMediaService").apply { … setCallback(myCallback) ɹɹɹɹɹɹ …
MediaBrowserService(session/player) override fun onCreate() { … } private val myCallback
= object : MediaSessionCompat.Callback() { override fun onPrepare() {} override fun onPlay() {} override fun onPause() {} override fun onStop() {} … }
MediaBrowserService(session/player) … override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints:
Bundle? ): BrowserRoot? { "// ଓ͞ΕͨΫϥΠΞϯτͷݕূΛ͢Δ "// ଓΛڋ൱͢Δͱ͖nullΛฦ͢ return BrowserRoot("root", null) }
MediaBrowserService(session/player) … override fun onLoadChildren( parentId: String, result: Result<MutableList<MediaBrowserCompat.MediaItem">> )
{ "// ΫϥΠΞϯτʹϝσΟΞͷϦετΛฦ͢ val list = getMetadata() result.sendResult(list) } …
Activity(UI/controller) class MediaPlayerActivity : AppCompatActivity() { private lateinit var mediaBrowser:
MediaBrowserCompat private lateinit var mediaController: MediaControllerCompat override fun onCreate(savedInstanceState: Bundle?) { … mediaBrowser = MediaBrowserCompat( this, ComponentName(this, MyMediaService"::class.java), connectionCallbacks, null
Activity(UI/controller) class MediaPlayerActivity : AppCompatActivity() { private lateinit var mediaBrowser:
MediaBrowserCompat private lateinit var mediaController: MediaControllerCompat override fun onCreate(savedInstanceState: Bundle?) { … } override fun onStart() { super.onStart() "// MediaBrowserServiceʹଓ mediaBrowser.connect()
Activity(UI/controller) class MediaPlayerActivity : AppCompatActivity() { … private lateinit var
mediaController: MediaControllerCompat … private val connectionCallbacks = object : MediaBrowserCompat.ConnectionCallback() { override fun onConnected() { "// sessionͷτʔΫϯ͔ΒcontrollerΛੜ mediaController = MediaControllerCompat(this@MediaPlayerActivity, mediaBrowser.sessionToken) .apply { registerCallback(controllerCallback) } "// UIͷૢ࡞ʹԠͯ͡controllerΛհͯ͠ΦʔσΟΦΛૢ࡞ "// ྫ) ࠶ੜɿmediaController.transportControls.play()
Activity(UI/controller) class MediaPlayerActivity : AppCompatActivity() { … private var controllerCallback
= object : MediaControllerCompat.Callback() { override fun onMetadataChanged(metadata: MediaMetadataCompat?) { "// ࠶ੜதͷίϯςϯπใͷมԽʹԠͯ͡UIΛߋ৽ } override fun onPlaybackStateChanged(state: PlaybackStateCompat?) { "// ࠶ੜͷঢ়ଶ(࠶ੜதఀࢭ)ͷมԽʹԠͯ͡UIΛߋ৽͢Δ } }
શʹཧղͨ͠ʁ
·ͱΊ •ԻΛ࠶ੜ͢Δ͚ͩͳΒ؆୯ʂ& •ΦʔσΟΦΞϓϦͰߟྀ͢Δ͜ͱҙ֎ͱଟ͍ • ࠓ͍ͯ͠ͳ͍͜ͱͨ͘͞Μ͋Δ…ʂ •ڵຯ͕༙͍ͨΒ࡞ͬͯΈΑ͏ʂ' • खΛಈ͔͢ͷେࣄʂ%