FileTransfer.kt 2.16 KB
Newer Older
Anon's avatar
Anon committed
1 2 3 4
package com.github.antweb.donkey

import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
Anon's avatar
WIP  
Anon committed
5
import android.bluetooth.BluetoothGattDescriptor
Anon's avatar
Anon committed
6
import android.os.Environment
Anon's avatar
WIP  
Anon committed
7
import android.util.Log
Anon's avatar
Anon committed
8 9 10 11
import java.io.BufferedInputStream
import java.io.File
import java.io.FileInputStream
import java.nio.ByteBuffer
Anon's avatar
WIP  
Anon committed
12 13 14 15
import java.util.*
import java.util.zip.CRC32

private const val TAG = "FileTransfer"
Anon's avatar
Anon committed
16 17 18

class FileTransfer(
    private val gatt: BluetoothGatt,
Anon's avatar
WIP  
Anon committed
19 20
    private val tx: BluetoothGattCharacteristic,
    private val rx: BluetoothGattCharacteristic,
Anon's avatar
Anon committed
21 22 23 24 25 26 27
    private val mtu: Int
) {
    private val filePath = "/Download/SEND.txt"

    private val iterator = openFile().iterator()
    private var offset: Int = 0

Anon's avatar
WIP  
Anon committed
28 29 30
    private var lastCrc: Long = 0


Anon's avatar
Anon committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    private fun openFile(): ByteArray {
        // TODO: Don't listen to Android Docs, use stuff that is not deprecated
        val file = File(
            Environment.getExternalStorageDirectory()
                .absolutePath, filePath
        )

        val size = file.length()
        val bytes = ByteArray(size.toInt())
        val buf = BufferedInputStream(FileInputStream(file))
        buf.read(bytes, 0, bytes.size)
        buf.close()

        return bytes
    }

    fun sendFile() {
        // Send first chunk
        sendNext()
    }

    fun sendNext() {
Anon's avatar
WIP  
Anon committed
53 54
        Log.d(TAG, "Sending next chunk: $offset")

Anon's avatar
Anon committed
55 56 57 58 59
        if (!iterator.hasNext()) {
            return
        }

        val chunk = mutableListOf<Byte>()
Anon's avatar
WIP  
Anon committed
60 61
//        for (i in 0 until (mtu - 5)) {
        for (i in 0 until (10)) {
Anon's avatar
Anon committed
62 63 64 65 66 67 68 69 70 71 72
            chunk.add(iterator.next())
        }

        // Our packet:
        // 4 byte header + chunk
        val header = offset
        offset += chunk.size

        val sendBuffer = ByteBuffer.allocate(chunk.size + 4)
        sendBuffer.putInt(header)
        sendBuffer.put(chunk.toByteArray())
Anon's avatar
WIP  
Anon committed
73
        val bytes = sendBuffer.array()
Anon's avatar
Anon committed
74

Anon's avatar
WIP  
Anon committed
75 76 77
        val crc = CRC32()
        crc.update(bytes)
        lastCrc = crc.value
Anon's avatar
Anon committed
78

Anon's avatar
WIP  
Anon committed
79 80 81
//        gatt?.beginReliableWrite()
        tx?.value = bytes
        val status = gatt?.writeCharacteristic(tx)
Anon's avatar
Anon committed
82

Anon's avatar
WIP  
Anon committed
83 84 85
        if (!status) {
            Log.d(TAG, "Write status: $status")
        }
Anon's avatar
Anon committed
86 87
    }
}