@ file : Suppress (" Blocking Method In Non Blocking Context ") Ċ Ċ package Ġio . github . solr ude v . simple installer . impl Ċ Ċ import Ġandroid . app . Pending Intent Ċ import Ġandroid . content . Context Ċ import Ġandroid . content . Intent Ċ import Ġandroid . content . pm . PackageManager Ċ import Ġandroid . net . Uri Ċ import Ġandroid . os . Build Ċ import Ġandroid . os . Bundle Ċ import Ġandroidx . activity . result . contract . Activity Result Contracts Ċ import Ġandroidx . annotation . Checks Sdk Int At Least Ċ import Ġandroidx . annotation . Requires Api Ċ import Ġandroidx . appcompat . app . AppCompatActivity Ċ import Ġandroidx . lifecycle . Lifecycle Ċ import Ġandroidx . lifecycle . flow With Lifecycle Ċ import Ġandroidx . lifecycle . lifecycle Scope Ċ import Ġio . github . solr ude v . simple installer . Package Installer Ċ import Ġio . github . solr ude v . simple installer . R Ċ import Ġio . github . solr ude v . simple installer . Simple Installer Ċ import Ġio . github . solr ude v . simple installer . activity result . Action Install Package Contract Ċ import Ġio . github . solr ude v . simple installer . apk source . A pk Source Ċ import Ġio . github . solr ude v . simple installer . data . Install Failure Cause Ċ import Ġio . github . solr ude v . simple installer . data . Install Result Ċ import Ġio . github . solr ude v . simple installer . data . Progress Data Ċ import Ġio . github . solr ude v . simple installer . data . utils . make In determinate Ċ import Ġio . github . solr ude v . simple installer . data . utils . try Emit Ċ import Ġio . github . solr ude v . simple installer . exceptions . ApplicationContext Not Set Exception Ċ import Ġio . github . solr ude v . simple installer . exceptions . Split Packages NotSupportedException Ċ import Ġio . github . solr ude v . simple installer . utils .* Ċ import Ġio . github . solr ude v . simple installer . utils . extensions . clear Turn Screen On Settings Ċ import Ġio . github . solr ude v . simple installer . utils . extensions . turn Screen On When Locked Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . channels . Buffer Overflow Ċ import Ġkotlinx . coroutines . flow . Mutable Shared Flow Ċ import Ġkotlinx . coroutines . flow . as Shared Flow Ċ import Ġkotlinx . coroutines . flow . emit All Ċ import Ġkotlin . coroutines . resume Ċ import Ġandroid . content . pm . Package Installer Ġas ĠAndroid Package Installer Ċ Ċ private Ġconst Ġval ĠA PK _ URI _ KEY Ġ= Ġ" PACKAGE _ INSTALL ER _ AP K _ URI " Ċ private Ġconst Ġval ĠREQUEST _ CODE Ġ= Ġ 6 5 4 1 Ċ Ċ /** Ċ Ġ* ĠA Ġconcrete Ġimplementation Ġof Ġ[ Package Installer ]. Ċ Ġ*/ Ċ internal Ġobject ĠPackage Installer Impl Ġ: ĠPackage Installer Ġ{ ĊĊ ĉ override Ġvar Ġhas Active Session Ġ= Ġfalse Ċĉ ĉ private Ġset ĊĊ ĉ private Ġval Ġ_ progress Ġ= ĠMutable Shared Flow < Progress Data >( Ċĉ ĉ extra Buffer Capacity Ġ= Ġ 1 , Ċĉ ĉ on Buffer Overflow Ġ= ĠBuffer Overflow . DROP _ OL DEST Ċ ĉ ) ĊĊ ĉ override Ġval Ġprogress Ġ= Ġ_ progress . as Shared Flow () ĊĊ ĉ override Ġsuspend Ġfun Ġinstall Split Package ( var arg Ġapk Files : ĠA pk Source ): ĠInstall Result Ġ{ Ċĉ ĉ if Ġ(! use Package Installer Api ) Ġ{ Ċĉĉ ĉ throw ĠSplit Packages NotSupportedException () Ċĉ ĉ } Ċĉ ĉ return Ġinstall Packages ( apk Files ) Ċ ĉ } ĊĊ ĉ override Ġsuspend Ġfun Ġinstall Package ( apk File : ĠA pk Source ) Ġ= Ġinstall Packages ( array Of ( apk File )) ĊĊ ĉ override Ġfun Ġinstall Split Package ( var arg Ġapk Files : ĠA pk Source , Ġcallback : ĠPackage Installer . Callback ) Ġ{ Ċĉ ĉ if Ġ(! use Package Installer Api ) Ġ{ Ċĉĉ ĉ throw ĠSplit Packages NotSupportedException () Ċĉ ĉ } Ċĉ ĉ install Packages ( apk Files , Ġcallback ) Ċ ĉ } ĊĊ ĉ override Ġfun Ġinstall Package ( apk File : ĠA pk Source , Ġcallback : ĠPackage Installer . Callback ) Ġ= Ċĉ ĉ install Packages ( array Of ( apk File ), Ġcallback ) ĊĊ ĉ override Ġfun Ġcancel () Ġ{ Ċĉ ĉ if Ġ(:: installer Continuation . isInitialized Ġ&& Ġinstaller Continuation . isActive ) Ġ{ Ċĉĉ ĉ installer Continuation . cancel () Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġval Ġaction Installation Status Ġby Ġlazy Ġ{ Ġ"${ Simple Installer . packageName }. INSTALL ATION _ STATUS " Ġ} Ċ ĉ private Ġval Ġaction Install Package Contract Ġ= ĠAction Install Package Contract () Ċ ĉ private Ġval Ġinstaller Scope Ġ= ĠCor outine Scope ( Dispatch ers . Default ) Ċ ĉ private Ġvar Ġnotification Id Ġ= Ġ 1 8 4 7 5 Ċ ĉ private Ġvar Ġcurrent A pk Sources : ĠArray < out ĠA pk Source > Ġ= Ġempty Array () Ċ ĉ private Ġvar Ġactivity First Created Ġ= Ġtrue Ċ ĉ private Ġlateinit Ġvar Ġinstaller Continuation : ĠC ancellable Continuation < Install Result > ĊĊ ĉ private Ġval Ġinstall Finished Callback Ġ= ĠMutable Shared Flow < Unit >( Ċĉ ĉ extra Buffer Capacity Ġ= Ġ 1 , Ċĉ ĉ on Buffer Overflow Ġ= ĠBuffer Overflow . DROP _ OL DEST Ċ ĉ ) ĊĊ ĉ private Ġval Ġpackage Installer Ċĉ ĉ @ Requires Api ( Build . VERSION _ CODES . LO L LI POP ) Ċĉ ĉ get () Ġ= ĠSimple Installer . application Context . package Manager . package Installer ĊĊ ĉ private Ġval Ġuse Package Installer Api Ċĉ ĉ @ Checks Sdk Int At Least ( api Ġ= ĠBuild . VERSION _ CODES . LO L LI POP ) Ċĉ ĉ get () Ġ= ĠBuild . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . LO L LI POP ĊĊ ĉ private Ġval Ġpackage Installer Session Observer Ġby Ġlazy Ġ{ Ċĉ ĉ @ Requires Api ( Build . VERSION _ CODES . LO L LI POP ) Ġobject Ġ: ĠAndroid Package Installer . Session Callback () Ġ{ Ċĉĉ ĉ override Ġfun Ġon Created ( sessionId : ĠInt ) Ġ{} Ċĉĉ ĉ override Ġfun Ġon Bad ging Changed ( sessionId : ĠInt ) Ġ{} Ċĉĉ ĉ override Ġfun Ġon Active Changed ( sessionId : ĠInt , Ġactive : ĠBoolean ) Ġ{} Ċĉĉ ĉ override Ġfun Ġon Finished ( sessionId : ĠInt , Ġsuccess : ĠBoolean ) Ġ{} ĊĊĉĉ ĉ override Ġfun Ġon Progress Changed ( sessionId : ĠInt , Ġprogress : ĠFloat ) Ġ{ Ċĉĉĉ ĉ _ progress . try Emit (( progress Ġ* Ġ 1 0 0 ). toInt (), Ġ 1 0 0 ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ @ Requires Api ( Build . VERSION _ CODES . LO L LI POP ) Ċ ĉ @ Jvm Synt hetic Ċ ĉ internal Ġfun Ġon Package Installer Status Changed ( context : ĠContext , Ġintent : ĠIntent ) Ġ{ Ċĉ ĉ if Ġ( intent . action Ġ!= Ġaction Installation Status ) Ġ{ Ċĉĉ ĉ return Ċĉ ĉ } Ċĉ ĉ val ĠsessionId Ġ= Ġintent . getInt Extra ( Android Package Installer . EXTRA _ SESSION _ ID , Ġ- 1 ) Ċĉ ĉ val Ġstatus Ġ= Ġintent . getInt Extra ( Android Package Installer . EXTRA _ STATUS , Ġ- 1 ) Ċĉ ĉ if Ġ( status Ġ== ĠAndroid Package Installer . STATUS _ PENDING _ USER _ ACTION ) Ġ{ Ċĉĉ ĉ val Ġconfirmation Intent Ġ= Ġintent . get Parcelable Extra < Intent >( Intent . EXTRA _ INT ENT ) Ċĉĉ ĉ if Ġ( confirmation Intent Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ val Ġwrapper Intent Ġ= ĠIntent ( context , ĠInstall Launcher Activity :: class . java ) Ċĉĉĉĉ ĉ . putExtra ( Intent . EXTRA _ INT ENT , Ġconfirmation Intent ) Ċĉĉĉĉ ĉ . putExtra ( Android Package Installer . EXTRA _ SESSION _ ID , ĠsessionId ) Ċĉĉĉĉ ĉ . add Flags ( Intent . FLAG _ ACTIVITY _ NEW _ TASK ) Ċĉĉĉ ĉ context . startActivity ( wrapper Intent ) Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ installer Continuation . cancel ( IllegalArgumentException (" confirmation Intent Ġwas Ġnull .")) Ċĉĉ ĉ } Ċĉĉ ĉ return Ċĉ ĉ } Ċĉ ĉ val Ġmessage Ġ= Ġintent . getString Extra ( Android Package Installer . EXTRA _ STATUS _ MESSAGE ) Ċĉ ĉ val Ġother PackageName Ġ= Ġintent . getString Extra ( Android Package Installer . EXTRA _ OTHER _ PACKAGE _ NAME ) Ċĉ ĉ val Ġstorage Path Ġ= Ġintent . getString Extra ( Android Package Installer . EXTRA _ STORAGE _ PATH ) Ċĉ ĉ finish Installation ( Install Result . from StatusCode ( status , Ġmessage , Ġother PackageName , Ġstorage Path )) Ċ ĉ } ĊĊ ĉ private Ġfun Ġinstall Packages ( apk Files : ĠArray < out ĠA pk Source >, Ġcallback : ĠPackage Installer . Callback ) Ġ{ Ċĉ ĉ installer Scope . launch Ġ{ Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ launch ( Dispatch ers . Main ) Ġ{ Ċĉĉĉĉ ĉ progress . collect Ġ{ Ġcallback . on Progress Changed ( it ) Ġ} Ċĉĉĉ ĉ } Ċĉĉĉ ĉ when Ġ( val Ġresult Ġ= Ġinstall Packages ( apk Files )) Ġ{ Ċĉĉĉĉ ĉ is ĠInstall Result . Success Ġ-> Ġwith Context ( Dispatch ers . Main ) Ġ{ Ġcallback . on Success () Ġ} Ċĉĉĉĉ ĉ is ĠInstall Result . Failure Ġ-> Ġwith Context ( Dispatch ers . Main ) Ġ{ Ġcallback . on Failure ( result . cause ) Ġ} Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ġcatch Ġ( t : ĠThrowable ) Ġ{ Ċĉĉĉ ĉ if Ġ( t Ġis ĠC ancellation Exception ) Ġ{ Ċĉĉĉĉ ĉ with Context ( Dispatch ers . Main Ġ+ ĠNon C ancellable ) Ġ{ Ġcallback . on Canceled () Ġ} Ċĉĉĉĉ ĉ return @ launch Ċĉĉĉ ĉ } Ċĉĉĉ ĉ with Context ( Dispatch ers . Main Ġ+ ĠNon C ancellable ) Ġ{ Ġcallback . on Exception ( t ) Ġ} Ċĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉ ĉ coroutine Context [ Job ]?. cancel () Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġsuspend Ġfun Ġinstall Packages ( apk Files : ĠArray < out ĠA pk Source >): ĠInstall Result Ġ{ Ċĉ ĉ if Ġ( apk Files . isEmpty ()) Ġ{ Ċĉĉ ĉ return ĠInstall Result . Failure ( Install Failure Cause . Generic (" No ĠA PK s Ġprovided .")) Ċĉ ĉ } Ċĉ ĉ return Ġsuspend C ancellable Coroutine Ġ{ Ġcontinuation Ġ-> Ċĉĉ ĉ var ĠsessionId Ġ= Ġ- 1 Ċĉĉ ĉ continu ation . invoke On Cancellation Ġ{ Ċĉĉĉ ĉ if Ġ( use Package Installer Api ) Ġ{ Ċĉĉĉĉ ĉ ab and on Session ( sessionId ) Ċĉĉĉ ĉ } Ċĉĉĉ ĉ on Cancellation () Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( has Active Session ) Ġ{ Ċĉĉĉ ĉ continu ation . cancel ( IllegalStateException (" Can 't Ġinstall Ġwhile Ġanother Ġinstall Ġsession Ġis Ġactive .")) Ċĉĉ ĉ } Ċĉĉ ĉ has Active Session Ġ= Ġtrue Ċĉĉ ĉ installer Continuation Ġ= Ġcontinuation Ċĉĉ ĉ Coroutine Scope ( continu ation . context Ġ+ ĠDispatch ers . IO ). launch Ġmain @{ Ċĉĉĉ ĉ try Ġ{ Ċĉĉĉĉ ĉ current A pk Sources Ġ= Ġapk Files Ċĉĉĉĉ ĉ if Ġ(! use Package Installer Api ) Ġ{ Ċĉĉĉĉĉ ĉ if Ġ( apk Files . size Ġ> Ġ 1 ) Ġ{ Ċĉĉĉĉĉĉ ĉ throw ĠSplit Packages NotSupportedException () Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ val Ġapk File Ġ= Ġapk Files . first () Ċĉĉĉĉĉ ĉ val Ġprogress Job Ġ= Ġlaunch Ġ{ Ċĉĉĉĉĉĉ ĉ _ progress . emit All ( apk File . progress ) Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ val Ġapk Uri Ġ= Ġapk File . get Uri () Ċĉĉĉĉĉ ĉ progress Job . cancel () Ċĉĉĉĉĉ ĉ _ progress . make In determinate () Ċĉĉĉĉĉ ĉ display Notification ( apk Uri Ġ= Ġapk Uri ) Ċĉĉĉĉĉ ĉ return @ main Ċĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ val Ġsession Params Ġ= Ċĉĉĉĉĉ ĉ Android Package Installer . Session Params ( Android Package Installer . Session Params . MODE _ FULL _ INSTALL ) Ċĉĉĉĉ ĉ if Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . O ) Ġ{ Ċĉĉĉĉĉ ĉ session Params . set Install Reason ( PackageManager . INSTALL _ REASON _ USER ) Ċĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ sessionId Ġ= Ġpackage Installer . create Session ( session Params ) Ċĉĉĉĉ ĉ package Installer . open Session ( sessionId ). use Ġ{ Ġsession Ġ-> Ċĉĉĉĉĉ ĉ with Context ( Dispatch ers . Main ) Ġ{ Ċĉĉĉĉĉĉ ĉ package Installer . register Session Callback ( package Installer Session Observer ) Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ session . copy A pk s From ( apk Files ) Ċĉĉĉĉĉ ĉ display Notification ( sessionId Ġ= ĠsessionId ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ġcatch Ġ( t : ĠThrowable ) Ġ{ Ċĉĉĉĉ ĉ continu ation . cancel ( t ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ @ Requires Api ( Build . VERSION _ CODES . LO L LI POP ) Ċ ĉ private Ġsuspend Ġinline Ġfun ĠAndroid Package Installer . Session . copy A pk s From ( apk Files : ĠArray < out ĠA pk Source >) Ġ{ Ċĉ ĉ val Ġtotal Length Ġ= Ġapk Files . sum Of Ġ{ Ġit . length Ġ} Ċĉ ĉ var Ġtransferred Bytes Ġ= Ġ 0 L Ċĉ ĉ for Ġ(( index , Ġapk File ) Ġin Ġapk Files . with Index ()) Ġ{ Ċĉĉ ĉ val Ġapk Stream Ġ= Ġapk File . open InputStream () Ċĉĉ ĉ val Ġapk Length Ġ= Ġapk File . length Ċĉĉ ĉ val Ġsession Stream Ġ= Ġopen Write (" temp $ index . apk ", Ġ 0 , Ġapk Length ) Ċĉĉ ĉ copy ( Ċĉĉĉ ĉ require NotNull ( apk Stream ) Ġ{ Ġ" AP K Ġ$ index ĠInputStream Ġwas Ġnull ." Ġ}, Ċĉĉĉ ĉ session Stream , Ċĉĉĉ ĉ total Length , Ċĉĉĉ ĉ transfer red Bytes Ċĉĉ ĉ ) Ġ{ Ġprogress Data Ġ-> Ċĉĉĉ ĉ set Staging Progress ( progress Data . progress . toFloat () Ġ/ Ġprogress Data . max . coerce At Least ( 1 )) Ċĉĉ ĉ } Ċĉĉ ĉ transfer red Bytes Ġ+= Ġapk Length Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ @ Requires Api ( Build . VERSION _ CODES . LO L LI POP ) Ċ ĉ private Ġfun Ġaband on Session ( sessionId : ĠInt ) Ġ= Ġtry Ġ{ Ċĉ ĉ package Installer . ab and on Session ( sessionId ) Ċ ĉ } Ġcatch Ġ(_ : ĠThrowable ) Ġ{ Ċ ĉ } ĊĊ ĉ private Ġfun Ġon Cancellation () Ġ= Ġtry Ġ{ Ċĉ ĉ if Ġ( use Package Installer Api ) Ġ{ Ċĉĉ ĉ package Installer . unregister Session Callback ( package Installer Session Observer ) Ċĉ ĉ } Ċĉ ĉ current A pk Sources . forEach Ġ{ Ġit . clear Temp Files () Ġ} Ċĉ ĉ notification Manager . cancel ( notification Id ) Ċ ĉ } Ġcatch Ġ(_ : ĠApplication Context Not Set Exception ) Ġ{ Ċ ĉ } Ġfinally Ġ{ Ċĉ ĉ Coroutine Scope ( installer Continuation . context Ġ+ ĠNon C ancellable ). launch Ġ{ Ċĉĉ ĉ install Finished Callback . emit ( Unit ) Ċĉ ĉ } Ċĉ ĉ current A pk Sources Ġ= Ġempty Array () Ċĉ ĉ activity First Created Ġ= Ġtrue Ċĉ ĉ has Active Session Ġ= Ġfalse Ċ ĉ } ĊĊ ĉ private Ġfun Ġfinish Installation ( result : ĠInstall Result ) Ġ{ Ċĉ ĉ on Cancellation () Ċĉ ĉ if Ġ( installer Continuation . isActive ) Ġ{ Ċĉĉ ĉ installer Continuation . resume ( result ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ private Ġfun Ġdisplay Notification ( sessionId : ĠInt ? Ġ= Ġnull , Ġapk Uri : ĠUri ? Ġ= Ġnull ) Ġ{ Ċĉ ĉ val Ġactivity Intent Ġ= ĠIntent ( Ċĉĉ ĉ Simple Installer . application Context , Ċĉĉ ĉ Install Launcher Activity :: class . java Ċĉ ĉ ). apply Ġ{ Ċĉĉ ĉ if Ġ( use Package Installer Api Ġ&& ĠsessionId Ġ!= Ġnull ) Ġ{ Ċĉĉĉ ĉ putExtra ( Android Package Installer . EXTRA _ SESSION _ ID , ĠsessionId ) Ċĉĉ ĉ } Ċĉĉ ĉ apk Uri ?. let Ġ{ Ġput Extra ( AP K _ URI _ KEY , Ġit ) Ġ} Ċĉ ĉ } Ċĉ ĉ val Ġfull Screen Intent Ġ= ĠPending Intent . getActivity ( Ċĉĉ ĉ Simple Installer . application Context , Ċĉĉ ĉ REQUEST _ CODE , Ċĉĉ ĉ activity Intent , Ċĉĉ ĉ pending Intent Cancel Current Flags Ċĉ ĉ ) Ċĉ ĉ show Notification ( Ċĉĉ ĉ full Screen Intent , Ċĉĉ ĉ ++ notification Id , Ċĉĉ ĉ R . string . ssi _ prompt _ install _ title , Ċĉĉ ĉ R . string . ssi _ prompt _ install _ message Ċĉ ĉ ) Ċ ĉ } ĊĊ ĉ internal Ġclass ĠInstall Launcher Activity Ġ: ĠAppCompatActivity () Ġ{ ĊĊĉ ĉ private Ġval Ġaction Install Package Launcher Ġ= Ġregister For Activity Result ( action Install Package Contract ) Ġ{ Ċĉĉ ĉ val Ġresult Ġ= Ġif Ġ( it ) ĠInstall Result . Success Ġelse ĠInstall Result . Failure () Ċĉĉ ĉ finish Installation ( result ) Ċĉ ĉ } ĊĊĉ ĉ @ Requires Api ( Build . VERSION _ CODES . LO L LI POP ) Ċĉ ĉ private Ġval Ġconfirmation Intent Launcher Ġ= Ċĉĉ ĉ register For Activity Result ( Activity Result Contracts . Start Activity For Result ()) Ġ{ Ċĉĉĉ ĉ intent . extras ?. getInt ( Android Package Installer . EXTRA _ SESSION _ ID )?. let Ġmain @{ ĠsessionId Ġ-> Ċĉĉĉĉ ĉ package Installer . getSession Info ( sessionId )?. let Ġ{ Ġsession Info Ġ-> Ċĉĉĉĉĉ ĉ // ĠHack y Ġworkaround : Ġprogress Ġnot Ġgoing Ġhigher Ġthan Ġ 0 . 8 Ġmeans Ġinstall Ġfailed . Ċĉĉĉĉĉ ĉ // ĠThis Ġis Ġneeded Ġto Ġresume Ġthe Ġcoroutine Ġwith Ġfailure Ġon Ġreasons Ġwhich Ġare Ġnot Ċĉĉĉĉĉ ĉ // Ġhandled Ġin Ġon Package Installer Status Changed . ĠFor Ġexample , Ġ" There Ġwas Ġa Ġproblem Ċĉĉĉĉĉ ĉ // Ġparsing Ġthe Ġpackage " Ġerror Ġfalls Ġunder Ġthat . Ċĉĉĉĉĉ ĉ if Ġ( session Info . progress Ġ< Ġ 0 . 8 1 ) Ġ{ Ċĉĉĉĉĉĉ ĉ ab and on Session ( sessionId ) Ċĉĉĉĉĉĉ ĉ finish Installation ( Install Result . Failure ()) Ċĉĉĉĉĉĉ ĉ return @ main Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ // ĠIf Ġsession Ġdoesn 't Ġexist Ġanymore . Ċĉĉĉĉ ĉ finish () Ċĉĉĉ ĉ } Ċĉĉ ĉ } ĊĊĉ ĉ override Ġfun ĠonCreate ( savedInstanceState : ĠBundle ?) Ġ{ Ċĉĉ ĉ super . onCreate ( savedInstanceState ) Ċĉĉ ĉ turn Screen On When Locked () Ċĉĉ ĉ lifecycle Scope . launch Ġ{ Ċĉĉĉ ĉ install Finished Callback Ċĉĉĉĉ ĉ . flow With Lifecycle ( lifecycle , ĠLifecycle . State . RE SU MED ) Ċĉĉĉĉ ĉ . collect Ġ{ Ġfinish () Ġ} Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( savedInstanceState Ġ!= Ġnull ) Ġreturn Ċĉĉ ĉ if Ġ( activity First Created ) Ġ{ Ċĉĉĉ ĉ activity First Created Ġ= Ġfalse Ċĉĉĉ ĉ if Ġ( use Package Installer Api ) Ġ{ Ċĉĉĉĉ ĉ commit Session () Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( use Package Installer Api ) Ġ{ Ċĉĉĉ ĉ intent . extras ?. get Parcelable < Intent >( Intent . EXTRA _ INT ENT )?. let Ġ{ Ċĉĉĉĉ ĉ confirmation Intent Launcher . launch ( it ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ intent . extras ?. get Parcelable < Uri >( AP K _ URI _ KEY )?. let Ġ{ Ċĉĉĉĉ ĉ action Install Package Launcher . launch ( it ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ @ Requires Api ( Build . VERSION _ CODES . LO L LI POP ) Ċĉ ĉ private Ġfun Ġcommit Session () Ġ{ Ċĉĉ ĉ val Ġreceiver Intent Ġ= ĠIntent ( Ċĉĉĉ ĉ Simple Installer . application Context , Ċĉĉĉ ĉ Installation Events Receiver :: class . java Ċĉĉ ĉ ). apply Ġ{ Ċĉĉĉ ĉ action Ġ= Ġaction Installation Status Ċĉĉ ĉ } Ċĉĉ ĉ val Ġreceiver Pending Intent Ġ= ĠPending Intent . get Broadcast ( Ċĉĉĉ ĉ Simple Installer . application Context , Ċĉĉĉ ĉ REQUEST _ CODE , Ċĉĉĉ ĉ receiver Intent , Ċĉĉĉ ĉ pending Intent Update Current Flags Ċĉĉ ĉ ) Ċĉĉ ĉ val Ġstatus Receiver Ġ= Ġreceiver Pending Intent . intent Sender Ċĉĉ ĉ val ĠsessionId Ġ= Ġintent . extras ?. getInt ( Android Package Installer . EXTRA _ SESSION _ ID ) Ċĉĉ ĉ package Installer . open Session ( sessionId !! ). commit ( status Receiver ) Ċĉ ĉ } ĊĊĉ ĉ override Ġfun Ġon New Intent ( intent : ĠIntent ?) Ġ{ Ċĉĉ ĉ super . on New Intent ( intent ) Ċĉĉ ĉ startActivity ( intent ) Ċĉĉ ĉ finish () Ċĉ ĉ } ĊĊĉ ĉ override Ġfun Ġon Destroy () Ġ{ Ċĉĉ ĉ super . on Destroy () Ċĉĉ ĉ clear Turn Screen On Settings () Ċĉ ĉ } Ċ ĉ } Ċ }