/* čĊ Ġ* ĠCopyright Ġ 2 0 2 2 ĠP unch ĠThrough ĠDesign ĠLLC čĊ Ġ* čĊ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); čĊ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . čĊ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat čĊ Ġ* čĊ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 čĊ Ġ* čĊ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware čĊ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , čĊ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . čĊ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand čĊ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . čĊ Ġ*/ čĊč Ċ package Ġcom . p unch through . ble starter app android čĊč Ċ import Ġandroid . Manifest č Ċ import Ġandroid . app . Activity č Ċ import Ġandroid . bluetooth . Bluetooth Adapter č Ċ import Ġandroid . bluetooth . Bluetooth Device č Ċ import Ġandroid . bluetooth . le . Scan Callback č Ċ import Ġandroid . bluetooth . le . Scan Result č Ċ import Ġandroid . bluetooth . le . Scan Settings č Ċ import Ġandroid . content . Context č Ċ import Ġandroid . content . Intent č Ċ import Ġandroid . content . pm . PackageManager č Ċ import Ġandroid . os . Build č Ċ import Ġandroidx . appcompat . app . AppCompatActivity č Ċ import Ġandroidx . core . app . Activity Compat č Ċ import Ġandroidx . core . content . Context Compat č Ċ import Ġcom . p unch through . ble starter app android . ble . Connection EventListener č Ċ import Ġcom . p unch through . ble starter app android . ble . ConnectionManager č Ċ import Ġorg . jetbrains . ank o . alert č Ċ import Ġtim ber . log . Tim ber č Ċ import Ġandroid . bluetooth . le . Scan Filter č Ċ import Ġandroid . util . Log čĊč Ċ private Ġconst Ġval ĠENABLE _ BL U ETO OTH _ REQUEST _ CODE Ġ= Ġ 1 č Ċ private Ġconst Ġval ĠLOC ATION _ PERMISSION _ REQUEST _ CODE Ġ= Ġ 2 čĊč Ċ class ĠScan Foreground : ĠAppCompatActivity () Ġ{ čĊčĊĠĠĠ Ġvar Ġnames Ġ= ĠarrayOf (" 2 0 2 1 1 2 0 5 5 ") čĊčĊĠĠĠ Ġprivate Ġvar ĠmContext : ĠContext ? Ġ= Ġnull čĊčĊĠĠĠ Ġfun Ġset Context ( mContext : ĠContext ?) Ġ{ čĊĠĠĠĠĠĠĠ Ġthis . mContext Ġ= ĠmContext čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/ **************************************** *** čĊĠĠĠĠ Ġ* ĠProperties čĊĠĠĠĠ Ġ********************************* ******** **/ čĊčĊĠĠĠ Ġprivate Ġval Ġbluetooth Adapter Ġ= ĠBluetooth Adapter . getDefault Adapter () čĊčĊĠĠĠ Ġprivate Ġval Ġble Scanner Ġ= Ġbluetooth Adapter . bluetooth Le Scanner čĊčĊĠĠĠ Ġprivate Ġvar Ġis Sc anning Ġ= Ġfalse čĊčĊĠĠĠ Ġprivate Ġval Ġscan Settings Ġ= ĠScan Settings . Builder () čĊĠĠĠĠĠĠĠ Ġ. set Scan Mode ( Scan Settings . SCAN _ MODE _ LOW _ LAT ENCY ) čĊĠĠĠĠĠĠĠ Ġ. build () čĊčĊĠĠĠ Ġprivate Ġval Ġscan Results Ġ= Ġmutable ListOf < Scan Result >() čĊčĊĠĠĠ Ġprivate Ġval Ġis Location Permission Granted čĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġhas Permission ( Manifest . permission . ACCESS _ F INE _ LOCATION ) čĊčĊĠĠĠ Ġ/ **************************************** *** čĊĠĠĠĠ Ġ* ĠActivity Ġfunction Ġoverrides čĊĠĠĠĠ Ġ********************************* ******** **/ čĊčĊĠĠĠ Ġoverride Ġfun Ġon Resume () Ġ{ čĊĠĠĠĠĠĠĠ Ġsuper . on Resume () čĊĠĠĠĠĠĠĠ ĠConnection Manager . register Listener ( connection EventListener ) čĊĠĠĠĠĠĠĠ Ġif Ġ(! bluetooth Adapter . isEnabled ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġprompt Enable Bluetooth () čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġoverride Ġfun Ġon Activity Result ( request Code : ĠInt , ĠresultCode : ĠInt , Ġdata : ĠIntent ?) Ġ{ čĊĠĠĠĠĠĠĠ Ġsuper . on Activity Result ( request Code , ĠresultCode , Ġdata ) čĊĠĠĠĠĠĠĠ Ġwhen Ġ( request Code ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠENABLE _ BL U ETO OTH _ REQUEST _ CODE Ġ-> Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result Code Ġ!= ĠActivity . RESULT _ OK ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprompt Enable Bluetooth () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġoverride Ġfun Ġon Request Permissions Result ( čĊĠĠĠĠĠĠĠ Ġrequest Code : ĠInt , čĊĠĠĠĠĠĠĠ Ġpermissions : ĠArray < out ĠString >, čĊĠĠĠĠĠĠĠ Ġgrant Results : ĠInt Array čĊĠĠĠ Ġ) Ġ{ čĊĠĠĠĠĠĠĠ Ġsuper . on Request Permissions Result ( request Code , Ġpermissions , Ġgrant Results ) čĊĠĠĠĠĠĠĠ Ġwhen Ġ( request Code ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠLOC ATION _ PERMISSION _ REQUEST _ CODE Ġ-> Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( grant Results . first OrNull () Ġ== ĠPackage Manager . PERMISSION _ DEN IED ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequest Location Permission () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/ **************************************** *** čĊĠĠĠĠ Ġ* ĠPrivate Ġfunctions čĊĠĠĠĠ Ġ********************************* ******** **/ čĊčĊĠĠĠ Ġprivate Ġfun Ġprompt Enable Bluetooth () Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ(! bluetooth Adapter . isEnabled ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġenable Bt Intent Ġ= ĠIntent ( Bluetooth Adapter . ACTION _ REQUEST _ ENABLE ) čĊĠĠĠĠĠĠĠĠĠĠĠ ĠstartActivity For Result ( enable Bt Intent , ĠENABLE _ BL U ETO OTH _ REQUEST _ CODE ) čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġfun Ġstart B le Scan () Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ( Context Compat . check Self Permission ( mContext !! , ĠManifest . permission . ACCESS _ F INE _ LOCATION ) Ġ== čĊĠĠĠĠĠĠĠĠĠĠĠ ĠPackage Manager . PERMISSION _ GRAN TED ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . M ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġfilters : ĠMutable List < Scan Filter ?> ? Ġ= Ġnull čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( names Ġ!= Ġnull ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfilters Ġ= ĠArrayList () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( name Ġin Ġnames ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfilter Ġ= ĠScan Filter . Builder () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Device Name ( name ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfilters . add ( filter ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġble Scanner . start Scan ( filters , Ġscan Settings , Ġscan Callback ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Sc anning Ġ= Ġtrue čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequest Location Permission () čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġfun Ġstop B le Scan () Ġ{ čĊĠĠĠĠĠĠĠ Ġble Scanner . stop Scan ( scan Callback ) čĊĠĠĠĠĠĠĠ Ġis Sc anning Ġ= Ġfalse čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġfun Ġconect ar BLE ( device : ĠBluetooth Device , Ġcontext : ĠContext ) Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ( is Sc anning ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġstop B le Scan () čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ ĠConnection Manager . connect ( device , Ġcontext ) čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġfun Ġrequest Location Permission () Ġ{ čĊĠĠĠĠĠĠĠ Ġif Ġ( is Location Permission Granted ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġrun On Ui Thread Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġalert Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtitle Ġ= Ġ" Location Ġpermission Ġrequired " čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Ġ= Ġ" Starting Ġfrom ĠAndroid ĠM Ġ( 6 . 0 ), Ġthe Ġsystem Ġrequires Ġapps Ġto Ġbe Ġgranted Ġ" Ġ+ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" location Ġaccess Ġin Ġorder Ġto Ġscan Ġfor ĠBLE Ġdevices ." čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Cancel able Ġ= Ġfalse čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpositive Button ( android . R . string . ok ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrequest Permission ( čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠManifest . permission . ACCESS _ F INE _ LOCATION , čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLOC ATION _ PERMISSION _ REQUEST _ CODE čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. show () čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/ **************************************** *** čĊĠĠĠĠ Ġ* ĠCallback Ġbodies čĊĠĠĠĠ Ġ********************************* ******** **/ čĊčĊĠĠĠ Ġprivate Ġval Ġscan Callback Ġ= Ġobject Ġ: ĠScan Callback () Ġ{ čĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Scan Result ( callback Type : ĠInt , Ġresult : ĠScan Result ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġindex Query Ġ= Ġscan Results . indexOf First Ġ{ Ġit . device . address Ġ== Ġresult . device . address Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( index Query Ġ!= Ġ- 1 ) Ġ{ Ġ// ĠA Ġscan Ġresult Ġalready Ġexists Ġwith Ġthe Ġsame Ġaddress čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġscan Results [ index Query ] Ġ= Ġresult čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwith ( result . device ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Found ĠBLE Ġdevice ! ĠName : Ġ${ name Ġ?: Ġ" Unnamed "}, Ġaddress : Ġ$ address ") čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( is Sc anning ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstop B le Scan () čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconect ar BLE ( this , ĠmContext !! ) čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊčĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Scan Failed ( errorCode : ĠInt ) Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . e (" on Scan Failed : Ġcode Ġ$ errorCode ") čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġval Ġconnection EventListener Ġby Ġlazy Ġ{ čĊĠĠĠĠĠĠĠ ĠConnection EventListener (). apply Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠ Ġon Disconnect Ġ= Ġ{ čĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrun On Ui Thread Ġ{ ĠLog . d (" F ", Ġ" TE ĠHAS ĠDES CON ECT ADO ")} čĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} čĊĠĠĠĠĠĠĠ Ġ} čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġ/ **************************************** *** čĊĠĠĠĠ Ġ* ĠExtension Ġfunctions čĊĠĠĠĠ Ġ********************************* ******** **/ čĊčĊĠĠĠ Ġprivate Ġfun ĠContext . has Permission ( permission Type : ĠString ): ĠBoolean Ġ{ čĊĠĠĠĠĠĠĠ Ġreturn ĠContext Compat . check Self Permission ( this , Ġpermission Type ) Ġ== čĊĠĠĠĠĠĠĠĠĠĠĠ ĠPackage Manager . PERMISSION _ GRAN TED čĊĠĠĠ Ġ} čĊčĊĠĠĠ Ġprivate Ġfun ĠActivity . request Permission ( permission : ĠString , Ġrequest Code : ĠInt ) Ġ{ čĊĠĠĠĠĠĠĠ ĠActivity Compat . request Permissions ( this , ĠarrayOf ( permission ), Ġrequest Code ) čĊĠĠĠ Ġ} č Ċ }