From 201a04bfbf1c8e8f742931371ed23c895b800cbc Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 13 Dec 2021 01:01:16 +0100 Subject: [PATCH] Unify bluetooth, Android 12 permissions --- .../maintenance/ImportExportPrefsImpl.kt | 100 ++++++++++-------- .../androidaps/queue/QueueThread.kt | 11 +- .../automation/triggers/TriggerBTDevice.kt | 2 +- core/src/main/AndroidManifest.xml | 2 + .../androidaps/dialogs/BolusProgressDialog.kt | 1 + .../plugins/pump/common/ble/BlePreCheck.kt | 17 ++- danar/src/main/AndroidManifest.xml | 2 + .../AbstractDanaRExecutionService.java | 3 +- .../danars/activities/BLEScanActivity.kt | 13 +-- .../androidaps/danars/services/BLEComm.kt | 21 ++-- diaconn/src/main/AndroidManifest.xml | 4 + .../activities/DiaconnG8BLEScanActivity.kt | 6 +- .../diaconn/service/BLECommonService.kt | 11 +- insight/src/main/AndroidManifest.xml | 2 + .../activities/InsightPairingActivity.java | 15 ++- .../InsightConnectionService.java | 5 +- .../pump/medtronic/MedtronicFragment.kt | 12 +-- .../pump/medtronic/MedtronicPumpPlugin.kt | 90 ++++++++-------- .../comm/ui/MedtronicUIPostprocessor.kt | 2 +- .../medtronic/driver/MedtronicPumpStatus.kt | 4 +- omnipod-dash/src/main/AndroidManifest.xml | 1 + .../driver/comm/OmnipodDashBleManagerImpl.kt | 3 +- .../dash/driver/comm/session/Connection.kt | 8 +- .../DashPodActivationWizardActivity.kt | 14 ++- .../plugins/pump/common/PumpPluginAbstract.kt | 51 +++------ rileylink/src/main/AndroidManifest.xml | 3 + .../common/hw/rileylink/ble/RileyLinkBLE.kt | 9 +- .../hw/rileylink/ble/device/OrangeLinkImpl.kt | 53 ++-------- .../service/RileyLinkBroadcastReceiver.java | 3 +- 29 files changed, 231 insertions(+), 237 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefsImpl.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefsImpl.kt index d9d5088830..10d062aef2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefsImpl.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefsImpl.kt @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.general.maintenance import android.Manifest -import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothManager import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -24,8 +24,6 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.events.EventAppExit import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.ImportExportPrefs -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.general.maintenance.formats.* @@ -41,9 +39,11 @@ import info.nightscout.androidaps.utils.alertDialogs.WarningDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.protection.PasswordCheck import info.nightscout.androidaps.utils.resources.ResourceHelper -import info.nightscout.shared.sharedPreferences.SP import info.nightscout.androidaps.utils.storage.Storage import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag +import info.nightscout.shared.sharedPreferences.SP import java.io.File import java.io.FileNotFoundException import java.io.IOException @@ -81,17 +81,13 @@ class ImportExportPrefsImpl @Inject constructor( override fun verifyStoragePermissions(fragment: Fragment, onGranted: Runnable) { fragment.context?.let { ctx -> - val permission = ContextCompat.checkSelfPermission(ctx, - Manifest.permission.WRITE_EXTERNAL_STORAGE) + val permission = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE) if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user fragment.activity?.let { - androidPermission.askForPermission(it, - arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) + androidPermission.askForPermission(it, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) } - } else { - onGranted.run() - } + } else onGranted.run() } } @@ -114,7 +110,7 @@ class ImportExportPrefsImpl @Inject constructor( // based on https://medium.com/@pribble88/how-to-get-an-android-device-nickname-4b4700b3068c val n1 = Settings.System.getString(context.contentResolver, "bluetooth_name") val n2 = Settings.Secure.getString(context.contentResolver, "bluetooth_name") - val n3 = BluetoothAdapter.getDefaultAdapter()?.name + val n3 = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.name val n4 = Settings.System.getString(context.contentResolver, "device_name") val n5 = Settings.Secure.getString(context.contentResolver, "lock_screen_owner_info") val n6 = Settings.Global.getString(context.contentResolver, "device_name") @@ -132,36 +128,38 @@ class ImportExportPrefsImpl @Inject constructor( passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { password -> then(password) }, { - ToastUtils.warnToast(activity, rh.gs(canceledMsg)) - }) + ToastUtils.warnToast(activity, rh.gs(canceledMsg)) + }) } @Suppress("SameParameterValue") - private fun askForEncryptionPass(activity: FragmentActivity, @StringRes canceledMsg: Int, @StringRes passwordName: Int, @StringRes passwordExplanation: Int?, - @StringRes passwordWarning: Int?, then: ((password: String) -> Unit)) { + private fun askForEncryptionPass( + activity: FragmentActivity, @StringRes canceledMsg: Int, @StringRes passwordName: Int, @StringRes passwordExplanation: Int?, + @StringRes passwordWarning: Int?, then: ((password: String) -> Unit) + ) { passwordCheck.queryAnyPassword(activity, passwordName, R.string.key_master_password, passwordExplanation, passwordWarning, { password -> then(password) }, { - ToastUtils.warnToast(activity, rh.gs(canceledMsg)) - }) + ToastUtils.warnToast(activity, rh.gs(canceledMsg)) + }) } @Suppress("SameParameterValue") private fun askForMasterPassIfNeeded(activity: FragmentActivity, @StringRes canceledMsg: Int, then: ((password: String) -> Unit)) { - askForMasterPass(activity, canceledMsg, then) + askForMasterPass(activity, canceledMsg, then) } private fun assureMasterPasswordSet(activity: FragmentActivity, @StringRes wrongPwdTitle: Int): Boolean { if (!sp.contains(R.string.key_master_password) || (sp.getString(R.string.key_master_password, "") == "")) { WarningDialog.showWarning(activity, - rh.gs(wrongPwdTitle), - rh.gs(R.string.master_password_missing, rh.gs(R.string.configbuilder_general), rh.gs(R.string.protection)), - R.string.nav_preferences, { - val intent = Intent(activity, PreferencesActivity::class.java).apply { - putExtra("id", R.xml.pref_general) - } - activity.startActivity(intent) - }) + rh.gs(wrongPwdTitle), + rh.gs(R.string.master_password_missing, rh.gs(R.string.configbuilder_general), rh.gs(R.string.protection)), + R.string.nav_preferences, { + val intent = Intent(activity, PreferencesActivity::class.java).apply { + putExtra("id", R.xml.pref_general) + } + activity.startActivity(intent) + }) return false } return true @@ -170,29 +168,37 @@ class ImportExportPrefsImpl @Inject constructor( private fun askToConfirmExport(activity: FragmentActivity, fileToExport: File, then: ((password: String) -> Unit)) { if (!assureMasterPasswordSet(activity, R.string.nav_export)) return - TwoMessagesAlertDialog.showAlert(activity, rh.gs(R.string.nav_export), + TwoMessagesAlertDialog.showAlert( + activity, rh.gs(R.string.nav_export), rh.gs(R.string.export_to) + " " + fileToExport.name + " ?", rh.gs(R.string.password_preferences_encrypt_prompt), { - askForMasterPassIfNeeded(activity, R.string.preferences_export_canceled, then) - }, null, R.drawable.ic_header_export) + askForMasterPassIfNeeded(activity, R.string.preferences_export_canceled, then) + }, null, R.drawable.ic_header_export + ) } private fun askToConfirmImport(activity: FragmentActivity, fileToImport: PrefsFile, then: ((password: String) -> Unit)) { if (!assureMasterPasswordSet(activity, R.string.nav_import)) return - TwoMessagesAlertDialog.showAlert(activity, rh.gs(R.string.nav_import), + TwoMessagesAlertDialog.showAlert( + activity, rh.gs(R.string.nav_import), rh.gs(R.string.import_from) + " " + fileToImport.name + " ?", rh.gs(R.string.password_preferences_decrypt_prompt), { - askForMasterPass(activity, R.string.preferences_import_canceled, then) - }, null, R.drawable.ic_header_import) + askForMasterPass(activity, R.string.preferences_import_canceled, then) + }, null, R.drawable.ic_header_import + ) } - private fun promptForDecryptionPasswordIfNeeded(activity: FragmentActivity, prefs: Prefs, importOk: Boolean, - format: PrefsFormat, importFile: PrefsFile, then: ((prefs: Prefs, importOk: Boolean) -> Unit)) { + private fun promptForDecryptionPasswordIfNeeded( + activity: FragmentActivity, prefs: Prefs, importOk: Boolean, + format: PrefsFormat, importFile: PrefsFile, then: ((prefs: Prefs, importOk: Boolean) -> Unit) + ) { // current master password was not the one used for decryption, so we prompt for old password... if (!importOk && (prefs.metadata[PrefsMetadataKey.ENCRYPTION]?.status == PrefsStatus.ERROR)) { - askForEncryptionPass(activity, R.string.preferences_import_canceled, R.string.old_master_password, - R.string.different_password_used, R.string.master_password_will_be_replaced) { password -> + askForEncryptionPass( + activity, R.string.preferences_import_canceled, R.string.old_master_password, + R.string.different_password_used, R.string.master_password_will_be_replaced + ) { password -> // ...and use it to load & decrypt file again val prefsReloaded = format.loadPreferences(importFile.file, password) @@ -232,15 +238,19 @@ class ImportExportPrefsImpl @Inject constructor( ToastUtils.errorToast(activity, e.message) log.error(LTag.CORE, "Unhandled exception", e) } catch (e: PrefFileNotFoundError) { - ToastUtils.Long.errorToast(activity, rh.gs(R.string.preferences_export_canceled) - + "\n\n" + rh.gs(R.string.filenotfound) - + ": " + e.message - + "\n\n" + rh.gs(R.string.needstoragepermission)) + ToastUtils.Long.errorToast( + activity, rh.gs(R.string.preferences_export_canceled) + + "\n\n" + rh.gs(R.string.filenotfound) + + ": " + e.message + + "\n\n" + rh.gs(R.string.needstoragepermission) + ) log.error(LTag.CORE, "File system exception", e) } catch (e: PrefIOError) { - ToastUtils.Long.errorToast(activity, rh.gs(R.string.preferences_export_canceled) - + "\n\n" + rh.gs(R.string.needstoragepermission) - + ": " + e.message) + ToastUtils.Long.errorToast( + activity, rh.gs(R.string.preferences_export_canceled) + + "\n\n" + rh.gs(R.string.needstoragepermission) + + ": " + e.message + ) log.error(LTag.CORE, "File system exception", e) } } @@ -269,7 +279,7 @@ class ImportExportPrefsImpl @Inject constructor( askToConfirmImport(activity, importFile) { password -> - val format: PrefsFormat = encryptedPrefsFormat + val format: PrefsFormat = encryptedPrefsFormat try { diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt index c947eda8b7..f536e70625 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt @@ -1,6 +1,6 @@ package info.nightscout.androidaps.queue -import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothManager import android.content.Context import android.os.PowerManager import android.os.SystemClock @@ -9,18 +9,18 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.CommandQueue -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning import info.nightscout.androidaps.queue.events.EventQueueChanged import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import info.nightscout.shared.sharedPreferences.SP class QueueThread internal constructor( private val queue: CommandQueue, - context: Context, + private val context: Context, private val aapsLogger: AAPSLogger, private val rxBus: RxBus, private val activePlugin: ActivePlugin, @@ -63,8 +63,7 @@ class QueueThread internal constructor( //toggle BT pump.disconnect("watchdog") SystemClock.sleep(1000) - val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() - if (bluetoothAdapter != null) { + (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.let { bluetoothAdapter -> bluetoothAdapter.disable() SystemClock.sleep(1000) bluetoothAdapter.enable() diff --git a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBTDevice.kt b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBTDevice.kt index daa1e53ef0..96f385f077 100644 --- a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBTDevice.kt +++ b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBTDevice.kt @@ -74,7 +74,7 @@ class TriggerBTDevice(injector: HasAndroidInjector) : Trigger(injector) { // Get the list of paired BT devices to use in dropdown menu private fun devicesPaired(): ArrayList { val s = ArrayList() - (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter?.bondedDevices?.forEach { s.add(it.name) } + (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter?.bondedDevices?.forEach { s.add(it.name) } return s } diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 9ef7e793bf..1e43d69ec4 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -7,6 +7,8 @@ + + = /*Build.VERSION_CODES.S*/31) { + //ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT), PERMISSION_REQUEST_BLUETOOTH) + ActivityCompat.requestPermissions(activity, arrayOf("android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT"), PERMISSION_REQUEST_BLUETOOTH) + } - val bluetoothAdapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter + val bluetoothAdapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter // Ensures Bluetooth is available on the device and it is enabled. If not, // displays a dialog requesting user permission to enable Bluetooth. - if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled) { + if (bluetoothAdapter?.isEnabled != true) { + bluetoothAdapter?.enable() + SystemClock.sleep(3000) + } + if (bluetoothAdapter?.isEnabled != true) { OKDialog.show(activity, rh.gs(R.string.message), rh.gs(R.string.ble_not_enabled)) return false } else { diff --git a/danar/src/main/AndroidManifest.xml b/danar/src/main/AndroidManifest.xml index f32d848875..26ce981370 100644 --- a/danar/src/main/AndroidManifest.xml +++ b/danar/src/main/AndroidManifest.xml @@ -3,6 +3,8 @@ + + bondedDevices = bluetoothAdapter.getBondedDevices(); diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/activities/BLEScanActivity.kt b/danars/src/main/java/info/nightscout/androidaps/danars/activities/BLEScanActivity.kt index dc90ef01f7..4352630f7f 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/activities/BLEScanActivity.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/activities/BLEScanActivity.kt @@ -3,9 +3,11 @@ package info.nightscout.androidaps.danars.activities import android.annotation.SuppressLint import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice +import android.bluetooth.BluetoothManager import android.bluetooth.le.BluetoothLeScanner import android.bluetooth.le.ScanCallback import android.bluetooth.le.ScanResult +import android.content.Context import android.content.pm.ActivityInfo import android.os.Bundle import android.os.Handler @@ -30,10 +32,12 @@ class BLEScanActivity : NoSplashAppCompatActivity() { @Inject lateinit var sp: SP @Inject lateinit var rxBus: RxBus @Inject lateinit var blePreCheck: BlePreCheck + @Inject lateinit var context: Context private var listAdapter: ListAdapter? = null private val devices = ArrayList() - private var bluetoothLeScanner: BluetoothLeScanner? = null + private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter + private val bluetoothLeScanner: BluetoothLeScanner? get() = bluetoothAdapter?.bluetoothLeScanner private lateinit var binding: DanarsBlescannerActivityBinding @@ -55,11 +59,8 @@ class BLEScanActivity : NoSplashAppCompatActivity() { override fun onResume() { super.onResume() - BluetoothAdapter.getDefaultAdapter()?.let { bluetoothAdapter -> - if (!bluetoothAdapter.isEnabled) bluetoothAdapter.enable() - bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner - startScan() - } + if (bluetoothAdapter?.isEnabled != true) bluetoothAdapter?.enable() + startScan() } override fun onPause() { diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt b/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt index b14f00649d..b7fd9fe286 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt @@ -21,8 +21,6 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.extensions.notify import info.nightscout.androidaps.extensions.waitMillis import info.nightscout.androidaps.interfaces.PumpSync -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification @@ -31,6 +29,8 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import info.nightscout.shared.sharedPreferences.SP import java.util.* import java.util.concurrent.ScheduledFuture @@ -69,8 +69,7 @@ class BLEComm @Inject internal constructor( private var scheduledDisconnection: ScheduledFuture<*>? = null private var processedMessage: DanaRSPacket? = null private val mSendQueue = ArrayList() - private var bluetoothManager: BluetoothManager? = null - private var bluetoothAdapter: BluetoothAdapter? = null + private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter private var connectDeviceName: String? = null private var bluetoothGatt: BluetoothGatt? = null @@ -92,14 +91,6 @@ class BLEComm @Inject internal constructor( @Synchronized fun connect(from: String, address: String?): Boolean { aapsLogger.debug(LTag.PUMPBTCOMM, "Initializing BLEComm.") - if (bluetoothManager == null) { - bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - if (bluetoothManager == null) { - aapsLogger.error("Unable to initialize BluetoothManager.") - return false - } - } - bluetoothAdapter = bluetoothManager?.adapter if (bluetoothAdapter == null) { aapsLogger.error("Unable to obtain a BluetoothAdapter.") return false @@ -411,7 +402,8 @@ class BLEComm @Inject internal constructor( if (bufferLength >= 6) { for (idxStartByte in 0 until bufferLength - 2) { if (readBuffer[idxStartByte] == PACKET_START_BYTE && readBuffer[idxStartByte + 1] == PACKET_START_BYTE || - readBuffer[idxStartByte] == BLE5_PACKET_START_BYTE && readBuffer[idxStartByte + 1] == BLE5_PACKET_START_BYTE) { + readBuffer[idxStartByte] == BLE5_PACKET_START_BYTE && readBuffer[idxStartByte + 1] == BLE5_PACKET_START_BYTE + ) { if (idxStartByte > 0) { // if buffer doesn't start with signature remove the leading trash aapsLogger.debug(LTag.PUMPBTCOMM, "Shifting the input buffer by $idxStartByte bytes") @@ -429,7 +421,8 @@ class BLEComm @Inject internal constructor( return // Verify packed end [5A 5A] if (readBuffer[length + 5] == PACKET_END_BYTE && readBuffer[length + 6] == PACKET_END_BYTE || - readBuffer[length + 5] == BLE5_PACKET_END_BYTE && readBuffer[length + 6] == BLE5_PACKET_END_BYTE) { + readBuffer[length + 5] == BLE5_PACKET_END_BYTE && readBuffer[length + 6] == BLE5_PACKET_END_BYTE + ) { packetIsValid = true } else { aapsLogger.error(LTag.PUMPBTCOMM, "Error in input data. Resetting buffer.") diff --git a/diaconn/src/main/AndroidManifest.xml b/diaconn/src/main/AndroidManifest.xml index 3ddb6c3a37..2d23e77d9c 100644 --- a/diaconn/src/main/AndroidManifest.xml +++ b/diaconn/src/main/AndroidManifest.xml @@ -5,6 +5,10 @@ + + + + diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt index 22cbaa8745..25dda64b2a 100644 --- a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/activities/DiaconnG8BLEScanActivity.kt @@ -3,11 +3,13 @@ package info.nightscout.androidaps.diaconn.activities import android.annotation.SuppressLint import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice +import android.bluetooth.BluetoothManager import android.bluetooth.le.BluetoothLeScanner import android.bluetooth.le.ScanCallback import android.bluetooth.le.ScanFilter import android.bluetooth.le.ScanResult import android.bluetooth.le.ScanSettings +import android.content.Context import android.content.pm.ActivityInfo import android.os.Bundle import android.os.Handler @@ -32,7 +34,9 @@ class DiaconnG8BLEScanActivity : NoSplashAppCompatActivity() { @Inject lateinit var sp: SP @Inject lateinit var rxBus: RxBus @Inject lateinit var blePreCheck: BlePreCheck + @Inject lateinit var context: Context + private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter private var listAdapter: ListAdapter? = null private val devices = ArrayList() private var bluetoothLeScanner: BluetoothLeScanner? = null @@ -58,7 +62,7 @@ class DiaconnG8BLEScanActivity : NoSplashAppCompatActivity() { override fun onResume() { super.onResume() - BluetoothAdapter.getDefaultAdapter()?.let { bluetoothAdapter -> + bluetoothAdapter?.let { bluetoothAdapter -> if (!bluetoothAdapter.isEnabled) bluetoothAdapter.enable() bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner startScan() diff --git a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt index 4c0aa3632c..d8b1edd5c2 100644 --- a/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt +++ b/diaconn/src/main/java/info/nightscout/androidaps/diaconn/service/BLECommonService.kt @@ -44,8 +44,7 @@ class BLECommonService @Inject internal constructor( private var processedMessage: DiaconnG8Packet? = null private var processedMessageByte: ByteArray? = null private val mSendQueue = ArrayList() - private var bluetoothManager: BluetoothManager? = null - private var bluetoothAdapter: BluetoothAdapter? = null + private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter private var connectDeviceName: String? = null private var bluetoothGatt: BluetoothGatt? = null @@ -69,14 +68,6 @@ class BLECommonService @Inject internal constructor( @Synchronized fun connect(from: String, address: String?): Boolean { aapsLogger.debug(LTag.PUMPBTCOMM, "Initializing Bluetooth ") - if (bluetoothManager == null) { - bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - if (bluetoothManager == null) { - aapsLogger.error("Unable to initialize BluetoothManager.") - return false - } - } - bluetoothAdapter = bluetoothManager?.adapter if (bluetoothAdapter == null) { aapsLogger.error("Unable to obtain a BluetoothAdapter.") return false diff --git a/insight/src/main/AndroidManifest.xml b/insight/src/main/AndroidManifest.xml index f00fc7fba9..9cb3923c6b 100644 --- a/insight/src/main/AndroidManifest.xml +++ b/insight/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + rh.gs(resourceId) @@ -337,7 +337,7 @@ class MedtronicFragment : DaggerFragment() { binding.reservoir.text = rh.gs(R.string.reservoirvalue, medtronicPumpStatus.reservoirRemainingUnits, medtronicPumpStatus.reservoirFullUnits) warnColors.setColorInverse(binding.reservoir, medtronicPumpStatus.reservoirRemainingUnits, 50.0, 20.0) - medtronicPumpPlugin.rileyLinkService.verifyConfiguration() + medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() binding.errors.text = medtronicPumpStatus.errorInfo val showRileyLinkBatteryLevel: Boolean = rileyLinkServiceData.showBatteryLevel diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 4a34d86f08..c9c5fbabb9 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -13,14 +13,13 @@ import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.events.EventRefreshButtonState @@ -33,6 +32,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry @@ -56,6 +56,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.TimeChangeType import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import info.nightscout.shared.sharedPreferences.SP import org.joda.time.LocalDateTime import java.util.* @@ -89,7 +91,7 @@ class MedtronicPumpPlugin @Inject constructor( aapsSchedulers: AapsSchedulers, pumpSync: PumpSync, pumpSyncStorage: info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage -) : info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract(PluginDescription() // +) : PumpPluginAbstract(PluginDescription() // .mainType(PluginType.PUMP) // .fragmentClass(MedtronicFragment::class.java.name) // .pluginIcon(R.drawable.ic_veo_128) @@ -97,11 +99,11 @@ class MedtronicPumpPlugin @Inject constructor( .shortName(R.string.medtronic_name_short) // .preferencesId(R.xml.pref_medtronic) .description(R.string.description_pump_medtronic), // - PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later - injector, rh, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync, pumpSyncStorage -), Pump, RileyLinkPumpDevice, info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator { + PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later + injector, rh, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync, pumpSyncStorage +), Pump, RileyLinkPumpDevice, PumpSyncEntriesCreator { - private lateinit var rileyLinkMedtronicService: RileyLinkMedtronicService + private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null // variables for handling statuses and history private var firstRun = true @@ -126,12 +128,12 @@ class MedtronicPumpPlugin @Inject constructor( val mLocalBinder = service as RileyLinkMedtronicService.LocalBinder rileyLinkMedtronicService = mLocalBinder.serviceInstance isServiceSet = true - rileyLinkMedtronicService.verifyConfiguration() + rileyLinkMedtronicService?.verifyConfiguration() Thread { for (i in 0..19) { SystemClock.sleep(5000) aapsLogger.debug(LTag.PUMP, "Starting Medtronic-RileyLink service") - if (rileyLinkMedtronicService.setNotInPreInit()) { + if (rileyLinkMedtronicService?.setNotInPreInit() == true) { break } } @@ -232,9 +234,7 @@ class MedtronicPumpPlugin @Inject constructor( // Pump Plugin private var isServiceSet: Boolean = false - override fun getRileyLinkService(): RileyLinkMedtronicService { - return rileyLinkMedtronicService - } + override fun getRileyLinkService(): RileyLinkMedtronicService? = rileyLinkMedtronicService override fun getPumpInfo(): RileyLinkPumpInfo { val frequency = rh.gs(if (medtronicPumpStatus.pumpFrequency == "medtronic_pump_frequency_us_ca") R.string.medtronic_pump_frequency_us_ca else R.string.medtronic_pump_frequency_worldwide) @@ -294,12 +294,12 @@ class MedtronicPumpPlugin @Inject constructor( override fun isConnected(): Boolean { if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnected") - return isServiceSet && rileyLinkMedtronicService.isInitialized + return isServiceSet && rileyLinkMedtronicService?.isInitialized == true } override fun isConnecting(): Boolean { if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnecting") - return !isServiceSet || !rileyLinkMedtronicService.isInitialized + return !isServiceSet || rileyLinkMedtronicService?.isInitialized != true } override fun getPumpStatus(reason: String) { @@ -330,7 +330,7 @@ class MedtronicPumpPlugin @Inject constructor( aapsLogger.debug(LTag.PUMP, "RileyLink unreachable.") return false } - return !rileyLinkMedtronicService.deviceCommunicationManager.isDeviceReachable + return rileyLinkMedtronicService?.deviceCommunicationManager?.isDeviceReachable != true } private fun refreshAnyStatusThatNeedsToBeRefreshed() { @@ -369,13 +369,13 @@ class MedtronicPumpPlugin @Inject constructor( } MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.RemainingInsulin -> { - rileyLinkMedtronicService.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) refreshTypesNeededToReschedule.add(key) resetTime = true } MedtronicStatusRefreshType.Configuration -> { - rileyLinkMedtronicService.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) resetTime = true } } @@ -406,7 +406,7 @@ class MedtronicPumpPlugin @Inject constructor( private fun initializePump(): Boolean { if (!isServiceSet) return false aapsLogger.info(LTag.PUMP, logPrefix + "initializePump - start") - rileyLinkMedtronicService.deviceCommunicationManager.setDoWakeUpBeforeCommand(false) + rileyLinkMedtronicService?.deviceCommunicationManager?.setDoWakeUpBeforeCommand(false) setRefreshButtonEnabled(false) if (isRefresh) { if (isPumpNotReachable) { @@ -420,7 +420,7 @@ class MedtronicPumpPlugin @Inject constructor( // model (once) if (!medtronicUtil.isModelSet) { - rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.PumpModel) } else { if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) { aapsLogger.warn(LTag.PUMP, logPrefix + "Configured pump is not the same as one detected.") @@ -434,19 +434,19 @@ class MedtronicPumpPlugin @Inject constructor( readPumpHistory() // remaining insulin (>50 = 4h; 50-20 = 1h; 15m) - rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetRemainingInsulin) scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10) // remaining power (1h) - rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBatteryStatus) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetBatteryStatus) scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20) // configuration (once and then if history shows config changes) - rileyLinkMedtronicService.medtronicUIComm.executeCommand(getSettings(medtronicUtil.medtronicPumpModel)) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(getSettings(medtronicUtil.medtronicPumpModel)) // read profile (once, later its controlled by isThisProfileSet method) basalProfiles - val errorCount = rileyLinkMedtronicService.medtronicUIComm.invalidResponsesCount + val errorCount = rileyLinkMedtronicService?.medtronicUIComm?.invalidResponsesCount ?: 0 if (errorCount >= 5) { aapsLogger.error("Number of error counts was 5 or more. Starting tuning.") setRefreshButtonEnabled(true) @@ -466,9 +466,9 @@ class MedtronicPumpPlugin @Inject constructor( private val basalProfiles: Unit get() { - val medtronicUITask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) - if (medtronicUITask.responseType === MedtronicUIResponseType.Error) { - rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + val medtronicUITask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + if (medtronicUITask?.responseType === MedtronicUIResponseType.Error) { + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetBasalProfileSTD) } } @@ -558,10 +558,10 @@ class MedtronicPumpPlugin @Inject constructor( return } medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) - rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetRealTimeClock) var clock = medtronicUtil.pumpTime if (clock == null) { // retry - rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetRealTimeClock) clock = medtronicUtil.pumpTime } if (clock == null) return @@ -569,7 +569,7 @@ class MedtronicPumpPlugin @Inject constructor( if (timeDiff > 20) { if (clock.localDeviceTime.year <= 2015 || timeDiff <= 24 * 60 * 60) { aapsLogger.info(LTag.PUMP, String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is %d s. Set time on pump.", timeDiff)) - rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetRealTimeClock) + rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetRealTimeClock) if (clock.timeDifference == 0) { val notification = Notification(Notification.INSIGHT_DATE_TIME_UPDATED, rh.gs(R.string.pump_time_updated), Notification.INFO, 60) rxBus.send(EventNewNotification(notification)) @@ -619,9 +619,9 @@ class MedtronicPumpPlugin @Inject constructor( bolusDeliveryType = BolusDeliveryType.Delivering // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); - val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus, + val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetBolus, arrayListOf(detailedBolusInfo.insulin)) - val response = responseTask.result as Boolean? + val response = responseTask?.result as Boolean? setRefreshButtonEnabled(true) // LOG.debug("MedtronicPumpPlugin::deliverBolus - Response: {}", response); @@ -639,8 +639,6 @@ class MedtronicPumpPlugin @Inject constructor( }.start() } val now = System.currentTimeMillis() - detailedBolusInfo.timestamp = now - detailedBolusInfo.deliverAtTheLatest = now // not sure about that one pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this) @@ -743,8 +741,8 @@ class MedtronicPumpPlugin @Inject constructor( aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - TBR running - so canceling it.") // CANCEL - val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) - val response = responseTask2.result as Boolean? + val responseTask2 = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.CancelTBR) + val response = responseTask2?.result as Boolean? if (response == null || !response) { aapsLogger.error(logPrefix + "setTempBasalAbsolute - Cancel TBR failed.") finishAction("TBR") @@ -757,9 +755,9 @@ class MedtronicPumpPlugin @Inject constructor( } // now start new TBR - val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetTemporaryBasal, + val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetTemporaryBasal, arrayListOf(absoluteRate, durationInMinutes)) - val response = responseTask.result as Boolean? + val response = responseTask?.result as Boolean? aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - setTBR. Response: " + response) return if (response == null || !response) { finishAction("TBR") @@ -922,10 +920,10 @@ class MedtronicPumpPlugin @Inject constructor( //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); @Suppress("UNCHECKED_CAST") - val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData, + val responseTask2 = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.GetHistoryData, arrayListOf(/*lastPumpHistoryEntry*/ null, targetDate) as? ArrayList?) if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: After task") - val historyResult = responseTask2.result as PumpHistoryResult? + val historyResult = responseTask2?.result as PumpHistoryResult? if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString()) val latestEntry = historyResult!!.latestEntry if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "Last entry: " + latestEntry) @@ -1018,8 +1016,8 @@ class MedtronicPumpPlugin @Inject constructor( } private fun readTBR(): TempBasalPair? { - val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.ReadTemporaryBasal) - return if (responseTask.hasData()) { + val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.ReadTemporaryBasal) + return if (responseTask?.hasData() == true) { val tbr = responseTask.result as TempBasalPair? // we sometimes get rate returned even if TBR is no longer running @@ -1060,8 +1058,8 @@ class MedtronicPumpPlugin @Inject constructor( return PumpEnactResult(injector).success(false).enacted(false) .comment(R.string.medtronic_cmd_cant_read_tbr) } - val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) - val response = responseTask2.result as Boolean? + val responseTask2 = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.CancelTBR) + val response = responseTask2?.result as Boolean? finishAction("TBR") return if (response == null || !response) { aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR failed.") @@ -1145,9 +1143,9 @@ class MedtronicPumpPlugin @Inject constructor( .enacted(false) // .comment(rh.gs(R.string.medtronic_cmd_set_profile_pattern_overflow, profileInvalid)) } - val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetBasalProfileSTD, + val responseTask = rileyLinkMedtronicService?.medtronicUIComm?.executeCommand(MedtronicCommandType.SetBasalProfileSTD, arrayListOf(basalProfile)) - val response = responseTask.result as Boolean? + val response = responseTask?.result as Boolean? aapsLogger.info(LTag.PUMP, logPrefix + "Basal Profile was set: " + response) return if (response == null || !response) { PumpEnactResult(injector).success(false).enacted(false) // @@ -1203,7 +1201,7 @@ class MedtronicPumpPlugin @Inject constructor( override fun executeCustomAction(customActionType: CustomActionType) { when (customActionType as? MedtronicCustomActionType) { MedtronicCustomActionType.WakeUpAndTune -> { - if (rileyLinkMedtronicService.verifyConfiguration()) { + if (rileyLinkMedtronicService?.verifyConfiguration() == true) { serviceTaskExecutor.startTask(WakeAndTuneTask(injector)) } else { runAlarm(context, rh.gs(R.string.medtronic_error_operation_not_possible_no_configuration), rh.gs(R.string.medtronic_warning), R.raw.boluserror) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt index 594c1d643a..3ab64f8c3d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -148,7 +148,7 @@ class MedtronicUIPostprocessor @Inject constructor( medtronicUtil.settings = settings var checkValue: PumpSettingDTO - medtronicPumpPlugin.rileyLinkService.verifyConfiguration() + medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() // check profile if (settings.containsKey("PCFG_BASAL_PROFILES_ENABLED") && settings.containsKey("PCFG_ACTIVE_BASAL_PROFILE")) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index efdfd9510c..af528a521e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -58,7 +58,7 @@ class MedtronicPumpStatus @Inject constructor(private val rh: ResourceHelper, if (medtronicDeviceTypeMap.isEmpty()) createMedtronicDeviceTypeMap() lastConnection = sp.getLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, 0L) lastDataTime = lastConnection - var serial = sp.getStringOrNull(MedtronicConst.Prefs.PumpSerial, null) + val serial = sp.getStringOrNull(MedtronicConst.Prefs.PumpSerial, null) if (serial != null) { serialNumber = serial } @@ -105,7 +105,7 @@ class MedtronicPumpStatus @Inject constructor(private val rh: ResourceHelper, private var batteryTypeByDescMap: MutableMap = HashMap() fun getBatteryTypeByDescription(batteryTypeStr: String?): BatteryType? { - if (batteryTypeByDescMap.size == 0) { + if (batteryTypeByDescMap.isEmpty()) { for (value in BatteryType.values()) { batteryTypeByDescMap[rh.gs(value.description)] = value } diff --git a/omnipod-dash/src/main/AndroidManifest.xml b/omnipod-dash/src/main/AndroidManifest.xml index 4f6d8178c6..fe414a04c7 100644 --- a/omnipod-dash/src/main/AndroidManifest.xml +++ b/omnipod-dash/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt index cb2adda059..986a3236c7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashBleManagerImpl.kt @@ -30,8 +30,7 @@ class OmnipodDashBleManagerImpl @Inject constructor( ) : OmnipodDashBleManager { private val busy = AtomicBoolean(false) - private val bluetoothAdapter: BluetoothAdapter? - get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter + private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter private var connection: Connection? = null private val ids = Ids(podState) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt index b174ad6065..c1a2361d41 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/Connection.kt @@ -53,8 +53,7 @@ class Connection( private val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets, this) private var gattConnection: BluetoothGatt? = null - private val bluetoothManager: BluetoothManager = - context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + private val bluetoothManager: BluetoothManager? = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager? @Volatile var session: Session? = null @@ -67,8 +66,7 @@ class Connection( podState.connectionAttempts++ podState.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING val autoConnect = false - val gatt = gattConnection - ?: podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) + val gatt = gattConnection ?: podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) gattConnection = gatt if (!gatt.connect()) { throw FailedToConnectException("connect() returned false") @@ -150,7 +148,7 @@ class Connection( } fun connectionState(): ConnectionState { - val connectionState = bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT) + val connectionState = bluetoothManager?.getConnectionState(podDevice, BluetoothProfile.GATT) aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: $connectionState") if (connectionState != BluetoothProfile.STATE_CONNECTED) { return NotConnected diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/DashPodActivationWizardActivity.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/DashPodActivationWizardActivity.kt index ad340053bf..6d4028c7f4 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/DashPodActivationWizardActivity.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/DashPodActivationWizardActivity.kt @@ -1,5 +1,17 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activation +import android.os.Bundle +import info.nightscout.androidaps.plugins.pump.common.ble.BlePreCheck import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.PodActivationWizardActivity +import javax.inject.Inject -class DashPodActivationWizardActivity : PodActivationWizardActivity() +class DashPodActivationWizardActivity : PodActivationWizardActivity() { + + @Inject lateinit var blePreCheck: BlePreCheck + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + blePreCheck.prerequisitesCheck(this) + } +} \ No newline at end of file diff --git a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index 3cbadb94d6..d634e9c73a 100644 --- a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -4,9 +4,7 @@ import android.content.Context import android.content.Intent import android.content.ServiceConnection import android.text.format.DateFormat -import com.google.gson.GsonBuilder import dagger.android.HasAndroidInjector - import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.events.EventAppExit @@ -16,20 +14,21 @@ import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.extensions.toStringFull import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.common.ManufacturerType import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import info.nightscout.shared.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable import org.json.JSONException @@ -74,8 +73,6 @@ abstract class PumpPluginAbstract protected constructor( pumpDescription.fillFor(value) } - protected var gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() - abstract fun initPumpStatusData() override fun onStart() { @@ -85,9 +82,9 @@ abstract class PumpPluginAbstract protected constructor( context.bindService(intent, serviceConnection!!, Context.BIND_AUTO_CREATE) serviceRunning = true disposable.add(rxBus - .toObservable(EventAppExit::class.java) - .observeOn(aapsSchedulers.io) - .subscribe({ _ -> context.unbindService(serviceConnection!!) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) } + .toObservable(EventAppExit::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ _ -> context.unbindService(serviceConnection!!) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) } ) onStartCustomActions() } @@ -113,17 +110,9 @@ abstract class PumpPluginAbstract protected constructor( abstract val serviceClass: Class<*>? abstract val pumpStatusData: PumpStatus - override fun isInitialized(): Boolean { - return pumpState.isInitialized() - } - - override fun isSuspended(): Boolean { - return pumpState === PumpDriverState.Suspended - } - - override fun isBusy(): Boolean { - return pumpState === PumpDriverState.Busy - } + override fun isInitialized(): Boolean = pumpState.isInitialized() + override fun isSuspended(): Boolean = pumpState == PumpDriverState.Suspended + override fun isBusy(): Boolean = pumpState == PumpDriverState.Busy override fun isConnected(): Boolean { if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "isConnected [PumpPluginAbstract].") @@ -335,10 +324,9 @@ abstract class PumpPluginAbstract protected constructor( // bolus needed, ask pump to deliver it deliverBolus(detailedBolusInfo) } else { - detailedBolusInfo.timestamp = System.currentTimeMillis() // no bolus required, carb only treatment - pumpSyncStorage.addCarbs(info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs(detailedBolusInfo, this)) + pumpSyncStorage.addCarbs(PumpDbEntryCarbs(detailedBolusInfo, this)) val bolusingEvent = EventOverviewBolusProgress bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, detailedBolusInfo.carbs.toInt(), detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) @@ -357,25 +345,16 @@ abstract class PumpPluginAbstract protected constructor( rxBus.send(EventCustomActionsChanged()) } - override fun manufacturer(): ManufacturerType { - return pumpType.manufacturer!! - } - - override fun model(): PumpType { - return pumpType - } - - override fun canHandleDST(): Boolean { - return false - } + override fun manufacturer(): ManufacturerType = pumpType.manufacturer!! + override fun model(): PumpType = pumpType + override fun canHandleDST(): Boolean = false protected abstract fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult protected abstract fun triggerUIChange() - private fun getOperationNotSupportedWithCustomText(resourceId: Int): PumpEnactResult { - return PumpEnactResult(injector).success(false).enacted(false).comment(resourceId) - } + private fun getOperationNotSupportedWithCustomText(resourceId: Int): PumpEnactResult = + PumpEnactResult(injector).success(false).enacted(false).comment(resourceId) init { pumpDescription.fillFor(pumpType) diff --git a/rileylink/src/main/AndroidManifest.xml b/rileylink/src/main/AndroidManifest.xml index a04965eb76..8bffe46b1e 100644 --- a/rileylink/src/main/AndroidManifest.xml +++ b/rileylink/src/main/AndroidManifest.xml @@ -3,12 +3,15 @@ + + + diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.kt b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.kt index a178605b62..0a557d79ed 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.kt +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.kt @@ -42,7 +42,8 @@ class RileyLinkBLE @Inject constructor(private val context: Context) { private val gattDebugEnabled = true private var manualDisconnect = false - val bluetoothAdapter: BluetoothAdapter = BluetoothAdapter.getDefaultAdapter() + + val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter private val bluetoothGattCallback: BluetoothGattCallback var rileyLinkDevice: BluetoothDevice? = null private var bluetoothConnectionGatt: BluetoothGatt? = null @@ -128,7 +129,7 @@ class RileyLinkBLE @Inject constructor(private val context: Context) { aapsLogger.debug(LTag.PUMPBTCOMM, "Start scan for OrangeLink device.") orangeLink.startScan() } else { - rileyLinkDevice = bluetoothAdapter.getRemoteDevice(rileyLinkAddress) + rileyLinkDevice = bluetoothAdapter?.getRemoteDevice(rileyLinkAddress) // if this succeeds, we get a connection state change callback? if (rileyLinkDevice != null) connectGattInternal() else aapsLogger.error(LTag.PUMPBTCOMM, "RileyLink device not found with address: $rileyLinkAddress") @@ -155,7 +156,7 @@ class RileyLinkBLE @Inject constructor(private val context: Context) { bluetoothConnectionGatt = rileyLinkDevice?.connectGatt(context, true, bluetoothGattCallback) // , BluetoothDevice.TRANSPORT_LE if (bluetoothConnectionGatt == null) - aapsLogger.error(LTag.PUMPBTCOMM, "Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter.address) + aapsLogger.error(LTag.PUMPBTCOMM, "Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter?.address) else { if (gattDebugEnabled) aapsLogger.debug(LTag.PUMPBTCOMM, "Gatt Connected.") val deviceName = bluetoothConnectionGatt?.device?.name @@ -361,7 +362,7 @@ class RileyLinkBLE @Inject constructor(private val context: Context) { } if (newState == BluetoothProfile.STATE_CONNECTED) { if (status == BluetoothGatt.GATT_SUCCESS) rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothConnected, context) - else aapsLogger.debug(LTag.PUMPBTCOMM, "BT State connected, GATT status ${status} (${getGattStatusMessage(status)})") + else aapsLogger.debug(LTag.PUMPBTCOMM, "BT State connected, GATT status $status (${getGattStatusMessage(status)})") } else if (newState == BluetoothProfile.STATE_CONNECTING || newState == BluetoothProfile.STATE_DISCONNECTING) { aapsLogger.debug(LTag.PUMPBTCOMM, "We are in ${if (status == BluetoothProfile.STATE_CONNECTING) "Connecting" else "Disconnecting"} state.") } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/device/OrangeLinkImpl.kt b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/device/OrangeLinkImpl.kt index 0e8f3cf6d7..4cfa13000b 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/device/OrangeLinkImpl.kt +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/device/OrangeLinkImpl.kt @@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.device import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothGattCharacteristic -import android.bluetooth.le.BluetoothLeScanner import android.bluetooth.le.ScanCallback import android.bluetooth.le.ScanFilter import android.bluetooth.le.ScanResult @@ -10,14 +9,14 @@ import android.bluetooth.le.ScanSettings import android.os.Handler import android.os.HandlerThread import android.os.Message -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import info.nightscout.shared.sharedPreferences.SP import java.util.* import javax.inject.Inject @@ -37,10 +36,7 @@ class OrangeLinkImpl @Inject constructor( if (characteristic.uuid.toString() == GattAttributes.CHARA_NOTIFICATION_ORANGE) { val data = characteristic.value val first = 0xff and data[0].toInt() - aapsLogger.info( - LTag.PUMPBTCOMM, - "OrangeLinkImpl: onCharacteristicChanged " + ByteUtil.shortHexString(characteristic.value) + "=====" + first - ) + aapsLogger.info(LTag.PUMPBTCOMM, "OrangeLinkImpl: onCharacteristicChanged ${ByteUtil.shortHexString(characteristic.value)}=====$first") val fv = data[3].toString() + "." + data[4] val hv = data[5].toString() + "." + data[6] rileyLinkServiceData.versionOrangeFirmware = fv @@ -60,9 +56,8 @@ class OrangeLinkImpl @Inject constructor( * We are checking if this is special Orange (with ORANGE_NOTIFICATION_SERVICE) */ fun checkIsOrange(uuidService: UUID) { - if (GattAttributes.isOrange(uuidService)) { + if (GattAttributes.isOrange(uuidService)) rileyLinkServiceData.isOrange = true - } } fun enableNotifications(): Boolean { @@ -98,15 +93,14 @@ class OrangeLinkImpl @Inject constructor( fun startScan() { try { stopScan() - val bluetoothAdapter = rileyLinkBLE.bluetoothAdapter aapsLogger.debug(LTag.PUMPBTCOMM, "startScan") handler.sendEmptyMessageDelayed(TIME_OUT_WHAT, TIME_OUT.toLong()) - val bluetoothLeScanner: BluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner + val bluetoothLeScanner = rileyLinkBLE.bluetoothAdapter?.bluetoothLeScanner // if (bluetoothLeScanner == null) { // bluetoothAdapter.startLeScan(mLeScanCallback) // return // } - bluetoothLeScanner.startScan(buildScanFilters(), buildScanSettings(), scanCallback) + bluetoothLeScanner?.startScan(buildScanFilters(), buildScanSettings(), scanCallback) } catch (e: Exception) { e.printStackTrace() aapsLogger.error(LTag.PUMPBTCOMM, "Start scan: ${e.message}", e) @@ -135,15 +129,6 @@ class OrangeLinkImpl @Inject constructor( } } - /* - private val mLeScanCallback = LeScanCallback { device, _, _ -> - if (rileyLinkServiceData.rileyLinkAddress.equals(device.address)) { - stopScan() - rileyLinkBLE.rileyLinkDevice = device - rileyLinkBLE.connectGattInternal() - } - } - */ private val handler: Handler = object : Handler(HandlerThread(this::class.java.simpleName + "Handler").also { it.start() }.looper) { override fun handleMessage(msg: Message) { super.handleMessage(msg) @@ -156,35 +141,17 @@ class OrangeLinkImpl @Inject constructor( fun stopScan() { handler.removeMessages(TIME_OUT_WHAT) - val bluetoothAdapter = rileyLinkBLE.bluetoothAdapter - try { - val bluetoothLeScanner: BluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner + if (isBluetoothAvailable()) + rileyLinkBLE.bluetoothAdapter?.bluetoothLeScanner?.stopScan(scanCallback) - if (isBluetoothAvailable()) { - bluetoothLeScanner.stopScan(scanCallback) - } - - return - - // if (bluetoothLeScanner == null) { - // if (isBluetoothAvailable()) { - // bluetoothAdapter.stopLeScan(mLeScanCallback) - // } - // return - // } - // if (isBluetoothAvailable()) { - // bluetoothLeScanner.stopScan(scanCallback) - // } } catch (e: Exception) { aapsLogger.error(LTag.PUMPBTCOMM, "Stop scan: ${e.message}", e) } } - private fun isBluetoothAvailable(): Boolean { - val bluetoothAdapter = rileyLinkBLE.bluetoothAdapter - return bluetoothAdapter.isEnabled && bluetoothAdapter.state == BluetoothAdapter.STATE_ON - } + private fun isBluetoothAvailable(): Boolean = + rileyLinkBLE.bluetoothAdapter?.isEnabled == true && rileyLinkBLE.bluetoothAdapter?.state == BluetoothAdapter.STATE_ON companion object { diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java index a88ce1e74a..d984c9ed27 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java @@ -5,6 +5,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service; */ import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -134,7 +135,7 @@ public class RileyLinkBroadcastReceiver extends DaggerBroadcastReceiver { RileyLinkService rileyLinkService = getServiceInstance(); if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) { - if (BluetoothAdapter.getDefaultAdapter().isEnabled()) { + if (((BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter().isEnabled()) { rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.RileyLinkUnreachable); } else { rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled);