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