SendActivity.kt 6.47 KB
Newer Older
Anon's avatar
WIP  
Anon committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
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)
    }
}