I'm stuck on figuring out how to ask for permission to access a USB com device, wait for the user input, then proceed accordingly if permission granted. I can't figure out what the "onRequestPermissionsResult
" is for when UsbManager
asks for permissions. I noticed that listener never gets called when UsbManager
requests permission, so its not used in the way I originally thought.
This code is all in the MainActivity
.
Here I'm setting my Intent
for when my USB device is connected or disconnected, and initializing UsbManager
.
Note I'm not using LOGCAT to log debug messages because my Android device has to be disconnected from Android Studio to plug in the USB com device I'm developing the app for. Instead I'm logging to the app UI.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DoIntent();
m_manager = (UsbManager) getSystemService(Context.USB_SERVICE);
}
private void DoIntent () {
m_usbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
try {
OnDeviceConnected();
// m_textViewDebug.setText("USB Connected");
} catch (Exception e) {
m_textViewDebug.setText(e.getMessage());
}
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
m_port = null;
m_serialIoManager = null;
m_isInitialized = false;
m_textViewDebug.setText("USB Disconnected");
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(m_usbReceiver , filter);
Then here is what happens when a device is connected. I want to establish permission as soon as its connected.
private void OnDeviceConnected () throws Exception {
ProbeTable customTable = new ProbeTable();
customTable.addProduct(0x239a, 0x800c, CdcAcmSerialDriver.class);
UsbSerialProber prober = new UsbSerialProber(customTable);
List<UsbSerialDriver> drivers = prober.findAllDrivers(m_manager);
UsbDeviceConnection connection = null;
UsbSerialDriver driver = drivers.get(0);
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(INTENT_ACTION_GRANT_USB), 0);
m_manager.requestPermission(driver.getDevice(), usbPermissionIntent);
/// Need some kind of pause or check for permissions here before executing forward.or
/// handle everything after on a different routine called after permission has been selected.
/// Continues to execute before user has time to respond to permissions.
try {
connection = m_manager.openDevice(driver.getDevice());
} catch (Exception e) {
throw new Exception(e.getMessage());
}
if (connection == null) {
throw new Exception ("Could not open device.");
}
m_port = driver.getPorts().get(0);
try {
m_port.open(connection);
m_port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
m_port.setDTR(true);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
m_serialIoManager = new SerialInputOutputManager(m_port, m_listener);
m_executor.submit(m_serialIoManager);
m_isInitialized = true;
}
Then here is what I'm originally trying to do once permission has been granted. I can't get any logging message to appear from this scope, so I believe it's never being called and I'm using it incorrectly.
@Override
public void onRequestPermissionsResult(final int requestCode, String[] permissions, int[] grantResults) {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
/// Never gets called :/
m_textViewDebug.setText(Integer.toString(requestCode));
}
});
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
/// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
/// permission was granted, yay! Do the
/// contacts-related task you need to do.
} else {
/// permission denied, boo! Disable the
/// functionality that depends on this permission.
}
return;
case USB_PERMISSION_GRANTED: { /// Not the real enum because I'm not sure where to find what it is.
try {
/// Need to somehow pass driver from OnDeviceConnected to this scope, or make it class property.
connection = m_manager.openDevice(driver.getDevice());
} catch (Exception e) {
throw new Exception(e.getMessage());
}
if (connection == null) {
throw new Exception ("Could not open device.");
}
m_port = driver.getPorts().get(0);
try {
m_port.open(connection);
m_port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
m_port.setDTR(true);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
m_serialIoManager = new SerialInputOutputManager(m_port, m_listener);
m_executor.submit(m_serialIoManager);
m_isInitialized = true
}
/// other 'case' lines to check for other
/// permissions this app might request.
}
}
I'm trying to log what requestCode
is so I can write a case for whatever the USB permission code is. I can't find a compiled list anywhere in the docs of what all the options are that requestCode
could be.
MY_PERMISSIONS_REQUEST_READ_CONTACTS
actually throws a compile error because I have no idea where it comes from. This guide isn't very detail with USB specifically. That guide is also where I got the switch statement in my above routine.
EDIT:
I tried messing around with UsbManager.EXTRA_PERMISSION_GRANTED
to see if that could work. I added it as an action to my intent filter.
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction(UsbManager.EXTRA_PERMISSION_GRANTED);
registerReceiver(m_usbReceiver, filter);
Then I'm logging what the action of the intent is coming into my Broadcast Receiver, but nothing happens when a USB permission is granted or denied.
What kind of action or event is triggered when "OK" is tapped in this above image? Been scratching my head at this for a few days poking at the API.