package Ġcom . ky l ent t . medi ap layer . domain . medi ase ssion . service . notification Ċ Ċ import Ġandroid . app . Notification Ċ import Ġandroid . app . Notification Channel Ċ import Ġandroid . app . Notification Manager Ċ import Ġandroid . app . Pending Intent Ċ import Ġandroid . content . Broadcast Receiver Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . Intent Ċ import Ġandroid . content . Intent Filter Ċ import Ġandroid . graphics . Bitmap Ċ import Ġandroid . graphics . Bitmap Factory Ċ import Ġandroid . os . Build Ċ import Ġandroid . os . Bundle Ċ import Ġandroidx . annotation . MainThread Ċ import Ġandroidx . annotation . Requires Api Ċ import Ġandroidx . annotation . Worker Thread Ċ import Ġandroidx . core . app . Notification Compat Ċ import Ġandroidx . lifecycle . Lifecycle Ċ import Ġandroidx . lifecycle . Lifecycle Owner Ċ import Ġandroidx . media 3 . common . Media Item Ċ import Ġandroidx . media 3 . common . Player Ċ import Ġandroidx . media 3 . session .* Ċ import Ġcom . ky l ent t . medi ap layer . R Ċ import Ġcom . ky l ent t . medi ap layer . app . deleg ates . App Delegate Ċ import Ġcom . ky l ent t . medi ap layer . core . coroutines . App Dispatch ers Ċ import Ġcom . ky l ent t . medi ap layer . core . deleg ates . Auto Cancel Job Ċ import Ġcom . ky l ent t . medi ap layer . core . ex op layer . Player Extension . is O ngo ing Ċ import Ġcom . ky l ent t . medi ap layer . core . ex op layer . Player Extension . is Repeat All Ċ import Ġcom . ky l ent t . medi ap layer . core . ex op layer . Player Extension . is Repeat Off Ċ import Ġcom . ky l ent t . medi ap layer . core . ex op layer . Player Extension . is Repeat One Ċ import Ġcom . ky l ent t . medi ap layer . core . ex op layer . Player Extension . is State Buffer ing Ċ import Ġcom . ky l ent t . medi ap layer . core . ex op layer . Player Extension . is State Ended Ċ import Ġcom . ky l ent t . medi ap layer . core . ex op layer . Player Extension . is State Idle Ċ import Ġcom . ky l ent t . medi ap layer . core . media 3 . Media Item Factory Ċ import Ġcom . ky l ent t . medi ap layer . data . source . local . Media Store Song Ċ import Ġcom . ky l ent t . medi ap layer . domain . medi ase ssion . service . Lifecycle Service Ċ import Ġcom . ky l ent t . medi ap layer . domain . medi ase ssion . service . Music Library Service Ċ import Ġcom . ky l ent t . medi ap layer . domain . medi ase ssion . service . On Changed Ċ import Ġcom . ky l ent t . medi ap layer . domain . medi ase ssion . service . connector . Controller Command Ċ import Ġcom . ky l ent t . medi ap layer . domain . medi ase ssion . service . connector . Controller Command . Companion . wrap With Fade Out Ċ import Ġcom . ky l ent t . medi ap layer . domain . medi ase ssion . service . sessions . Music Library Session Manager Ċ import Ġcom . ky l ent t . medi ap layer . helper . Preconditions . check Argument Ċ import Ġcom . ky l ent t . medi ap layer . helper . Preconditions . check MainThread Ċ import Ġcom . ky l ent t . medi ap layer . helper . Preconditions . check Not MainThread Ċ import Ġcom . ky l ent t . medi ap layer . helper . Preconditions . check State Ċ import Ġcom . ky l ent t . medi ap layer . helper . Version Helper Ċ import Ġcom . ky l ent t . medi ap layer . helper . media . Media Item Helper . Companion . or Empty Ċ import Ġcom . ky l ent t . medi ap layer . ui . activity . main activity . MainActivity Ċ import Ġkotlinx . coroutines .* Ċ import Ġtim ber . log . Tim ber Ċ Ċ /** Ċ Ġ* Ġ[ Media Notification . Provider ] ĠImplementation Ġfor Ġ[ Music Library Service ] Ċ Ġ* Ġmust Ġbe ĠInitialized Ġafter Ġ[ Media Library Service ] ĠSuper . onCreate () Ċ Ġ* Ġ@ throws Ġ[ IllegalStateException ] Ġif Ġ[ Media Library Service ] Ġbase Context Ġis Ġnull Ċ Ġ* Ġ@ author ĠK yl ent t Ċ Ġ* Ġ@ since Ġ 2 0 2 2 / 0 4 / 3 0 Ċ Ġ*/ Ċ Ċ class ĠMusic Library Notification Provider ( Ċ ĉ private Ġval Ġmusic Service : ĠMusic Library Service , Ċ ĉ private Ġval Ġsession Manager : ĠMusic Library Session Manager Ċ ) Ġ: ĠMedia Notification . Provider Ġ{ ĊĊ ĉ private Ġval Ġnotification Builder Ġ= ĠNotification Builder () Ċ ĉ private Ġval Ġnotification Action Receiver Ġ= ĠNotification Action Receiver () ĊĊ ĉ private Ġval Ġplayer Listener Impl Ġ= ĠPlayer Listener Impl () Ċ ĉ private Ġval Ġplayer Changed Impl Ġ= ĠPlayer Changed Impl () ĊĊ ĉ private Ġval Ġinternal Job Ġ= ĠSuper visor Job ( music Service . service Job ) ĊĊ ĉ private Ġval Ġimmediate Scope Ġ= ĠCor outine Scope ( dispatch ers . main Immediate Ġ+ Ġinternal Job ) Ċ ĉ private Ġval Ġmain Scope Ġ= ĠCor outine Scope ( dispatch ers . main Ġ+ Ġinternal Job ) Ċ ĉ private Ġval Ġio Scope Ġ= ĠCor outine Scope ( dispatch ers . io Ġ+ Ġinternal Job ) ĊĊ ĉ private Ġvar Ġis Initialized : ĠBoolean Ġ= Ġfalse Ċ ĉ private Ġvar Ġis Released : ĠBoolean Ġ= Ġfalse Ċ ĉ private Ġvar Ġitem Bitmap Ġ= ĠPair < Media Item , ĠBitmap ? >( Media Item . EMPTY , Ġnull ) ĊĊ ĉ private Ġval Ġdispatch ers : ĠApp Dispatch ers Ċĉ ĉ get () Ġ= Ġmusic Service . coroutine Dispatch ers ĊĊ ĉ private Ġval Ġcurrent Media Session Ċĉ ĉ get () Ġ= Ġsession Manager . getCurrent Media Session () ĊĊ ĉ private Ġval Ġnotification Manager Ċĉ ĉ get () Ġ= Ġmusic Service . notification Manager ĊĊ ĉ val Ġmedia Notification Channel Name : ĠString Ċĉ ĉ get () Ġ= ĠNOT IFICATION _ CHANNEL _ NAME ĊĊ ĉ val Ġmedia Notification Name : ĠString Ċĉ ĉ get () Ġ= ĠNOT IFICATION _ NAME ĊĊ ĉ val Ġmedia Notification Id : ĠInt Ċĉ ĉ get () Ġ= ĠNOT IFICATION _ ID ĊĊ ĉ init Ġ{ Ċĉ ĉ check State ( music Service . sessions . isEmpty ()) Ġ{ Ċĉĉ ĉ " This ĠProvider Ġmust Ġbe Ġinitialized Ġbefore ĠMedia Library Service . on Get Session ()" Ċĉ ĉ } ĊĊĉ ĉ if Ġ( music Service . base Context Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ initialize Provider () Ċĉ ĉ } Ġelse Ġ{ ĊĊĉĉ ĉ val Ġowner Ġ= Ġmusic Service Ġas ĠLifecycle Service ĊĊĉĉ ĉ val Ġobs Ġ= Ġobject Ġ: Ġandroidx . lifecycle . Lifecycle Event Observer Ġ{ ĊĊĉĉĉ ĉ override Ġfun Ġon StateChanged ( source : ĠLifecycle Owner , Ġevent : ĠLifecycle . Event ) Ġ{ Ċĉĉĉĉ ĉ if Ġ( owner . lifecycle . currentState . is At Least ( Lifecycle . State . CREATED )) Ġ{ Ċĉĉĉĉĉ ĉ initialize Provider () Ċĉĉĉĉĉ ĉ owner . lifecycle . remove Observer ( this ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } ĊĊĉĉ ĉ } ĊĊĉĉ ĉ owner . lifecycle . add Observer ( obs ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ @ MainThread Ċ ĉ private Ġfun Ġinitialize Provider () Ġ{ Ċĉ ĉ check MainThread () ĊĊĉ ĉ if Ġ( isInitialized ) Ġ{ Ċĉĉ ĉ return ĠTim ber . w (" Notification Provider Ġinitialize Provider () Ġcalled Ġtwice ") Ċĉ ĉ } ĊĊĉ ĉ check State ( music Service . base Context Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ " Cannot ĠInitialize ĠNotification Provider Ġwithout ĠContext , ĠInitialize Ġit Ġin Ġor Ġafter ĠonCreate ()" Ċĉ ĉ } ĊĊĉ ĉ if Ġ( Version Helper . has O re o ()) Ġ{ Ċĉĉ ĉ create Notification Channel ( notification Manager ) Ċĉ ĉ } ĊĊĉ ĉ session Manager . register Player EventListener ( player Listener Impl ) ĊĊĉ ĉ music Service . register Receiver ( notification Action Receiver , ĠIntent Filter ( PLAY BACK _ CONTROL _ INT ENT )) Ċĉ ĉ session Manager . register Player Changed Listener ( player Changed Impl ) ĊĊĉ ĉ isInitialized Ġ= Ġtrue Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCreate Ġ[ Notification Channel ] Ġfor Ġ[ Version Helper . has O re o ] Ċĉ Ġ* Ġ@ param Ġmanager ĠThe ĠNotification ĠManager Ċĉ Ġ*/ ĊĊ ĉ @ Requires Api ( Build . VERSION _ CODES . O ) Ċ ĉ private Ġfun Ġcreate Notification Channel ( manager : ĠNotification Manager ) Ġ{ Ċĉ ĉ val Ġimportance Ġ= ĠNotification Manager . IMPORT ANCE _ LOW Ċĉ ĉ val Ġchannel Ġ= ĠNotification Channel ( NOTIFICATION _ CHANNEL _ NAME , ĠNOT IFICATION _ NAME , Ġimportance ) Ċĉ ĉ manager . create Notification Channel ( channel ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠUpdate ĠNotification ĠCallback Ġfrom Ġ[ android x . media 3 . session . Media Notification Manager . Media Controller Listener ] Ċĉ Ġ* Ġany Of : Ġ[ Player . EVENT _ PLAY BACK _ STATE _ CHANGED ], Ġ[ Player . EVENT _ PLAY _ WHEN _ READY _ CHANGED ], Ġ[ Player . EVENT _ MEDIA _ METADATA _ CHANGED ] Ċĉ Ġ* Ġ@ param Ġmedia Controller Ġof Ġthe ĠLinked Ġ[ Media Session ] Ċĉ Ġ* Ġ@ param Ġon Notification Changed Callback ĠCallback ĠMethod Ġfor ĠAsync ĠTask Ċĉ Ġ*/ ĊĊ ĉ override Ġfun Ġcreate Notification ( Ċĉ ĉ media Controller : ĠMedia Controller , Ċĉ ĉ action Factory : ĠMedia Notification . Action Factory , Ċĉ ĉ on Notification Changed Callback : ĠMedia Notification . Provider . Callback Ċ ĉ ): ĠMedia Notification Ġ{ Ċĉ ĉ return Ġcreate Notification Internal Impl ( Ċĉĉ ĉ media Controller , Ġaction Factory , Ġon Notification Changed Callback Ċĉ ĉ ) Ċ ĉ } ĊĊ ĉ override Ġfun Ġhandle Custom Action ( Ċĉ ĉ media Controller : ĠMedia Controller , Ċĉ ĉ action : ĠString , Ċĉ ĉ extras : ĠBundle Ċ ĉ ) Ġ= ĠUnit ĊĊ ĉ fun Ġget Session Notification ( session : ĠMedia Session ): ĠNotification Ġ{ Ċĉ ĉ return Ġget Notification For Session ( session , ĠNOT IFICATION _ CHANNEL _ NAME ) Ċ ĉ } ĊĊ ĉ fun Ġupdate Notification From Session ( session : ĠMedia Session ) Ġ{ Ċĉ ĉ notification Manager . notify ( media Notification Id , Ġget Session Notification ( session )) Ċ ĉ } ĊĊ ĉ fun Ġupdate Session Notification ( notification : ĠNotification ) Ġ{ Ċĉ ĉ if Ġ( session Manager . getCurrent Media Session () Ġ!= Ġnull ) Ġ{ Ċĉĉ ĉ notification Manager . notify ( media Notification Id , Ġnotification ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġvar Ġvalidator Job Ġby ĠAuto Cancel Job () Ċ ĉ suspend Ġfun Ġlaunch Session Notification Validator ( Ċĉ ĉ session : ĠMedia Session , Ċĉ ĉ interval : ĠLong Ġ= ĠNOT IFICATION _ UPDATE _ INTERVAL , Ċĉ ĉ on Update : Ġsuspend Ġ( Notification ) Ġ-> ĠUnit Ċ ĉ ) Ġ= Ġwith Context ( dispatch ers . main ) Ġ{ Ċĉ ĉ validator Job Ġ= Ġlaunch Ġ{ Ċĉĉ ĉ dispatch Suspend Notification Validator ( 2 , Ġinterval ) Ġ{ Ċĉĉĉ ĉ val Ġnotification Ġ= Ġget Notification For Session ( session , Ġmedia Notification Channel Name ) Ċĉĉĉ ĉ consider Foreground Service ( session . player , Ġnotification , Ġtrue ) Ċĉĉĉ ĉ on Update ( notification ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġsuspend Ġfun Ġsuspend Update Notification ( Ċĉ ĉ session : ĠMedia Session Ċ ĉ ): ĠUnit Ġ= Ġwith Context ( dispatch ers . main Immediate ) Ġ{ Ċĉ ĉ update Notification From Session ( session ) Ċĉ ĉ launch Session Notification Validator ( session ) Ġ{ Ċĉĉ ĉ ensure Active () Ċĉĉ ĉ update Session Notification ( it ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġsuspend Ġfun Ġdispatch Suspend Notification Validator ( Ċĉ ĉ times : ĠInt , Ċĉ ĉ interval : ĠLong , Ċĉ ĉ update : Ġsuspend Ġ() Ġ-> ĠUnit Ċ ĉ ) Ġ= Ġwith Context ( dispatch ers . main ) Ġ{ Ċĉ ĉ repeat ( times ) Ġ{ Ċĉĉ ĉ delay ( interval ) Ċĉĉ ĉ ensure Active () Ċĉĉ ĉ update () Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ suspend Ġfun Ġsuspend Handle Media Item Transition ( Ċĉ ĉ session : ĠMedia Session , Ċĉ ĉ item : ĠMedia Item , Ċĉ ĉ reason : ĠInt Ġ// ĠTODO Ċ ĉ ) Ġ= Ġwith Context ( dispatch ers . main ) Ġ{ Ċĉ ĉ ensure Active () ĊĊĉ ĉ with Context ( dispatch ers . io ) Ġ{ Ċĉĉ ĉ val Ġbitmap Ġ= Ġget Media Item Embedded Picture ( item )?. let Ġ{ ĠbyteArray Ġ-> Ċĉĉĉ ĉ get Bitmap From ByteArray ( byteArray ) Ċĉĉ ĉ } ĊĊĉĉ ĉ check Cancellation Ġ{ Ġbitmap ?. recycle () Ġ} Ċĉĉ ĉ val Ġsquared Bitmap Ġ= Ġbitmap ?. let Ġ{ Ġresize Bitmap For Notification ( it ) Ġ} ĊĊĉĉ ĉ check Cancellation Ġ{ Ċĉĉĉ ĉ // ĠCo il Ġmight Ġgive Ġthe Ġsame Ġinstance Ġso Ġsquared Bitmap Ġis Ġnot Ġre cyc led Ċĉĉĉ ĉ bitmap ?. recycle () Ċĉĉ ĉ } Ċĉĉ ĉ item Bitmap Ġ= Ġitem Ġto Ġsquared Bitmap Ċĉ ĉ } ĊĊĉ ĉ suspend Update Notification ( session ) Ċ ĉ } ĊĊ ĉ @ Worker Thread Ċ ĉ private Ġfun Ġget Media Item Embedded Picture ( item : ĠMedia Item ): ĠByteArray ? Ġ{ Ċĉ ĉ check Not MainThread () Ċĉ ĉ return Ġmusic Service . media Item Helper . get Embedded Picture ( item ) Ċ ĉ } ĊĊ ĉ @ Worker Thread Ċ ĉ private Ġfun Ġget Bitmap From ByteArray ( bytes : ĠByteArray ): ĠBitmap ? Ġ{ Ċĉ ĉ check Not MainThread () Ċĉ ĉ return ĠBitmap Factory . decode ByteArray ( bytes , Ġ 0 , Ġbytes . size ) Ċ ĉ } ĊĊ ĉ private Ġinline Ġfun ĠCor outine Scope . check Cancellation ( if Cancelled : Ġ() Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ if Not Active Ġ{ Ġif Cancelled () Ġ} Ċĉ ĉ ensure Active () Ċ ĉ } ĊĊ ĉ private Ġinline Ġfun ĠCor outine Scope . if Not Active ( block : Ġ() Ġ-> ĠUnit ) Ġ{ Ċĉ ĉ if Ġ(! isActive ) Ġblock () Ċ ĉ } ĊĊĠ Ġ/** ĊĠĠ Ġ* Ġ@ param Ġ[ player ] Ġthe Ġplayer ĊĠĠ Ġ* Ġ@ return Ġ[ item Bitmap ]? Ġif Ġ[ player ] ĠMedia Item ĠBitmap Ġis Ġready ĊĠĠ Ġ* Ġ@ see Ġitem Bitmap ĊĠĠ Ġ*/ ĊĊĠ Ġprivate Ġfun ĠgetItem Bitmap ( player : ĠPlayer ): ĠBitmap ? Ġ{ Ċĉ ĉ val Ġequal Ġ= Ġplayer . current Media Item . id Equal ( item Bitmap . first ) Ċĉ ĉ return Ġelse Null ( equal ) Ġ{ Ġitem Bitmap . second Ġ} ĊĠ Ġ} ĊĊ ĉ private Ġinline Ġfun Ġ< T > Ġelse Null ( condition : ĠBoolean , Ġblock : Ġ() Ġ-> ĠT ): ĠT ? Ġ{ Ċĉ ĉ return Ġif Ġ( condition ) Ġblock () Ġelse Ġnull Ċ ĉ } ĊĊ ĉ private Ġval Ġinternal Foreground Condition : Ġ( Player ) Ġ-> ĠBoolean Ġ= Ġ{ Ġit . play When Ready Ġ} ĊĊ ĉ private Ġfun Ġcreate Notification Internal Impl ( Ċĉ ĉ controller : ĠMedia Controller , Ċĉ ĉ action Factory : ĠMedia Notification . Action Factory , Ċĉ ĉ callback : ĠMedia Notification . Provider . Callback Ċ ĉ ): ĠMedia Notification Ġ{ ĊĊĉ ĉ val Ġnotification Ġ= Ġget Notification From Player ( controller , Ġmedia Notification Channel Name ) ĊĊĉ ĉ val Ġshould Foreground Ġ= Ġinternal Foreground Condition ( controller ) ĊĊĉ ĉ if Ġ( music Service . is Service Foreground Ġ!= Ġshould Foreground ) Ġ{ Ċĉĉ ĉ music Service . update Foreground State ( should Foreground ) Ċĉ ĉ } ĊĊĉ ĉ return ĠMedia Notification ( media Notification Id , Ġnotification ) Ċ ĉ } ĊĊ ĉ private Ġfun Ġget Notification From Player ( Ċĉ ĉ player : ĠPlayer , Ċĉ ĉ channel Name : ĠString Ċ ĉ ): ĠNotification Ġ{ ĊĊĉ ĉ Tim ber . d (" get Notification From Player Ġfor Ġ" Ġ+ Ċĉĉ ĉ "${ player . current Media Item ?. media Metadata ?. title }" Ċĉ ĉ ) ĊĊĉ ĉ val Ġicon Ġ= ĠgetItem Bitmap ( player ) ĊĊĉ ĉ return Ġnotification Builder . build Media Style Notification ( player , Ġicon , Ġchannel Name ) Ċ ĉ } ĊĊ ĉ private Ġfun Ġget Notification For Session ( Ċĉ ĉ session : ĠMedia Session , Ċĉ ĉ channel Name : ĠString Ċ ĉ ): ĠNotification Ġ{ ĊĊĉ ĉ Tim ber . d (" get Notification For Session Ġfor Ġ" Ġ+ Ċĉĉ ĉ "${ session . player . current Media Item ?. media Metadata ?. title }" Ċĉ ĉ ) ĊĊĉ ĉ val Ġicon Ġ= ĠgetItem Bitmap ( session . player ) Ċĉ ĉ return Ġnotification Builder . build Media Style Notification ( session , Ġicon , Ġchannel Name ) Ċ ĉ } ĊĊ ĉ val Ġforeground Service Condition : Ġ( Player ) Ġ-> ĠBoolean Ġ= Ġ{ Ġit . playback State . is O ngo ing () Ġ} ĊĊĠ ĉ fun Ġconsider Foreground Service ( player : ĠPlayer , Ġnotification : ĠNotification , Ġis Validator : ĠBoolean ) Ġ{ Ċĉ ĉ when Ġ{ Ċĉĉ ĉ foreground Service Condition ( player ) Ġ-> Ġ{ Ċĉĉĉ ĉ if Ġ( music Service . is Service Foreground ) Ġreturn Ċĉĉĉ ĉ music Service . start Foreground Service ( media Notification Id , Ġnotification , Ġtrue ) Ċĉĉ ĉ } Ċĉĉ ĉ else Ġ-> Ġ{ Ċĉĉĉ ĉ if Ġ(! music Service . is Service Foreground ) Ġreturn Ċĉĉĉ ĉ music Service . stop Foreground Service ( media Notification Id , Ċĉĉĉĉ ĉ remove Notification Ġ= Ġfalse , Ċĉĉĉĉ ĉ is Event Ġ= Ġtrue Ċĉĉĉ ĉ ) Ċĉĉ ĉ } Ċĉ ĉ } ĊĠ Ġ} ĊĊ ĉ @ MainThread Ċ ĉ fun Ġrelease () Ġ{ Ċĉ ĉ check MainThread () ĊĊĉ ĉ if Ġ( is Released ) Ġ{ Ċĉĉ ĉ return Ċĉ ĉ } ĊĊĉ ĉ music Service . unregister Receiver ( notification Action Receiver ) Ċĉ ĉ Tim ber . d (" Notification Provider Ġreceiver ĠUn Registered ") ĊĊĉ ĉ is Released Ġ= Ġtrue Ċ ĉ } ĊĊ ĉ private Ġinner Ġclass ĠNotification Action Receiver Ġ: ĠBroadcast Receiver () Ġ{ ĊĊĉ ĉ override Ġfun Ġon Receive ( p 0 : ĠContext ?, Ġp 1 : ĠIntent ?) Ġ{ Ċĉĉ ĉ p 1 ?. let Ġ{ Ġhandle Notification Action Impl ( it ) Ġ} Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġhandle Notification Action Impl ( intent : ĠIntent ) Ġ{ Ċĉĉ ĉ val Ġget Ġ= Ġcurrent Media Session Ġ?: Ġreturn ĊĊĉĉ ĉ val Ġaction Ġ= Ġintent . getString Extra ( PLAY BACK _ CONTROL _ ACTION ) Ġ?: Ġreturn Ċĉĉ ĉ if Ġ( get . player . current Media Item Ġ== Ġnull ) Ġ{ Ċĉĉĉ ĉ return Ġvalidate Item ( get , Ġintent ) Ċĉĉ ĉ } Ċĉĉ ĉ when Ġ( action ) Ġ{ Ċĉĉĉ ĉ ACTION _ PLAY Ġ-> Ġon Receive Action Play ( get ) Ċĉĉĉ ĉ ACTION _ PAUSE Ġ-> Ġon Receive Action Pause ( get ) Ċĉĉĉ ĉ ACTION _ NEXT Ġ-> Ġon Receive Action Next ( get ) Ċĉĉĉ ĉ ACTION _ PREV Ġ-> Ġon Receive Action Prev ( get ) Ċĉĉĉ ĉ ACTION _ REPEAT _ OFF _ TO _ ONE Ġ-> Ġon Receive Repeat Off ToOne ( get ) Ċĉĉĉ ĉ ACTION _ REPEAT _ ONE _ TO _ ALL Ġ-> Ġon Receive Repeat One To All ( get ) Ċĉĉĉ ĉ ACTION _ REPEAT _ ALL _ TO _ OFF Ġ-> Ġon Receive Repeat All To Off ( get ) Ċĉĉĉ ĉ ACTION _ STOP _ CANCEL Ġ-> Ġon Receive Stop Cancel ( get ) Ċĉĉĉ ĉ ACTION _ DIS MIS S _ NOTIFICATION Ġ-> Ġon Receive Stop Cancel ( get ) Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġvar ĠisValid ating Ġ= Ġfalse Ċĉ ĉ private Ġfun Ġvalidate Item ( session : ĠMedia Session , Ġintent : ĠIntent ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ Tim ber . d (" check Item ĠCurrent Media Item : Ġ$ current Media Item ") ĊĊĉĉ ĉ if Ġ( current Media Item Ġ== Ġnull Ġ&& Ġ! isValid ating ) Ġ{ Ċĉĉĉ ĉ isValid ating Ġ= Ġtrue ĊĊĉĉĉ ĉ val Ġmedia Id Ġ= Ġintent . getString Extra ( PLAY BACK _ ITEM _ ID ) Ċĉĉĉ ĉ when Ġ{ Ċĉĉĉĉ ĉ media Id Ġ== Ġnull Ġ-> Ġmusic Service . stop Service ( true ) Ċĉĉĉĉ ĉ media Id . startsWith ( Media Store Song . MEDIA _ ID _ PREFIX ) Ġ-> Ġ{ Ċĉĉĉĉĉ ĉ music Service . main Scope Ċĉĉĉĉĉĉ ĉ . launch Ġ{ Ċĉĉĉĉĉĉĉ ĉ val Ġitem Ġ= Ġmusic Service . media Repository . get Media Store Song ById ( media Id ) Ċĉĉĉĉĉĉĉ ĉ item ?. let Ġ{ Ġset Media Item ( it . as Media Item ) Ġ} Ċĉĉĉĉĉĉĉ ĉ isValid ating Ġ= Ġfalse Ċĉĉĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Action Play ( session : ĠMedia Session ): ĠUnit Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ if Ġ( play When Ready Ġ&& Ġplayback State . is O ngo ing ()) Ġ{ Ċĉĉĉ ĉ return Ġupdate Notification From Session ( session ) Ċĉĉ ĉ } ĊĊĉĉ ĉ when Ġ{ Ċĉĉĉ ĉ playback State . is State Ended () Ġ-> Ġ{ Ċĉĉĉĉ ĉ if Ġ( hasNext Media Item ()) Ġseek To Next Media Item () Ċĉĉĉĉ ĉ seek To ( 0 L ) Ċĉĉĉ ĉ } Ċĉĉĉ ĉ playback State . is State Idle () Ġ-> Ġ{ Ċĉĉĉĉ ĉ prepare () Ċĉĉĉ ĉ } Ċĉĉ ĉ } ĊĊĉĉ ĉ play When Ready Ġ= Ġtrue Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Action Pause ( session : ĠMedia Session ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ if Ġ(! play When Ready Ġ&& Ġplayback State . is O ngo ing ()) Ġ{ Ċĉĉĉ ĉ return Ġupdate Notification From Session ( session ) Ċĉĉ ĉ } Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ check State ( playback State . is O ngo ing ()) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠIllegalStateException ) Ġ{ Ċĉĉĉ ĉ Tim ber . e ("$ e : ĠNotification ĠPause Ġreceived Ġwhen Ġ$ this Ġis ĠId le Ġ/ ĠEn ded ") Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ play When Ready Ġ= Ġfalse Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Action Next ( session : ĠMedia Session ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ if Ġ(! hasNext Media Item () Ġ&& Ġplayback State . is O ngo ing ()) Ġ{ Ċĉĉĉ ĉ return Ġupdate Notification From Session ( session ) Ċĉĉ ĉ } Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ check State ( hasNext Media Item ()) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠIllegalStateException ) Ġ{ Ċĉĉĉ ĉ Tim ber . e ("$ e : ĠNotification ĠNext Ġreceived Ġwhen Ġ$ this Ġhas Ġno ĠNext ĠItem ") Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ seek To Next Media Item () Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Action Prev ( session : ĠMedia Session ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ if Ġ(! has Previous Media Item () Ġ&& Ġplayback State . is O ngo ing ()) Ġ{ Ċĉĉĉ ĉ return Ġupdate Notification From Session ( session ) Ċĉĉ ĉ } Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ check State ( has Previous Media Item ()) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠIllegalStateException ) Ġ{ Ċĉĉĉ ĉ Tim ber . e ("$ e : ĠNotification ĠPrevious Ġreceived Ġwhen Ġ$ this Ġhas Ġno ĠPrevious ĠItem ") Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ seek To Previous Media Item () Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Repeat Off ToOne ( session : ĠMedia Session ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ if Ġ(! repeat Mode . is Repeat Off () Ġ&& Ġplayback State . is O ngo ing ()) Ġ{ Ċĉĉĉ ĉ return Ġupdate Notification From Session ( session ) Ċĉĉ ĉ } Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ check State ( repeat Mode . is Repeat Off ()) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠIllegalStateException ) Ġ{ Ċĉĉĉ ĉ Tim ber . e ("$ e : ĠNotification ĠRepeat ToOne Ġreceived Ġwhen Ġ$ this ĠRepeat Ġis Ġnot ĠOff ") Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ repeat Mode Ġ= ĠPlayer . REPEAT _ MODE _ ONE Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Repeat One To All ( session : ĠMedia Session ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ if Ġ(! repeat Mode . is Repeat One () Ġ&& Ġplayback State . is O ngo ing ()) Ġ{ Ċĉĉĉ ĉ return Ġupdate Notification From Session ( session ) Ċĉĉ ĉ } Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ check State ( repeat Mode . is Repeat One ()) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠIllegalStateException ) Ġ{ Ċĉĉĉ ĉ Tim ber . e ("$ e : ĠNotification ĠRepeat To All Ġreceived Ġwhen Ġ$ this ĠRepeat Ġis Ġnot ĠOne ") Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ repeat Mode Ġ= ĠPlayer . REPEAT _ MODE _ ALL Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Repeat All To Off ( session : ĠMedia Session ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ if Ġ(! repeat Mode . is Repeat All () Ġ&& Ġplayback State . is O ngo ing ()) Ġ{ Ċĉĉĉ ĉ return Ġupdate Notification From Session ( session ) Ċĉĉ ĉ } Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ check State ( repeat Mode . is Repeat All ()) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠIllegalStateException ) Ġ{ Ċĉĉĉ ĉ Tim ber . e ("$ e : ĠNotification ĠRepeat To Off Ġreceived Ġwhen Ġ$ this ĠRepeat Ġis Ġnot ĠAll ") Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ repeat Mode Ġ= ĠPlayer . REPEAT _ MODE _ OFF Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġon Receive Stop Cancel ( session : ĠMedia Session ) Ġ= Ġwith ( session . player ) Ġ{ Ċĉĉ ĉ when Ġ{ Ċĉĉĉ ĉ playback State . is O ngo ing () Ġ-> Ġ{ Ċĉĉĉĉ ĉ val Ġcommand Ġ= ĠController Command . STOP . wrap With Fade Out ( true , Ġ 1 0 0 0 L ) Ċĉĉĉĉ ĉ music Service . session Connector . send Controller Command ( command ) Ċĉĉĉ ĉ } Ċĉĉĉ ĉ else Ġ-> Ġ{ Ċĉĉĉĉ ĉ Tim ber . d (" on Receive Stop Cancel Ġ$ this Ġnot ĠOn Go ing ") ĊĊĉĉĉĉ ĉ music Service . stop Foreground Service ( media Notification Id , Ċĉĉĉĉĉ ĉ remove Notification Ġ= Ġtrue , Ġis Event Ġ= Ġmusic Service . is Service Foreground Ċĉĉĉĉ ĉ ) ĊĊĉĉĉĉ ĉ if Ġ(! MainActivity . is Alive ) Ġ{ Ċĉĉĉĉĉ ĉ music Service . stop Service ( true ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ @ Worker Thread Ċ ĉ private Ġsuspend Ġfun Ġresize Bitmap For Notification ( bitmap : ĠBitmap ): ĠBitmap Ġ{ Ċĉ ĉ val Ġsize Ġ= Ġif Ġ( Version Helper . has R ()) Ġ 2 5 6 Ġelse Ġ 5 1 2 Ċĉ ĉ return Ġmusic Service . co il Helper . square Bitmap ( bitmap Ġ= Ġbitmap , Ġsize Ġ= Ġsize , Ġfast Path Ġ= Ġtrue ) Ċ ĉ } ĊĊĠ Ġprivate Ġfun ĠMedia Item ?. id Equal ( that : ĠMedia Item ?): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġid Equal ( that ?. media Id . toString ()) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun ĠMedia Item ?. id Equal ( that : ĠString ): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġthis ?. media Id Ġ== Ġthat ĊĠ Ġ} ĊĊ ĉ private Ġinner Ġclass ĠPlayer Listener Impl Ġ: ĠPlayer . Listener Ġ{ ĊĊĉ ĉ private Ġvar Ġupdate Notification Job Ġby ĠAuto Cancel Job () Ċĉ ĉ private Ġvar Ġmedia Item Transition Job Ġby ĠAuto Cancel Job () ĊĊĉ ĉ override Ġfun Ġon Media Item Transition ( media Item : ĠMedia Item ?, Ġreason : ĠInt ) Ġ{ Ċĉĉ ĉ super . on Media Item Transition ( media Item , Ġreason ) ĊĊĉĉ ĉ val Ġitem Ġ= Ġmedia Item Ġ?: ĠMedia Item Factory . EMPTY ĊĊĉĉ ĉ session Manager . getCurrent Media Session ()?. let Ġ{ Ċĉĉĉ ĉ media Item Transition Job Ġ= Ġmain Scope . launch Ġ{ Ċĉĉĉĉ ĉ suspend Handle Media Item Transition ( it , Ġitem , Ġreason ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ override Ġfun Ġon Repeat Mode Changed ( repeat Mode : ĠInt ) Ġ{ Ċĉĉ ĉ super . on Repeat Mode Changed ( repeat Mode ) ĊĊĉĉ ĉ session Manager . getCurrent Media Session ()?. let Ġ{ Ċĉĉĉ ĉ update Notification Job Ġ= Ġmain Scope . launch Ġ{ Ġsuspend Update Notification ( it ) Ġ} Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ override Ġfun Ġon Playback StateChanged ( playback State : ĠInt ) Ġ{ Ċĉĉ ĉ super . on Playback StateChanged ( playback State ) ĊĊĉĉ ĉ session Manager . getCurrent Media Session ()?. let Ġ{ Ġdispatch Notification Validator ( it ) Ġ} Ċĉ ĉ } ĊĊĉ ĉ override Ġfun Ġon Play When Ready Changed ( play When Ready : ĠBoolean , Ġreason : ĠInt ) Ġ{ Ċĉĉ ĉ super . on Play When Ready Changed ( play When Ready , Ġreason ) ĊĊĉĉ ĉ session Manager . getCurrent Media Session ()?. let Ġ{ Ġdispatch Notification Validator ( it ) Ġ} Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġdispatch Notification Validator ( session : ĠMedia Session ) Ġ{ Ċĉĉ ĉ main Scope . launch Ġ{ Ċĉĉĉ ĉ this @ Music Library Notification Provider . launch Session Notification Validator ( session ) Ġ{ Ċĉĉĉĉ ĉ update Session Notification ( it ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġinner Ġclass ĠPlayer Changed Impl Ġ: ĠOn Changed < Player > Ġ{ ĊĊĉ ĉ override Ġfun ĠonChanged ( old : ĠPlayer ?, Ġnew : ĠPlayer ) Ġ{ Ċĉĉ ĉ check Argument ( old Ġ!== Ġnew ) ĊĊĉĉ ĉ // Ġnull Ġmeans Ġplayer Ġis Ġfirst Ġtime Ġchanged Ġor Ġreleased Ċĉĉ ĉ // Ġin Ġboth Ġcases Ġlistener Ġis Ġempty Ċĉĉ ĉ /* old ?. remove Listener ( player Listener Impl ) ĊĊĉĉ ĉ new . addListener ( player Listener Impl ) */ Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġinner Ġclass ĠNotification Builder Ġ{ ĊĊĉ ĉ fun Ġbuild Media Style Notification ( Ċĉĉ ĉ media Session : ĠMedia Session , Ċĉĉ ĉ large Icon : ĠBitmap ?, Ċĉĉ ĉ channelId : ĠString , Ċĉ ĉ ): ĠNotification Ġ{ Ċĉĉ ĉ return ĠNotification Compat . Builder ( music Service , Ġchannel Id ) Ċĉĉĉ ĉ . apply Ġ{ ĊĊĉĉĉĉ ĉ val Ġplayer Ġ= Ġmedia Session . player ĊĊĉĉĉĉ ĉ val Ġcontent Intent Ġ= ĠPending Intent Ċĉĉĉĉĉ ĉ . getActivity ( music Service , Ġ 4 4 5 , ĠApp Delegate . launcher Intent (), Ċĉĉĉĉĉĉ ĉ Pending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉĉĉĉ ĉ ) ĊĊĉĉĉĉ ĉ val Ġmedia Item Ġ= Ġplayer . current Media Item . or Empty () ĊĊĉĉĉĉ ĉ set Channel Id ( channelId ) Ċĉĉĉĉ ĉ setContent Intent ( content Intent ) Ċĉĉĉĉ ĉ setContent Title ( media Item . media Metadata . title ) Ċĉĉĉĉ ĉ setContent Text ( media Item . media Metadata . artist ) Ċĉĉĉĉ ĉ set Small Icon ( R . drawable . play _ icon _ theme 3 _ notification ) ĊĊĉĉĉĉ ĉ setColor ized ( true ) Ċĉĉĉĉ ĉ set O ngo ing ( false ) Ċĉĉĉĉ ĉ set Show When ( false ) ĊĊĉĉĉĉ ĉ val Ġsub Text Ġ= Ġmedia Item . media Metadata . album Title Ċĉĉĉĉ ĉ if Ġ(! sub Text . isNull OrEmpty ()) Ġset Sub Text ( sub Text ) ĊĊĉĉĉĉ ĉ val Ġrepeat Action Ġ= Ġwhen Ġ( player . repeat Mode ) Ġ{ Ċĉĉĉĉĉ ĉ Player . REPEAT _ MODE _ OFF Ġ-> Ġmake Action Repeat Off ToOne ( media Item ) Ċĉĉĉĉĉ ĉ Player . REPEAT _ MODE _ ONE Ġ-> Ġmake Action Repeat One To All ( media Item ) Ċĉĉĉĉĉ ĉ Player . REPEAT _ MODE _ ALL Ġ-> Ġmake Action Repeat All To Off ( media Item ) Ċĉĉĉĉĉ ĉ else Ġ-> Ġthrow ĠIllegalStateException () Ċĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġprev Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( player . has Previous Media Item ()) Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Prev ( media Item ) Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Prev Disabled ( media Item ) Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġshow Play Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( player . playback State . is State Buffer ing ()) Ġ{ Ċĉĉĉĉĉĉ ĉ ! player . play When Ready Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ ! player . is Playing Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġplay Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( show Play Action ) Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Play ( media Item ) Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Pause ( media Item ) Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġnext Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( player . hasNext Media Item ()) Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Next ( media Item ) Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Next Disabled ( media Item ) Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ addAction ( repeat Action ) Ċĉĉĉĉ ĉ addAction ( prev Action ) Ċĉĉĉĉ ĉ addAction ( play Action ) Ċĉĉĉĉ ĉ addAction ( next Action ) Ċĉĉĉĉ ĉ addAction ( make Action Stop Cancel ( media Item )) ĊĊĉĉĉĉ ĉ set Large Icon ( large Icon ) ĊĊĉĉĉĉ ĉ val Ġdismiss Intent Ġ= Ġmake Dismiss Pending Intent ( media Item ) Ċĉĉĉĉ ĉ set Delete Intent ( dismiss Intent ) ĊĊĉĉĉĉ ĉ val Ġstyle Ġ= ĠMedia Style Notification Helper Ċĉĉĉĉĉ ĉ . Decorated Media Custom View Style ( media Session ) Ċĉĉĉĉĉ ĉ . set Cancel Button Intent ( dismiss Intent ) Ċĉĉĉĉĉ ĉ . set Show Cancel Button ( true ) Ċĉĉĉĉĉ ĉ . set Show Actions In Compact View ( 1 , 2 , 3 ) Ċĉĉĉĉ ĉ setStyle ( style ) ĊĊĉĉĉ ĉ }. build () Ċĉ ĉ } ĊĊĉ ĉ fun Ġbuild Media Style Notification ( Ċĉĉ ĉ player : ĠPlayer , Ċĉĉ ĉ large Icon : ĠBitmap ?, Ċĉĉ ĉ channelId : ĠString , Ċĉ ĉ ): ĠNotification Ġ{ Ċĉĉ ĉ return ĠNotification Compat . Builder ( music Service , Ġchannel Id ) Ċĉĉĉ ĉ . apply Ġ{ ĊĊĉĉĉĉ ĉ val Ġcontent Intent Ġ= ĠPending Intent Ċĉĉĉĉĉ ĉ . getActivity ( music Service , Ġ 4 4 5 , ĠApp Delegate . launcher Intent (), Ċĉĉĉĉĉĉ ĉ Pending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉĉĉĉ ĉ ) ĊĊĉĉĉĉ ĉ val Ġmedia Item Ġ= Ġplayer . current Media Item . or Empty () ĊĊĉĉĉĉ ĉ set Channel Id ( channelId ) Ċĉĉĉĉ ĉ setContent Intent ( content Intent ) Ċĉĉĉĉ ĉ setContent Title ( media Item . media Metadata . title ) Ċĉĉĉĉ ĉ setContent Text ( media Item . media Metadata . artist ) Ċĉĉĉĉ ĉ set Small Icon ( R . drawable . play _ icon _ theme 3 _ notification ) ĊĊĉĉĉĉ ĉ setColor ized ( true ) Ċĉĉĉĉ ĉ set O ngo ing ( player . playback State . is O ngo ing ()) Ċĉĉĉĉ ĉ set Show When ( false ) ĊĊĉĉĉĉ ĉ val Ġsub Text Ġ= Ġmedia Item . media Metadata . album Title Ċĉĉĉĉ ĉ if Ġ(! sub Text . isNull OrEmpty ()) Ġset Sub Text ( sub Text ) ĊĊĉĉĉĉ ĉ val Ġrepeat Action Ġ= Ġwhen Ġ( player . repeat Mode ) Ġ{ Ċĉĉĉĉĉ ĉ Player . REPEAT _ MODE _ OFF Ġ-> Ġmake Action Repeat Off ToOne ( media Item ) Ċĉĉĉĉĉ ĉ Player . REPEAT _ MODE _ ONE Ġ-> Ġmake Action Repeat One To All ( media Item ) Ċĉĉĉĉĉ ĉ Player . REPEAT _ MODE _ ALL Ġ-> Ġmake Action Repeat All To Off ( media Item ) Ċĉĉĉĉĉ ĉ else Ġ-> Ġthrow ĠIllegalStateException () Ċĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġprev Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( player . has Previous Media Item ()) Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Prev ( media Item ) Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Prev Disabled ( media Item ) Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġshow Play Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( player . playback State . is State Buffer ing ()) Ġ{ Ċĉĉĉĉĉĉ ĉ ! player . play When Ready Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ ! player . is Playing Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġplay Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( show Play Action ) Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Play ( media Item ) Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Pause ( media Item ) Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ val Ġnext Action Ġ= Ċĉĉĉĉĉ ĉ if Ġ( player . hasNext Media Item ()) Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Next ( media Item ) Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ make Action Next Disabled ( media Item ) Ċĉĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ addAction ( repeat Action ) Ċĉĉĉĉ ĉ addAction ( prev Action ) Ċĉĉĉĉ ĉ addAction ( play Action ) Ċĉĉĉĉ ĉ addAction ( next Action ) Ċĉĉĉĉ ĉ addAction ( make Action Stop Cancel ( media Item )) ĊĊĉĉĉĉ ĉ set Large Icon ( large Icon ) ĊĊĉĉĉĉ ĉ val Ġdismiss Intent Ġ= Ġmake Dismiss Pending Intent ( media Item ) Ċĉĉĉĉ ĉ set Delete Intent ( dismiss Intent ) ĊĊĉĉĉĉ ĉ val Ġstyle Ġ= Ġandroidx . media . app . Notification Compat . Media Style () Ċĉĉĉĉĉ ĉ . set Cancel Button Intent ( dismiss Intent ) Ċĉĉĉĉĉ ĉ . set Show Cancel Button ( true ) Ċĉĉĉĉĉ ĉ . set Show Actions In Compact View ( 1 , 2 , 3 ) Ċĉĉĉĉ ĉ setStyle ( style ) ĊĊĉĉĉ ĉ }. build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Dismiss Pending Intent ( item : ĠMedia Item ): ĠPending Intent Ġ{ Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ DIS MIS S _ NOTIFICATION ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ return ĠPending Intent . get Broadcast ( music Service , ĠACTION _ DIS MIS S _ NOTIFICATION _ CODE , Ġintent , Ġflag ) Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Stop Cancel ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ close Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ PLAY " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ STOP _ CANCEL ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ STOP _ CANCEL _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Repeat One To All ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ repeat _ one Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ PLAY " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ REPEAT _ ONE _ TO _ ALL ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ REPEAT _ ONE _ TO _ ALL _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Repeat Off ToOne ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ repeat _ off Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ REPEAT _ OFF _ TO _ ONE " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ REPEAT _ OFF _ TO _ ONE ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ REPEAT _ OFF _ TO _ ONE _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Repeat All To Off ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ repeat _ all Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ REPEAT _ ALL _ TO _ OFF " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ REPEAT _ ALL _ TO _ OFF ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ REPEAT _ ALL _ TO _ OFF _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Play ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ play Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ PLAY " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ PLAY ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ PLAY _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Pause ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ pause Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ PAUSE " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ PAUSE ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ PAUSE _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Next ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ next Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ NEXT " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ NEXT ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ NEXT _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Next Disabled ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ next _ disabled Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ NEXT _ DISABLED " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ NEXT _ DISABLED ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ NEXT _ DISABLED _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Prev ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ prev Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ PREV " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ PREV ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ PREV _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } ĊĊĉ ĉ private Ġfun Ġmake Action Prev Disabled ( item : ĠMedia Item ): ĠNotification Compat . Action Ġ{ Ċĉĉ ĉ val Ġres Id Ġ= ĠR . drawable . ic _ notif _ prev _ disabled Ċĉĉ ĉ val Ġtitle Ġ= Ġ" ACTION _ PREV _ DISABLED " Ċĉĉ ĉ val Ġintent Ġ= ĠIntent ( PLAY BACK _ CONTROL _ INT ENT ) Ċĉĉĉ ĉ . apply Ġ{ Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ CONTROL _ ACTION , ĠACTION _ PREV _ DISABLED ) Ċĉĉĉĉ ĉ putExtra ( PLAY BACK _ ITEM _ ID , Ġitem . media Id ) Ċĉĉĉĉ ĉ set Package ( music Service . packageName ) Ċĉĉĉ ĉ } Ċĉĉ ĉ val Ġflag Ġ= ĠPending Intent . FLAG _ UPDATE _ CURRENT Ġor ĠPending Intent . FLAG _ IM MUT ABLE Ċĉĉ ĉ val Ġp Intent Ġ= ĠPending Intent . get Broadcast ( music Service , ĠACTION _ PREV _ DISABLED _ CODE , Ġintent , Ġflag ) Ċĉĉ ĉ return ĠNotification Compat . Action . Builder ( res Id , Ġtitle , Ġp Intent ). build () Ċĉ ĉ } Ċ ĉ } ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġconst Ġval ĠNOT IFICATION _ CHANNEL _ NAME Ġ= Ġ" Media ĠService ĠChannel " ĊĠĠĠ Ġconst Ġval ĠNOT IFICATION _ NAME Ġ= Ġ" Media ĠService ĠNotification " ĊĠĠĠ Ġconst Ġval ĠNOT IFICATION _ ID Ġ= Ġ 3 0 1 ĊĊĠĠĠ Ġconst Ġval ĠP LAY BACK _ CONTROL _ INT ENT Ġ= Ġ" com . ky len nt . medi ap layer . PLAY BACK _ CONTROL _ INT ENT " ĊĠĠĠ Ġconst Ġval ĠP LAY BACK _ CONTROL _ ACTION Ġ= Ġ" PLAY BACK _ CONTROL _ ACTION " ĊĠĠĠ Ġconst Ġval ĠP LAY BACK _ ITEM _ ID Ġ= Ġ" PLAY BACK _ ITEM _ ID " ĊĠĠĠ Ġconst Ġval ĠACTION _ STOP _ CANCEL Ġ= Ġ" ACTION _ STOP _ CANCEL " ĊĠĠĠ Ġconst Ġval ĠACTION _ NEXT Ġ= Ġ" ACTION _ NEXT " ĊĠĠĠ Ġconst Ġval ĠACTION _ PREV Ġ= Ġ" ACTION _ PREV " ĊĠĠĠ Ġconst Ġval ĠACTION _ NEXT _ DISABLED Ġ= Ġ" ACTION _ NEXT _ DISABLED " ĊĠĠĠ Ġconst Ġval ĠACTION _ PREV _ DISABLED Ġ= Ġ" ACTION _ PREV _ DISABLED " ĊĠĠĠ Ġconst Ġval ĠACTION _ PLAY Ġ= Ġ" ACTION _ PLAY " ĊĠĠĠ Ġconst Ġval ĠACTION _ PAUSE Ġ= Ġ" ACTION _ PAUSE " ĊĊĠĠĠ Ġconst Ġval ĠACTION _ REPEAT _ OFF _ TO _ ONE Ġ= Ġ" ACTION _ REPEAT _ OFF _ TO _ ONE " ĊĠĠĠ Ġconst Ġval ĠACTION _ REPEAT _ ONE _ TO _ ALL Ġ= Ġ" ACTION _ REPEAT _ ONE _ TO _ ALL " ĊĠĠĠ Ġconst Ġval ĠACTION _ REPEAT _ ALL _ TO _ OFF Ġ= Ġ" ACTION _ REPEAT _ ALL _ TO _ OFF " ĊĊĠĠĠ Ġconst Ġval ĠACTION _ DIS MIS S _ NOTIFICATION Ġ= Ġ" ACTION _ DIS MIS S _ NOTIFICATION " ĊĊĠĠĠ Ġconst Ġval ĠACTION _ STOP _ CANCEL _ CODE Ġ= Ġ 4 0 0 ĊĠĠĠ Ġconst Ġval ĠACTION _ PLAY _ CODE Ġ= Ġ 4 0 1 ĊĠĠĠ Ġconst Ġval ĠACTION _ PAUSE _ CODE Ġ= Ġ 4 0 2 ĊĠĠĠ Ġconst Ġval ĠACTION _ NEXT _ CODE Ġ= Ġ 4 0 3 ĊĠĠĠ Ġconst Ġval ĠACTION _ PREV _ CODE Ġ= Ġ 4 0 4 ĊĠĠĠ Ġconst Ġval ĠACTION _ NEXT _ DISABLED _ CODE Ġ= Ġ 4 0 5 ĊĠĠĠ Ġconst Ġval ĠACTION _ PREV _ DISABLED _ CODE Ġ= Ġ 4 0 6 ĊĠĠĠ Ġconst Ġval ĠACTION _ REPEAT _ OFF _ TO _ ONE _ CODE Ġ= Ġ 4 0 7 ĊĠĠĠ Ġconst Ġval ĠACTION _ REPEAT _ ONE _ TO _ ALL _ CODE Ġ= Ġ 4 0 8 ĊĠĠĠ Ġconst Ġval ĠACTION _ REPEAT _ ALL _ TO _ OFF _ CODE Ġ= Ġ 4 0 9 ĊĠĠĠ Ġconst Ġval ĠACTION _ DIS MIS S _ NOTIFICATION _ CODE Ġ= Ġ 4 1 0 ĊĊĠĠĠ Ġconst Ġval ĠNOT IFICATION _ UPDATE _ INTERVAL Ġ= Ġ 1 0 0 0 L ĊĠ Ġ} Ċ } Ċ