Refactoring & CR fixes

This commit is contained in:
Sylwester Zieliński
2021-10-05 10:15:14 +02:00
parent 0384b717b6
commit 90fa2db2ad
124 changed files with 986 additions and 1429 deletions

View File

@@ -6,6 +6,7 @@ import android.bluetooth.BluetoothGattCharacteristic
import android.content.Context
import android.util.Log
import androidx.annotation.IntRange
import no.nordicsemi.android.ble.BleManager
import no.nordicsemi.android.ble.callback.DataReceivedCallback
import no.nordicsemi.android.ble.common.callback.battery.BatteryLevelDataCallback
import no.nordicsemi.android.ble.data.Data
@@ -18,17 +19,10 @@ import java.util.*
* @param <T> The profile callbacks type.
* @see BleManager
</T> */
abstract class BatteryManager<T : BatteryManagerCallbacks?>(context: Context) : LoggableBleManager<T>(context) {
abstract class BatteryManager(context: Context) : BleManager(context) {
private var batteryLevelCharacteristic: BluetoothGattCharacteristic? = null
/**
* Returns the last received Battery Level value.
* The value is set to null when the device disconnects.
* @return Battery Level value, in percent.
*/
/** Last received Battery Level value. */
var batteryLevel: Int? = null
private set
private val batteryLevelDataCallback: DataReceivedCallback =
object : BatteryLevelDataCallback() {
override fun onBatteryLevelChanged(
@@ -36,8 +30,7 @@ abstract class BatteryManager<T : BatteryManagerCallbacks?>(context: Context) :
@IntRange(from = 0, to = 100) batteryLevel: Int
) {
log(LogContract.Log.Level.APPLICATION, "Battery Level received: $batteryLevel%")
this@BatteryManager.batteryLevel = batteryLevel
mCallbacks?.onBatteryLevelChanged(device, batteryLevel)
onBatteryLevelChanged(batteryLevel)
}
override fun onInvalidDataReceived(device: BluetoothDevice, data: Data) {
@@ -45,15 +38,14 @@ abstract class BatteryManager<T : BatteryManagerCallbacks?>(context: Context) :
}
}
protected abstract fun onBatteryLevelChanged(batteryLevel: Int)
fun readBatteryLevelCharacteristic() {
if (isConnected) {
readCharacteristic(batteryLevelCharacteristic)
.with(batteryLevelDataCallback)
.fail { device: BluetoothDevice?, status: Int ->
log(
Log.WARN,
"Battery Level characteristic not found"
)
log(Log.WARN, "Battery Level characteristic not found")
}
.enqueue()
}
@@ -66,32 +58,10 @@ abstract class BatteryManager<T : BatteryManagerCallbacks?>(context: Context) :
.with(batteryLevelDataCallback)
enableNotifications(batteryLevelCharacteristic)
.done { device: BluetoothDevice? ->
log(
Log.INFO,
"Battery Level notifications enabled"
)
log(Log.INFO, "Battery Level notifications enabled")
}
.fail { device: BluetoothDevice?, status: Int ->
log(
Log.WARN,
"Battery Level characteristic not found"
)
}
.enqueue()
}
}
/**
* Disables Battery Level notifications on the Server.
*/
fun disableBatteryLevelCharacteristicNotifications() {
if (isConnected) {
disableNotifications(batteryLevelCharacteristic)
.done { device: BluetoothDevice? ->
log(
Log.INFO,
"Battery Level notifications disabled"
)
log(Log.WARN, "Battery Level characteristic not found")
}
.enqueue()
}
@@ -106,16 +76,14 @@ abstract class BatteryManager<T : BatteryManagerCallbacks?>(context: Context) :
override fun isOptionalServiceSupported(gatt: BluetoothGatt): Boolean {
val service = gatt.getService(BATTERY_SERVICE_UUID)
if (service != null) {
batteryLevelCharacteristic = service.getCharacteristic(
BATTERY_LEVEL_CHARACTERISTIC_UUID
)
batteryLevelCharacteristic = service.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID)
}
return batteryLevelCharacteristic != null
}
override fun onDeviceDisconnected() {
batteryLevelCharacteristic = null
batteryLevel = null
onBatteryLevelChanged(0)
}
}

View File

@@ -1,6 +0,0 @@
package no.nordicsemi.android.service
import no.nordicsemi.android.ble.BleManagerCallbacks
import no.nordicsemi.android.ble.common.profile.battery.BatteryLevelCallback
interface BatteryManagerCallbacks : BleManagerCallbacks, BatteryLevelCallback

View File

@@ -21,33 +21,21 @@
*/
package no.nordicsemi.android.service
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Binder
import android.os.Handler
import android.os.IBinder
import android.util.Log
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.lifecycle.LifecycleService
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import dagger.hilt.android.AndroidEntryPoint
import no.nordicsemi.android.ble.BleManagerCallbacks
import no.nordicsemi.android.ble.utils.ILogger
import no.nordicsemi.android.ble.BleManager
import no.nordicsemi.android.log.ILogSession
import no.nordicsemi.android.log.Logger
import javax.inject.Inject
@AndroidEntryPoint
abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
abstract class BleProfileService : LifecycleService() {
private var bleManager: LoggableBleManager<out BleManagerCallbacks>? = null
protected abstract val manager: BleManager
@Inject
lateinit var bluetoothDeviceHolder: SelectedBluetoothDeviceHolder
@@ -56,9 +44,8 @@ abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
* Returns a handler that is created in onCreate().
* The handler may be used to postpone execution of some operations or to run them in UI thread.
*/
protected var handler: Handler? = null
private set
protected var bound = false
private var handler: Handler? = null
private var activityIsChangingConfiguration = false
/**
@@ -66,256 +53,45 @@ abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
*
* @return bluetooth device
*/
protected val bluetoothDevice: BluetoothDevice by lazy {
private val bluetoothDevice: BluetoothDevice by lazy {
bluetoothDeviceHolder.device ?: throw IllegalArgumentException(
"No device address at EXTRA_DEVICE_ADDRESS key"
"No device associated with the application."
)
}
/**
* Returns the device name
*
* @return the device name
*/
protected var deviceName: String? = null
private set
/**
* Returns the log session that can be used to append log entries. The method returns `null` if the nRF Logger app was not installed. It is safe to use logger when
* [.onServiceStarted] has been called.
*
* @return the log session
*/
protected var logSession: ILogSession? = null
private var logSession: ILogSession? = null
private set
private val bluetoothStateBroadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
val logger: ILogger = binder
val stateString =
"[Broadcast] Action received: " + BluetoothAdapter.ACTION_STATE_CHANGED + ", state changed to " + state2String(
state
)
logger.log(Log.DEBUG, stateString)
when (state) {
BluetoothAdapter.STATE_ON -> onBluetoothEnabled()
BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF -> onBluetoothDisabled()
}
}
private fun state2String(state: Int): String {
return when (state) {
BluetoothAdapter.STATE_TURNING_ON -> "TURNING ON"
BluetoothAdapter.STATE_ON -> "ON"
BluetoothAdapter.STATE_TURNING_OFF -> "TURNING OFF"
BluetoothAdapter.STATE_OFF -> "OFF"
else -> "UNKNOWN ($state)"
}
}
}
inner class LocalBinder : Binder(), ILogger {
/**
* Disconnects from the sensor.
*/
fun disconnect() {
val state = bleManager!!.connectionState
if (state == BluetoothGatt.STATE_DISCONNECTED || state == BluetoothGatt.STATE_DISCONNECTING) {
bleManager!!.close()
onDeviceDisconnected(bluetoothDevice!!)
return
}
bleManager!!.disconnect().enqueue()
}
/**
* Sets whether the bound activity if changing configuration or not.
* If `false`, we will turn off battery level notifications in onUnbind(..) method below.
*
* @param changing true if the bound activity is finishing
*/
fun setActivityIsChangingConfiguration(changing: Boolean) {
activityIsChangingConfiguration = changing
}
/**
* Returns the device address
*
* @return device address
*/
val deviceAddress: String
get() = bluetoothDevice!!.address
/**
* Returns the device name
*
* @return the device name
*/
fun getDeviceName(): String? {
return deviceName
}
/**
* Returns the Bluetooth device
*
* @return the Bluetooth device
*/
fun getBluetoothDevice(): BluetoothDevice? {
return bluetoothDevice
}
/**
* Returns `true` if the device is connected to the sensor.
*
* @return `true` if device is connected to the sensor, `false` otherwise
*/
val isConnected: Boolean
get() = bleManager!!.isConnected
/**
* Returns the connection state of given device.
*
* @return the connection state, as in [BleManager.getConnectionState].
*/
val connectionState: Int
get() = bleManager!!.connectionState
/**
* Returns the log session that can be used to append log entries.
* The log session is created when the service is being created.
* The method returns `null` if the nRF Logger app was not installed.
*
* @return the log session
*/
fun getLogSession(): ILogSession? {
return logSession
}
override fun log(level: Int, message: String) {
Logger.log(logSession, level, message)
}
override fun log(level: Int, @StringRes messageRes: Int, vararg params: Any) {
Logger.log(logSession, level, messageRes, *params)
}
}// default implementation returns the basic binder. You can overwrite the LocalBinder with your own, wider implementation
/**
* Returns the binder implementation. This must return class implementing the additional manager interface that may be used in the bound activity.
*
* @return the service binder
*/
protected val binder: LocalBinder
protected get() =// default implementation returns the basic binder. You can overwrite the LocalBinder with your own, wider implementation
LocalBinder()
override fun onBind(intent: Intent): IBinder? {
super.onBind(intent)
bound = true
return binder
}
override fun onRebind(intent: Intent) {
bound = true
if (!activityIsChangingConfiguration) onRebind()
}
/**
* Called when the activity has rebound to the service after being recreated.
* This method is not called when the activity was killed to be recreated when the phone orientation changed
* if prior to being killed called [LocalBinder.setActivityIsChangingConfiguration] with parameter true.
*/
protected open fun onRebind() {
// empty default implementation
}
override fun onUnbind(intent: Intent): Boolean {
bound = false
if (!activityIsChangingConfiguration) onUnbind()
// We want the onRebind method be called if anything else binds to it again
return true
}
/**
* Called when the activity has unbound from the service before being finished.
* This method is not called when the activity is killed to be recreated when the phone orientation changed.
*/
protected open fun onUnbind() {
// empty default implementation
}
override fun onCreate() {
super.onCreate()
handler = Handler()
// Initialize the manager
bleManager = initializeManager()
// Register broadcast receivers
registerReceiver(
bluetoothStateBroadcastReceiver,
IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
)
// Service has now been created
onServiceCreated()
// Call onBluetoothEnabled if Bluetooth enabled
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
if (bluetoothAdapter.isEnabled) {
onBluetoothEnabled()
}
}
/**
* Called when the service has been created, before the [.onBluetoothEnabled] is called.
*/
protected fun onServiceCreated() {
// empty default implementation
}
/**
* Initializes the Ble Manager responsible for connecting to a single device.
*
* @return a new BleManager object
*/
protected abstract fun initializeManager(): LoggableBleManager<out BleManagerCallbacks>
/**
* This method returns whether autoConnect option should be used.
*
* @return true to use autoConnect feature, false (default) otherwise.
*/
protected fun shouldAutoConnect(): Boolean {
private fun shouldAutoConnect(): Boolean {
return false
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
val logUri = intent?.getParcelableExtra<Uri>(EXTRA_LOG_URI)
logSession = Logger.openSession(applicationContext, logUri)
deviceName = intent?.getStringExtra(EXTRA_DEVICE_NAME)
Logger.i(logSession, "Service started")
val adapter = BluetoothAdapter.getDefaultAdapter()
bleManager!!.setLogger(logSession)
onServiceStarted()
bleManager!!.connect(bluetoothDevice)
manager.connect(bluetoothDevice)
.useAutoConnect(shouldAutoConnect())
.retry(3, 100)
.enqueue()
return START_REDELIVER_INTENT
}
/**
* Called when the service has been started. The device name and address are set.
* The BLE Manager will try to connect to the device after this method finishes.
*/
protected fun onServiceStarted() {
// empty default implementation
}
override fun onTaskRemoved(rootIntent: Intent) {
super.onTaskRemoved(rootIntent)
// This method is called when user removed the app from Recents.
@@ -326,58 +102,15 @@ abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
override fun onDestroy() {
super.onDestroy()
// Unregister broadcast receivers
unregisterReceiver(bluetoothStateBroadcastReceiver)
// shutdown the manager
bleManager!!.close()
manager.close()
Logger.i(logSession, "Service destroyed")
bleManager = null
bluetoothDeviceHolder.forgetDevice()
deviceName = null
logSession = null
handler = null
}
/**
* Method called when Bluetooth Adapter has been disabled.
*/
protected fun onBluetoothDisabled() {
// empty default implementation
}
/**
* This method is called when Bluetooth Adapter has been enabled and
* after the service was created if Bluetooth Adapter was enabled at that moment.
* This method could initialize all Bluetooth related features, for example open the GATT server.
*/
protected fun onBluetoothEnabled() {
// empty default implementation
}
override fun onDeviceConnecting(device: BluetoothDevice) {
val broadcast = Intent(BROADCAST_CONNECTION_STATE)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTING)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onDeviceConnected(device: BluetoothDevice) {
val broadcast = Intent(BROADCAST_CONNECTION_STATE)
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_DEVICE_NAME, deviceName)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onDeviceDisconnecting(device: BluetoothDevice) {
// Notify user about changing the state to DISCONNECTING
val broadcast = Intent(BROADCAST_CONNECTION_STATE)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTING)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
/**
* This method should return false if the service needs to do some asynchronous work after if has disconnected from the device.
* In that case the [.stopService] method must be called when done.
@@ -388,102 +121,19 @@ abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
return true
}
override fun onDeviceDisconnected(device: BluetoothDevice) {
// Note 1: Do not use the device argument here unless you change calling onDeviceDisconnected from the binder above
// Note 2: if BleManager#shouldAutoConnect() for this device returned true, this callback will be
// invoked ONLY when user requested disconnection (using Disconnect button). If the device
// disconnects due to a link loss, the onLinkLossOccurred(BluetoothDevice) method will be called instead.
val broadcast = Intent(BROADCAST_CONNECTION_STATE)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_DISCONNECTED)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
if (stopWhenDisconnected()) stopService()
}
protected fun stopService() {
private fun stopService() {
// user requested disconnection. We must stop the service
Logger.v(logSession, "Stopping service...")
stopSelf()
}
override fun onLinkLossOccurred(device: BluetoothDevice) {
val broadcast = Intent(BROADCAST_CONNECTION_STATE)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onServicesDiscovered(device: BluetoothDevice, optionalServicesFound: Boolean) {
val broadcast = Intent(BROADCAST_SERVICES_DISCOVERED)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, true)
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, optionalServicesFound)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onDeviceReady(device: BluetoothDevice) {
val broadcast = Intent(BROADCAST_DEVICE_READY)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onDeviceNotSupported(device: BluetoothDevice) {
val broadcast = Intent(BROADCAST_SERVICES_DISCOVERED)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_SERVICE_PRIMARY, false)
broadcast.putExtra(EXTRA_SERVICE_SECONDARY, false)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
// no need for disconnecting, it will be disconnected by the manager automatically
}
override fun onBatteryValueReceived(device: BluetoothDevice, value: Int) {
val broadcast = Intent(BROADCAST_BATTERY_LEVEL)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_BATTERY_LEVEL, value)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onBondingRequired(device: BluetoothDevice) {
showToast(R.string.csc_bonding)
val broadcast = Intent(BROADCAST_BOND_STATE)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onBonded(device: BluetoothDevice) {
showToast(R.string.csc_bonded)
val broadcast = Intent(BROADCAST_BOND_STATE)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onBondingFailed(device: BluetoothDevice) {
showToast(R.string.csc_bonding_failed)
val broadcast = Intent(BROADCAST_BOND_STATE)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
override fun onError(device: BluetoothDevice, message: String, errorCode: Int) {
val broadcast = Intent(BROADCAST_ERROR)
broadcast.putExtra(EXTRA_DEVICE, bluetoothDevice)
broadcast.putExtra(EXTRA_ERROR_MESSAGE, message)
broadcast.putExtra(EXTRA_ERROR_CODE, errorCode)
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast)
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId an resource id of the message to be shown
*/
protected fun showToast(messageResId: Int) {
handler!!.post {
handler?.post {
Toast.makeText(this@BleProfileService, messageResId, Toast.LENGTH_SHORT).show()
}
}
@@ -494,7 +144,7 @@ abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
* @param message a message to be shown
*/
protected fun showToast(message: String?) {
handler!!.post {
handler?.post {
Toast.makeText(this@BleProfileService, message, Toast.LENGTH_SHORT).show()
}
}
@@ -505,7 +155,7 @@ abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
* @return device address
*/
protected val deviceAddress: String
protected get() = bluetoothDevice!!.address
get() = bluetoothDevice.address
/**
* Returns `true` if the device is connected to the sensor.
@@ -513,41 +163,5 @@ abstract class BleProfileService : LifecycleService(), BleManagerCallbacks {
* @return `true` if device is connected to the sensor, `false` otherwise
*/
protected val isConnected: Boolean
protected get() = bleManager != null && bleManager!!.isConnected
companion object {
private const val TAG = "BleProfileService"
const val BROADCAST_CONNECTION_STATE =
"no.nordicsemi.android.nrftoolbox.BROADCAST_CONNECTION_STATE"
const val BROADCAST_SERVICES_DISCOVERED =
"no.nordicsemi.android.nrftoolbox.BROADCAST_SERVICES_DISCOVERED"
const val BROADCAST_DEVICE_READY = "no.nordicsemi.android.nrftoolbox.DEVICE_READY"
const val BROADCAST_BOND_STATE = "no.nordicsemi.android.nrftoolbox.BROADCAST_BOND_STATE"
@Deprecated("")
val BROADCAST_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.BROADCAST_BATTERY_LEVEL"
const val BROADCAST_ERROR = "no.nordicsemi.android.nrftoolbox.BROADCAST_ERROR"
/**
* The key for the device name that is returned in [.BROADCAST_CONNECTION_STATE] with state [.STATE_CONNECTED].
*/
const val EXTRA_DEVICE_NAME = "no.nordicsemi.android.nrftoolbox.EXTRA_DEVICE_NAME"
const val EXTRA_DEVICE = "no.nordicsemi.android.nrftoolbox.EXTRA_DEVICE"
const val EXTRA_LOG_URI = "no.nordicsemi.android.nrftoolbox.EXTRA_LOG_URI"
const val EXTRA_CONNECTION_STATE = "no.nordicsemi.android.nrftoolbox.EXTRA_CONNECTION_STATE"
const val EXTRA_BOND_STATE = "no.nordicsemi.android.nrftoolbox.EXTRA_BOND_STATE"
const val EXTRA_SERVICE_PRIMARY = "no.nordicsemi.android.nrftoolbox.EXTRA_SERVICE_PRIMARY"
const val EXTRA_SERVICE_SECONDARY =
"no.nordicsemi.android.nrftoolbox.EXTRA_SERVICE_SECONDARY"
@Deprecated("")
val EXTRA_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.EXTRA_BATTERY_LEVEL"
const val EXTRA_ERROR_MESSAGE = "no.nordicsemi.android.nrftoolbox.EXTRA_ERROR_MESSAGE"
const val EXTRA_ERROR_CODE = "no.nordicsemi.android.nrftoolbox.EXTRA_ERROR_CODE"
const val STATE_LINK_LOSS = -1
const val STATE_DISCONNECTED = 0
const val STATE_CONNECTED = 1
const val STATE_CONNECTING = 2
const val STATE_DISCONNECTING = 3
}
}
get() = manager.isConnected
}

View File

@@ -1,19 +0,0 @@
package no.nordicsemi.android.service
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
abstract class BluetoothDataReadBroadcast<T> {
private val _event = MutableSharedFlow<T>(
replay = 1,
extraBufferCapacity = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
val events: SharedFlow<T> = _event
fun offer(newEvent: T) {
_event.tryEmit(newEvent)
}
}

View File

@@ -31,9 +31,7 @@ import androidx.core.app.NotificationCompat
private const val CHANNEL_ID = "FOREGROUND_BLE_SERVICE"
abstract class ForegroundBleService<T : BatteryManager<out BatteryManagerCallbacks>> : BleProfileService() {
protected abstract val manager: T
abstract class ForegroundBleService : BleProfileService() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val result = super.onStartCommand(intent, flags, startId)
@@ -48,22 +46,6 @@ abstract class ForegroundBleService<T : BatteryManager<out BatteryManagerCallbac
super.onDestroy()
}
override fun onRebind() {
stopForegroundService()
if (isConnected) {
// This method will read the Battery Level value, if possible and then try to enable battery notifications (if it has NOTIFY property).
// If the Battery Level characteristic has only the NOTIFY property, it will only try to enable notifications.
manager.readBatteryLevelCharacteristic()
}
}
override fun onUnbind() {
// When we are connected, but the application is not open, we are not really interested in battery level notifications.
// But we will still be receiving other values, if enabled.
if (isConnected) manager.disableBatteryLevelCharacteristicNotifications()
startForegroundService()
}
/**
* Sets the service as a foreground service
*/

View File

@@ -1,32 +0,0 @@
package no.nordicsemi.android.service
import android.content.Context
import android.util.Log
import no.nordicsemi.android.ble.BleManagerCallbacks
import no.nordicsemi.android.ble.LegacyBleManager
import no.nordicsemi.android.log.ILogSession
import no.nordicsemi.android.log.LogContract
import no.nordicsemi.android.log.Logger
/**
* The manager that logs to nRF Logger. If nRF Logger is not installed, logs are ignored.
*
* @param <T> the callbacks class.
</T> */
abstract class LoggableBleManager<T : BleManagerCallbacks?>(context: Context) : LegacyBleManager<T>(context) {
private var logSession: ILogSession? = null
/**
* Sets the log session to log into.
*
* @param session nRF Logger log session to log inti, or null, if nRF Logger is not installed.
*/
fun setLogger(session: ILogSession?) {
logSession = session
}
override fun log(priority: Int, message: String) {
Logger.log(logSession, LogContract.Log.Level.fromPriority(priority), message)
Log.println(priority, "BleManager", message)
}
}

View File

@@ -16,7 +16,7 @@ class SelectedBluetoothDeviceHolder constructor(
return deviceManager.associations.firstOrNull()?.let { bluetoothAdapter?.getRemoteDevice(it) }
}
fun isDeviceBonded(): Boolean {
fun isBondingRequired(): Boolean {
return device?.bondState == BluetoothDevice.BOND_NONE
}
fun bondDevice() {