Slide 1

Slide 1 text

"OESPJEͰ ΦʔσΟΦΞϓϦΛ ࡞Δͱ͍͏͜ͱ Zli x ΤΩαΠτ ߹ಉLT 2020/09/26 ryo makiyama

Slide 2

Slide 2 text

ɹɹࣗݾ঺հ •຀ࢁྎ •Radiotalkגࣜձࣾ •AndroidΤϯδχΞ • @_rmakiyama • rmakiyama

Slide 3

Slide 3 text

Ի੠Λ࠶ੜ͢Δ

Slide 4

Slide 4 text

Ի੠Λ࠶ੜ͢Δʹ͸ʁ • AudioTrack • SoundPool • MediaPlayer • ExoPlayer • etc…

Slide 5

Slide 5 text

Ի੠Λ࠶ੜ͢Δʹ͸ʁ • AudioTrack • ੜͷԻ੠σʔλΛѻ͑Δ • ࠷΋஗Ԇ͕গͳ͍ • ѻ͍͕೉͍͠… • SoundPool • ୹͍Ի੠ʹద͍ͯ͠Δ • ޮՌԻͳͲ • ෛՙ͕௿͍ • ஗Ԇ͕গͳ͍

Slide 6

Slide 6 text

Ի੠Λ࠶ੜ͢Δʹ͸ʁ • MediaPlayer • ࠷΋Ұൠత • ө૾ʹ΋ରԠ • ѻ͍͕؆୯ • HLSະରԠ • ExoPlayer • Google੡ͷϥΠϒϥϦ • ө૾ʹ΋ରԠ • ΧελϚΠζੑ͕ߴ͍ • HLS΍DASH౳ʹରԠ

Slide 7

Slide 7 text

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)

Slide 8

Slide 8 text

؆୯

Slide 9

Slide 9 text

؆୯

Slide 10

Slide 10 text

ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥ΢ϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ੠͕ࢭ·Δ • ผͷΞϓϦͰԻ੠Λ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ • etc…

Slide 11

Slide 11 text

Ͳ͏΍ͬͯ΍ͬͯΔͷ

Slide 12

Slide 12 text

ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥ΢ϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ੠͕ࢭ·Δ • ผͷΞϓϦͰԻ੠Λ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ • etc… AndroidͷServiceΛར༻͢Δ

Slide 13

Slide 13 text

ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥ΢ϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ੠͕ࢭ·Δ • ผͷΞϓϦͰԻ੠Λ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ • etc… ExoPlayerઌੜ͕΍ͬͯ͘ΕΔ

Slide 14

Slide 14 text

ΦʔσΟΦΞϓϦʹٻΊΒΕΔ͜ͱ • όοΫάϥ΢ϯυͰ࠶ੜͰ͖Δ • ΠϠϗϯ͕ൈ͚ͨΒԻ੠͕ࢭ·Δ • ผͷΞϓϦͰԻ੠Λ࠶ੜ͢Δͱఀࢭ͢Δ • ༷ʑͳσόΠε͔Βૢ࡞͕Ͱ͖Δ • etc…

Slide 15

Slide 15 text

headset watch tv auto

Slide 16

Slide 16 text

༷ʑͳσόΠε͔Β ૢ࡞͞ΕΔ͜ͱΛ ૝ఆ͢Δඞཁ͕͋Δ

Slide 17

Slide 17 text

ΦʔσΟΦΞϓϦͷਪ঑ΞʔΩςΫνϟ • ΫϥΠΞϯτ/αʔόʔઃܭ • ϝσΟΞίϯτϩʔϥʔ(ΫϥΠΞϯτ) • ϝσΟΞηογϣϯ(αʔόʔ) • UI౳ʹΑΔૢ࡞ͱ
 ίϯςϯπ৘ใɾϓϨΠϠʔૢ࡞Λ෼͚ͨ ref. https:"//developer.android.com/guide/topics/media-apps/media-apps-overview

Slide 18

Slide 18 text

UI/ϝσΟΞίϯτϩʔϥʔ(ΫϥΠΞϯτ) • UI͸ίϯτϩʔϥʔͷΈͱ΍ΓͱΓ • ϓϨΠϠʔࣗମͱ͸௚઀΍ΓऔΓΛ͠ͳ͍ • ΞΫγϣϯ͸ηογϣϯ΁ͷίʔϧόοΫʹ • ۂ৘ใͷมߋͳͲ͸ηογϣϯ͔Β
 ίϯτϩʔϥʔ͕ίʔϧόοΫܗࣜͰड͚औΔ

Slide 19

Slide 19 text

ϝσΟΞηογϣϯ/ϓϨΠϠʔ(αʔόʔ) • 1ͭͷηογϣϯͰෳ਺ͷίϯτϩʔϥʔ͔Β
 ίʔϧόοΫΛड͚Δ͜ͱ͕Ͱ͖Δ • ϓϨΠϠʔ͸ηογϣϯ͔ΒͷΈૢ࡞͞ΕΔ • ίϯτϩʔϥʔ͔ΒͷίʔϧόοΫʹΑΓૢ࡞

Slide 20

Slide 20 text

ΦʔσΟΦΞϓϦ֓ཁ ref. https:"//developer.android.com/guide/topics/media-apps/media-apps-overview controller session player ui devices/controller

Slide 21

Slide 21 text

࣮૷ฤ%

Slide 22

Slide 22 text

ΦʔσΟΦΞϓϦ֓ཁʢ࣮૷دΓʣ ref. https:"//developer.android.com/guide/topics/media-apps/media-apps-overview

Slide 23

Slide 23 text

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) ɹɹɹɹɹɹ …

Slide 24

Slide 24 text

MediaBrowserService(session/player) override fun onCreate() { … } private val myCallback = object : MediaSessionCompat.Callback() { override fun onPrepare() {} override fun onPlay() {} override fun onPause() {} override fun onStop() {} … }

Slide 25

Slide 25 text

MediaBrowserService(session/player) … override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle? ): BrowserRoot? { "// ઀ଓ͞ΕͨΫϥΠΞϯτͷݕূΛ͢Δ "// ઀ଓΛڋ൱͢Δͱ͖͸nullΛฦ͢ return BrowserRoot("root", null) }

Slide 26

Slide 26 text

MediaBrowserService(session/player) …
 override fun onLoadChildren( parentId: String, result: Result> ) { "// ΫϥΠΞϯτʹϝσΟΞͷϦετΛฦ͢ val list = getMetadata() result.sendResult(list) } …

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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()

Slide 29

Slide 29 text

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()

Slide 30

Slide 30 text

Activity(UI/controller) class MediaPlayerActivity : AppCompatActivity() { … private var controllerCallback = object : MediaControllerCompat.Callback() { override fun onMetadataChanged(metadata: MediaMetadataCompat?) { "// ࠶ੜதͷίϯςϯπ৘ใͷมԽʹԠͯ͡UIΛߋ৽ } override fun onPlaybackStateChanged(state: PlaybackStateCompat?) { "// ࠶ੜͷঢ়ଶ(࠶ੜத΍ఀࢭ)ͷมԽʹԠͯ͡UIΛߋ৽͢Δ } }

Slide 31

Slide 31 text

׬શʹཧղͨ͠ʁ

Slide 32

Slide 32 text

·ͱΊ •Ի੠Λ࠶ੜ͢Δ͚ͩͳΒ؆୯ʂ& •ΦʔσΟΦΞϓϦͰߟྀ͢Δ͜ͱ͸ҙ֎ͱଟ͍ • ࠓ೔࿩͍ͯ͠ͳ͍͜ͱ΋ͨ͘͞Μ͋Δ…ʂ •ڵຯ͕༙͍ͨΒ࡞ͬͯΈΑ͏ʂ' • खΛಈ͔͢ͷେࣄʂ%