Sending and receiving data over usb is not working (Android studio Kotlin app)

253 views Asked by At

I am having some issues finding the correct way to connect to a usb FTDI device from an android phone. Does anybody know a way to do this with the standard function of android studio? The issue is either i have no permision for the usb connection. Now i have a nulpoint exeption even when is check if it is null. with as log

I QUALCOMM build : 961b24f, Ib57168459a Build Date : 02/24/20 OpenGL ES Shader Compiler Version: EV031.27.05.06 Local Branch : Remote Branch : Remote Branch : Reconstruct Branch : I Build Config : S L 8.0.12 AArch32 I PFP: 0x005ff113, ME: 0x005ff066 W mapper 3.x is not supported D init D init D recieved permision. D Received permission. D close D close D close D init E FATAL EXCEPTION: Thread-2 Process: eu.rovin, PID: 8317 java.lang.NullPointerException: Attempt to invoke virtual method 'int android.hardware.usb.UsbEndpoint.getDirection()' on a null object reference at android.hardware.usb.UsbRequest.dequeue(UsbRequest.java:303) at android.hardware.usb.UsbDeviceConnection.requestWait(UsbDeviceConnection.java:309) at eu.rovin.MainActivity$startListeningForUsbData$1.invoke(MainActivity.kt:224) at eu.rovin.MainActivity$startListeningForUsbData$1.invoke(MainActivity.kt:218) at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30) D init I Sending signal. PID: 8317 SIG: 9


import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.usb.UsbConstants
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbEndpoint
import android.hardware.usb.UsbManager
import android.hardware.usb.UsbRequest
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import eu.rovin.databinding.ActivityMainBinding
import android.widget.Button
import android.widget.EditText
import android.util.Log
import java.nio.ByteBuffer
import kotlin.concurrent.thread

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val ACTION_USB_PERMISSION = "com.example.usbtest.USB_PERMISSION"
    private lateinit var usbManager: UsbManager
    private lateinit var inputField: EditText
    private lateinit var connectButton: Button
    private lateinit var sendButton: Button
    private lateinit var receivedDataTextView: TextView
    private var connectedUsbDevice: UsbDevice? = null
    private var usbDeviceConnection: UsbDeviceConnection? = null
    private var usbEndpointOut: UsbEndpoint? = null
    private var usbEndpointIn: UsbEndpoint? = null
    private val receivedDataStringBuilder = StringBuilder()
    private var sendRequest: UsbRequest? = null
    private var usbRequestRecieved: UsbRequest? = null

    private val usbPermissionReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            Log.d(TAG, "recieved permision.")

            if (ACTION_USB_PERMISSION == intent?.action) {
                val granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                if (granted) {
                    Log.d(TAG, "Received permission.")
                    if (connectedUsbDevice != null) {
                        setupUsbCommunication(connectedUsbDevice!!)
                    }
                } else {
                }
            }
        }
    }

    private fun setupUsbCommunication(device: UsbDevice) {
        if (usbDeviceConnection != null) {
            closeUsbCommunication()
        }

        connectedUsbDevice = device
        usbDeviceConnection = usbManager?.openDevice(device)

        if (usbDeviceConnection != null) {

            // Example:
            for (i in 0 until device.interfaceCount) {
                val usbInterface = device.getInterface(i)
                for (j in 0 until usbInterface.endpointCount) {
                    val endpoint = usbInterface.getEndpoint(j)
                    if (endpoint.type == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                        if (endpoint.direction == UsbConstants.USB_DIR_IN) {
                            usbEndpointIn = endpoint
                            usbRequestRecieved = UsbRequest()
                            usbRequestRecieved?.initialize(usbDeviceConnection, usbEndpointIn)
                        } else {
                            usbEndpointOut = endpoint
                            sendRequest = UsbRequest()
                            sendRequest?.initialize(usbDeviceConnection, usbEndpointOut)
                        }
                    }
                }
            }

            startListeningForUsbData()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        usbManager = getSystemService(Context.USB_SERVICE) as UsbManager

        receivedDataTextView = findViewById(R.id.receivedDataTextView)
        inputField = findViewById(R.id.inputField)
        sendButton = findViewById(R.id.sendButton)
        connectButton = findViewById(R.id.connectButton)

        connectButton.setOnClickListener {
//            connectToFirstUsbDevice()
            val deviceList = usbManager?.deviceList
            if (deviceList?.isNotEmpty() == true) {
                for (device in deviceList.values) {

                    val permissionIntent = PendingIntent.getBroadcast(
                        this,
                        0,
                        Intent(ACTION_USB_PERMISSION),
                        0
                    )
                    usbManager?.requestPermission(device, permissionIntent)
                    setupUsbCommunication(device)
                }
            }
        }

        sendButton.setOnClickListener {
            val dataToSend = inputField.text.toString()
            if (dataToSend.isNotEmpty()) {
                // Send the data when the "Send Data" button is pressed
//                sendDataOverUsbDevice(dataToSend)
                sendUsbData(dataToSend.toByteArray())
            } else {
                // Handle the case where the input field is empty
                Log.e(TAG, "Input field is empty.")
            }
        }


//        deviceListTextView = findViewById(R.id.Connected_devices)
    }

    override fun onResume() {
        super.onResume()
        val filter = IntentFilter(ACTION_USB_PERMISSION)
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
        registerReceiver(usbPermissionReceiver, filter)
    }

    override fun onPause() {
        super.onPause()
        unregisterReceiver(usbPermissionReceiver)
    }

    private fun sendUsbData(dataToSend: ByteArray) {
        val request = sendRequest
        if (usbDeviceConnection != null && usbEndpointOut != null && request != null) {
            val buffer = ByteBuffer.wrap(dataToSend)
            request.queue(buffer, buffer.remaining())
            if (usbDeviceConnection!!.requestWait() == request) {
                Log.d(TAG, "Send data success.")
            } else {
                Log.e(TAG, "Sending data failed.")
            }
        }
    }

    private fun sendDataOverUsbDevice(dataToSend: String) {
        // Check if a USB device is connected
        if (connectedUsbDevice != null) {
            try {
                val dataBytes = dataToSend.toByteArray(Charsets.UTF_8)
                val timeout = 1000 // Set an appropriate timeout
                val dataByteBuffer = ByteBuffer.allocate(dataBytes.size)
                dataByteBuffer.put(dataBytes)
                dataByteBuffer.flip()

                val queue = sendRequest?.queue(dataByteBuffer, dataByteBuffer.remaining())

//                val sentBytes = connectedDevice!!.bulkTransfer(
//                    usbEndpointOut, // Provide the appropriate output endpoint
//                    dataToSend,
//                    dataToSend.size,
//                    timeout
//                )
                // Log the sent data for debugging
                Log.d(TAG, "Sent data over USB device: $dataToSend")
            } catch (e: Exception) {
                // Handle any exceptions that may occur during data transmission
                Log.e(TAG, "Error sending data over USB: ${e.message}")
            }
        } else {
            // Handle the case where no USB device is connected
            Log.e(TAG, "No USB device is connected.")
        }
    }

    private fun startListeningForUsbData() {
        if (usbDeviceConnection != null && usbEndpointIn != null) {
            thread {
                while (true) {
                    val request = usbRequestRecieved
                    if (request != null) {
                        val buffer = ByteBuffer.allocate(64)
                        request.queue(buffer, buffer.capacity())
                        if (usbDeviceConnection!!.requestWait() == request) {
                            buffer.flip()
                            val receivedData = String(buffer.array())
//                            receivedDataStringBuilder.append(receivedData)
                            runOnUiThread {
                                val receivedDataTextView = findViewById<TextView>(R.id.receivedDataTextView)
                                receivedDataTextView.text = receivedData.toString()
                            }
                        }
                    }
                }
            }
        }
    }

    companion object {
        private const val TAG = "MainActivity"  // Define a TAG for logging
    }

    private fun displayReceivedData(receivedData: String) {
        receivedDataTextView.text = "Received Data: $receivedData"
    }

    private fun closeUsbCommunication() {
        usbEndpointIn = null
        usbEndpointOut = null
        sendRequest?.close()
        usbRequestRecieved?.close()
        usbDeviceConnection?.close()
        connectedUsbDevice = null
        usbDeviceConnection = null
    }```

I tried to use the a connect button and a send button to connect and send without the UsbRequest class. Thane i was having problems with the thread being floudded and the app crashing. Then i was having issues with the receiving of the data. So i am now trying to use the UsbRequest class to send an receive data from the the FTDI. No success so far
0

There are 0 answers