MainApplication.kt
We set these initializations here instead of in an Activity in order to accommodate an app with a background service for the scanning.
If you need only a foreground activity, you can simply host them in the
onCreate()
of a main activity.
package my.package
import android.app.Application
import my.package.ble.ScannerManager
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
// delegated to a ble component, to keep the pure app module clean of direct accesses to the library
ScannerManager.init(this)
}
}
MainActivity.kt
How screens and layouts are implemented (XML, Jetpack Compose, ...) is out of scope of the samples.
An
(UI)
marker is used in the code comments to denote this point.
package my.package
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import my.package.ble.Configuration
import my.package.ble.IStatusCallback
import my.package.ble.ScannerManager
import my.package.ble.UserConfig
class MainActivity : ComponentActivity() {
// actions are delegated to a component
private lateinit var mScannerManager: ScannerManager
// configuration settings are delegated to a component
private lateinit var mConfiguration: Configuration
// a status is kept to know if the scanning is active
private var mIsScanning: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
if (BuildConfig.DEBUG) Log.d(TAG, "lifecycle onCreate")
super.onCreate(savedInstanceState)
mScannerManager = ScannerManager(this)
// here, a simple interactive configuration, assuming a user in control
mConfiguration = UserConfig.create()
// ... (UI) setup your screen layout
// typically, for this sample, with start and stop buttons to act on the scanning,
// respectively associated with onClickSetup() and onClickTeardown()
}
override fun onDestroy() {
// should be harmless if already stopped some other way (for example a receiver detecting that the Bluetooth has turned off)
if (mIsScanning) mScannerManager.tearDown()
super.onDestroy()
}
private val mStatusCallback = object : IStatusCallback {
override fun onResult(isScanning: Boolean) {
if (BuildConfig.DEBUG) Log.d(TAG, "onResult: isScanning $isScanning")
mIsScanning = isScanning
// ... (UI) may need to update some elements, like button properties (text, enabled, ...)
}
override fun onError(message: String) {
if (BuildConfig.DEBUG) Log.d(TAG, "onError $message")
// ... (UI) inform of the failure
}
}
private fun onClickSetup() {
if (BuildConfig.DEBUG) Log.d(TAG, "onClickSetUp")
if (mScannerManager.isBluetoothDisabled) {
// ... (UI) inform that the app can't work at all if the Bluetooth is off
} else {
if (mScannerManager.isLocationDisabled) {
// ... (UI) inform that no detection will be accessible until Location is enabled
}
// ... (UI) according to RadioButtons, may call mConfiguration.setRangingScanFrequency() (default setting)
// or mConfiguration.setMonitoringScanFrequency()
// ... (UI) according to a CheckBox, may set mConfiguration.verbose = true
mScannerManager.setUp(mConfiguration, mStatusCallback)
}
}
private fun onClickTeardown() {
if (BuildConfig.DEBUG) Log.d(TAG, "onClickTearDown")
mScannerManager.tearDown(mStatusCallback)
}
private companion object {
private val TAG = MainActivity::class.java.simpleName
}
}
IStatusCallback.kt
package my.package.ble
interface IStatusCallback {
fun onResult(isScanning: Boolean)
fun onError(message: String)
}