Я реализую небольшое приложение BLE и у меня есть список устройств, и я хочу отключить их, когда я нажимаю на них в представлении списка.
UUID моего сервиса: 0xFFB0
Мои характеристики c UUID: 0xFFB7 Запись с ответом / Чтение с ответом
Характеристики c Формат:
Порядок байтов; 0; 1 ~ 19
R / W ON / OFF; -
0x01 -> ON и 0x00 -> OFF
class MainActivity : AppCompatActivity() {
private var macList: ArrayList<String> = ArrayList()
private var deviceList: ArrayList<BluetoothDevice> = ArrayList()
private lateinit var adapter: ArrayAdapter<String>
private var mBtAdapter: BluetoothAdapter? = null
private var mConnectedGatt: BluetoothGatt? = null
private var mCharacteristic: BluetoothGattCharacteristic? = null
private var on = true
private lateinit var currentDevice: BluetoothDevice
/**
* CHECK IF BT AND LOCATION IS ON!
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!isBLESupported(this)) {
Toast.makeText(this, "This device doesn't support bluetooth", Toast.LENGTH_SHORT).show()
finish()
} else {
if (!mBtAdapter!!.isEnabled) {
val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBluetoothIntent, REQUEST_ENABLE_BLUETOOTH)
}
}
adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, macList)
list_view.adapter = adapter
list_view.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
currentDevice = deviceList[position]
mConnectedGatt = currentDevice.connectGatt(applicationContext, false, gattCallback)
}
scan_button.setOnClickListener {
scanForDeviceWithFilter(LIGHT_SERVICE)
}
power_button.setOnClickListener {
mConnectedGatt = currentDevice.connectGatt(applicationContext, true, powerCallback)
on = !on
}
}
override fun onStop() {
super.onStop()
//Disconnect from any active tag connection
if (mConnectedGatt != null) {
mConnectedGatt!!.disconnect()
mConnectedGatt = null
}
}
private fun scanForDeviceWithFilter(serviceUUID: Int) {
val uuid = ParcelUuid(convertFromInteger(serviceUUID))
val filter = ScanFilter.Builder().setServiceUuid(uuid).build()
val filters = listOf(filter)
val settings = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build()
checkBTPermissions()
mBtAdapter!!.bluetoothLeScanner.startScan(filters, settings, scanDevicesCallback)
Thread.sleep(3000)
mBtAdapter!!.bluetoothLeScanner.stopScan(scanDevicesCallback)
}
private val scanDevicesCallback = object : ScanCallback() {
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
results?.forEach { result ->
macList.add(result.device.toString())
Log.d(TAG, "device name:${result.device}")
}
}
override fun onScanResult(callbackType: Int, result: ScanResult?) {
result?.let {
if (!macList.contains(result.device.name.toString())) {
deviceList.add(result.device)
macList.add(result.device.name.toString())
adapter.notifyDataSetChanged()
}
Log.d(TAG, "device found:${result.device}")
}
}
override fun onScanFailed(errorCode: Int) {
Log.d(TAG, "Scan failed $errorCode")
}
}
private val gattCallback = object : BluetoothGattCallback() {
/* OK */
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
Log.d(TAG, "Connection State Change: " + status + " -> " + connectionState(newState))
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
/**
* Once successfully connected, we must next discover all the services on the
* device before we can read and write their characteristics.
*/
gatt.discoverServices()
Thread.sleep(500)
} else if (status != BluetoothGatt.GATT_SUCCESS) {
/**
* If there is a failure at any stage, simply disconnect
*/
gatt.disconnect()
}
}
private fun connectionState(status: Int): String {
return when (status) {
BluetoothProfile.STATE_CONNECTED -> "Connected"
BluetoothProfile.STATE_DISCONNECTED -> "Disconnected"
BluetoothProfile.STATE_CONNECTING -> "Connecting"
BluetoothProfile.STATE_DISCONNECTING -> "Disconnecting"
else -> status.toString()
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
mCharacteristic = gatt?.getService(convertFromInteger(LIGHT_SERVICE))?.getCharacteristic(convertFromInteger(PASSWORD_CHARACTERISTIC))
mCharacteristic!!.setValue("0123")
if (gatt!!.writeCharacteristic(mCharacteristic)) {
Log.d(TAG, "Login success")
Thread.sleep(500)
} else
Log.d(TAG, "Login failed")
}
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
if (status != BluetoothGatt.GATT_SUCCESS) {
Log.d("onCharacteristicWrite", "Failed write, retrying: $status")
gatt!!.writeCharacteristic(characteristic)
}
super.onCharacteristicWrite(gatt, characteristic, status)
}
}
private val powerCallback = object : BluetoothGattCallback() {
/* OK */
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
Log.d(TAG, "Connection State Change: " + status + " -> " + connectionState(newState))
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices()
Thread.sleep(500)
} else if (status != BluetoothGatt.GATT_SUCCESS) {
gatt.disconnect()
}
}
private fun connectionState(status: Int): String {
return when (status) {
BluetoothProfile.STATE_CONNECTED -> "Connected"
BluetoothProfile.STATE_DISCONNECTED -> "Disconnected"
BluetoothProfile.STATE_CONNECTING -> "Connecting"
BluetoothProfile.STATE_DISCONNECTING -> "Disconnecting"
else -> status.toString()
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
if (on) {
mCharacteristic = gatt!!.getService(convertFromInteger(LIGHT_SERVICE))?.getCharacteristic(convertFromInteger(LIGHT_CHARACTERISTIC))
mCharacteristic!!.setValue("0")
gatt.setCharacteristicNotification(mCharacteristic, true)
if (gatt.writeCharacteristic(mCharacteristic)) {
Log.d(TAG, "Power off success")
Thread.sleep(500)
} else Log.d(TAG, "Power off failed")
} else {
mCharacteristic = gatt!!.getService(convertFromInteger(LIGHT_SERVICE))?.getCharacteristic(convertFromInteger(LIGHT_CHARACTERISTIC))
mCharacteristic!!.setValue("1")
if (gatt.writeCharacteristic(mCharacteristic)) {
Log.d(TAG, "Power on success")
Thread.sleep(500)
} else Log.d(TAG, "Power on failed")
}
}
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
if (status != BluetoothGatt.GATT_SUCCESS) {
Log.d("onCharacteristicWrite", "Failed write, retrying: $status")
gatt!!.writeCharacteristic(characteristic)
}
super.onCharacteristicWrite(gatt, characteristic, status);
}
}
private fun isBLESupported(context: Context): Boolean {
return BluetoothAdapter.getDefaultAdapter() != null && context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
}
init {
mBtAdapter = BluetoothAdapter.getDefaultAdapter()
}
private fun checkBTPermissions() {
val permissionCheck = checkSelfPermission("Manifest.permission.ACCESS_FINE_LOCATION")
if (permissionCheck != 0) {
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1001)
}
}
fun convertFromInteger(i: Int): UUID? {
val msb = 0x0000000000001000L
val lsb = -0x7fffff7fa064cb05L
val value = (i and ((-0x1).toLong()).toInt()).toLong()
return UUID(msb or (value shl 32), lsb)
}
companion object {
private const val TAG = "Main Activity"
private const val LIGHT_SERVICE = 0xffb0
private const val LIGHT_CHARACTERISTIC = 0xffb7
private const val PASSWORD_CHARACTERISTIC = 0xffba
private const val REQUEST_ENABLE_BLUETOOTH = 1
}
}
Я изменил свой код, но теперь, когда я пытаюсь писать, я получаю status = 128; GATT_NO_RESOURCES и я понятия не имею, что делать.