package com.github.antweb.donkey import android.bluetooth.* import android.content.Context import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.util.Log import android.widget.Button import android.widget.TextView import java.lang.NullPointerException class MainActivity : AppCompatActivity() { private val TAG = "MainActivity" private val targetDeviceName = "card10" private val mtu = 128 private val serviceUuid = "00422342-2342-2342-2342-234223422342" private val dataCharacteristicUuid = "01422342-2342-2342-2342-234223422342" private val bluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE) { val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager.adapter } private var bluetoothGatt: BluetoothGatt? = null private var fileService: BluetoothGattService? = null private var dataCharacteristic: BluetoothGattCharacteristic? = null private var mGatt: BluetoothGatt? = null private var fileTransferService: FileTransfer? = null private var mScanning: Boolean = false private var connected = false private lateinit var tvConnection: TextView private lateinit var tvValue: TextView private lateinit var buttonConnect: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) tvValue = findViewById(R.id.text_value) tvConnection = findViewById(R.id.text_connection_status) tvConnection.text = "STATE_DISCONNECTED" buttonConnect = findViewById(R.id.button_connect) buttonConnect.setOnClickListener { scanLeDevice() } } private fun checkPermissions() { // if (bluetoothAdapter == null || !(bluetoothAdapter?.isEnabled)) { // val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) // startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) // } } private fun scanLeDevice() { 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() == dataCharacteristicUuid) { dataCharacteristic = characteristic } } } if (fileService == null || dataCharacteristic == 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 onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) { Log.d(TAG, "MTU changed to: $mtu") runOnUiThread { tvValue.text = "MTU: $mtu" } val lData = dataCharacteristic if (gatt != null && lData != null) { fileTransferService = FileTransfer(gatt, lData, 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() } } val leScanCallback = BluetoothAdapter.LeScanCallback { device, _, _ -> if (device.name == targetDeviceName) { if (!connected) { connected = true bluetoothGatt = device.connectGatt(this, true, gattCallback, BluetoothDevice.TRANSPORT_LE) } } } // Stops scanning after a pre-defined period Handler().postDelayed({ mScanning = false bluetoothAdapter?.stopLeScan(leScanCallback) }, 5000) mScanning = true bluetoothAdapter?.startLeScan(leScanCallback) } }