package com.github.antweb.donkey import android.bluetooth.* import android.content.Context import android.os.Bundle import android.util.Log import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import java.lang.NullPointerException import java.util.* private const val TAG = "SendActivity" class SendActivity : AppCompatActivity() { private val mtu = 128 private val serviceUuid = "00422342-2342-2342-2342-234223422342" private val centralTxCharacteristicUuid = UUID.fromString("01422342-2342-2342-2342-234223422342") // private var centralTxCharacteristic: BluetoothGattCharacteristic? = null private val centralRxCharacteristicUuid = UUID.fromString("02422342-2342-2342-2342-234223422342") // private var centralRxCharacteristic: BluetoothGattCharacteristic? = null private val clientConfigUuid = "00002902-0000-1000-8000-00805f9b34fb" private var bluetoothGatt: BluetoothGatt? = null private var fileService: BluetoothGattService? = null private var mGatt: BluetoothGatt? = null private var fileTransferService: FileTransfer? = null private lateinit var tvConnection: TextView private lateinit var tvValue: TextView private val bluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE) { val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager.adapter } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_send) tvValue = findViewById(R.id.text_value) tvConnection = findViewById(R.id.text_connection_status) tvConnection.text = "STATE_DISCONNECTED" val device = ScanActivity.selectedDevice if (device != null) { connect(device) } else { Log.e(TAG, "Device is NULL!") } } fun connect(device: BluetoothDevice) { val gattCallback = object : BluetoothGattCallback() { override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { super.onServicesDiscovered(gatt, status) if (gatt == null) { throw NullPointerException() } for (service in gatt.services) { Log.d(TAG, "Found service: ${service.uuid}") if (service.uuid.toString() == serviceUuid) { fileService = service } // for (characteristic in service.characteristics) { // Log.d(TAG, "Characteristic: ${characteristic.uuid}") // // if (characteristic.uuid.toString() == centralTxCharacteristicUuid) { // centralTxCharacteristic = characteristic // } else if (characteristic.uuid.toString() == centralRxCharacteristicUuid) { // centralRxCharacteristic = characteristic // } // } } if (fileService == null) { // if (fileService == null || centralTxCharacteristic == null) { Log.e(TAG, "Could not find file transfer service") return } gatt.requestMtu(mtu) } override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { super.onConnectionStateChange(gatt, status, newState) when (newState) { BluetoothGatt.STATE_CONNECTED -> { runOnUiThread { tvConnection.text = "STATE_CONNECTED" } mGatt = gatt gatt?.discoverServices() } BluetoothGatt.STATE_DISCONNECTED -> tvConnection.text = "STATE_DISCONNECTED" BluetoothGatt.STATE_CONNECTING -> tvConnection.text = "STATE_CONNECTING" BluetoothGatt.STATE_DISCONNECTING -> tvConnection.text = "STATE_DISCONNECTING" } } override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?) { super.onCharacteristicChanged(gatt, characteristic) } override fun onCharacteristicRead( gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int ) { super.onCharacteristicRead(gatt, characteristic, status) } override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) { Log.d(TAG, "MTU changed to: $mtu") runOnUiThread { tvValue.text = "MTU: $mtu" } val tx = fileService?.getCharacteristic(centralTxCharacteristicUuid) val rx = fileService?.getCharacteristic(centralRxCharacteristicUuid) if (gatt != null && tx != null && rx != null) { val descriptor = rx.getDescriptor(UUID.fromString(clientConfigUuid)) if (descriptor != null) { gatt.setCharacteristicNotification(rx, true) descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE val success = gatt.writeDescriptor(descriptor) if (!success) { Log.e(TAG, "Descriptor write failed") } } else { Log.e(TAG, "Failed to write descriptor") } fileTransferService = FileTransfer(gatt, tx, rx, mtu) fileTransferService?.sendFile() } } override fun onReliableWriteCompleted(gatt: BluetoothGatt?, status: Int) { // Last chunk sent successfully. Send next chunk // fileTransferService?.sendNext() } override fun onCharacteristicWrite( gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int ) { // gatt?.executeReliableWrite() Thread.sleep(3000) fileTransferService?.sendNext() return } } bluetoothGatt = device.connectGatt(this, true, gattCallback, BluetoothDevice.TRANSPORT_LE) } }