Android USB connection established only the second time the app is opened - android

For my application, I need to establish a connection with an attached Arduino device, here is the code:
public String openConnection(UsbManager manager, Context context) {
// getting the driver with an external library...
UsbSerialDriver driver = availableDrivers.get(0);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
manager.requestPermission(driver.getDevice(), pi);
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
if (connection == null) {
return "Found a device, but cannot connect";
}
// otherwise, continue and do stuff
}
The problem is that, when a device is attached, the first time I open the app it shows the alert asking for the permission, but if I click "OK", the connection is null, so it returns early. However, the second time it does not ask for any permission but the connection is opened and everything works fine.
Why does this happen?
I know this is not the most correct approach to open an USB connection, but I have other issues that are not inherent to the question, so I'm rather intrested to understand why does this happen than what should I do instead
I'm testing this on Android 8.1.0

Try to previously ask for permission and start the rest of your code from a Broadcast Receiver that listens for the USB permission granted.
This is showed in Google's docs:
private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//call method to set up device communication
}
}
else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
Here's how you register the Broadcast Receiver:
UsbManager mUsbManager = (UsbManager)
getSystemService(Context.USB_SERVICE);
private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
...
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new
Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
And then you start it all with:
UsbDevice device;
...
mUsbManager.requestPermission(device, mPermissionIntent);
In the way you do it, the device tries to connect to USB even before the permission has been granted and so it fails.

Related

Android external fingerprint USB always returns false on USB permission

I have problem with Futronic fingerprint usb device on Android 10 & 11. The code
intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
always return false when I press the OK button on permission dialog. I have old an android 5 device, it works OK.
Here is the code from their SDK (UsbDeviceDataExchangeImpl.java), included as module on Android Studio
public UsbDeviceDataExchangeImpl( Context ctx, Handler trg_handler )
{
context = ctx;
handler = trg_handler;
mDevManager = (UsbManager)ctx.getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(ctx, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
context.registerReceiver(mUsbReceiver, filter);
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action))
{
synchronized (mPermissionIntent)
{
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
{
if(device != null)
{
usb_ctx = OpenDevice(device);
}
handler.obtainMessage(MESSAGE_ALLOW_DEVICE).sendToTarget();
}
else
{
handler.obtainMessage(MESSAGE_DENY_DEVICE).sendToTarget();
}
}
}
}
};
Are there any extra permission settings for Android 10 & 11 for external usb device ?
Thank you.
Might be the same issue: AndroidStudio USB: EXTRA_PERMISSION_GRANTED returns false - always
Changing PendingIntent.FLAG_IMMUTABLE to PendingIntent.FLAG_MUTABLE helped in my case.

Automatically pairing 2 BlueTooth devices

I know this question has already been asked but It does not work for me. I want to automatically pair 2 devices without having a pairing notification on my device. I followed the instruction here: How to pair Bluetooth device programmatically Android but it does not work. Indeed, I still have a pairing notification.
Here is my code:
IntentFilter filter2 = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
final BroadcastReceiver mReceiver2 = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int pin=intent.getIntExtra("android.bluetooth.device.extra.PAIRING_KEY", 0);
byte[] pinBytes = Integer.toString(pin).getBytes();
device.setPin(pinBytes);
boolean b = device.createBond();
}
}
}
};
registerReceiver(mReceiver2, filter2);

App asks for USB permission on every Phone restart

I'm using an USB-Receiver to handle the Communication with a Temperature Sensor attached via USB to the Phone.
Everything is working fine so far, but if i restart the Phone, the App throws an USB-Permission pop-up directly after restarting, even if there isn't any USB-Device attached to the Phone at that Moment.
Has anyone an Idea of what's causing this strange Problem?
[ EDIT: I'm Sorry, the App isn't asking for USB Permission, the popup asks if i want to Open the app if "this device is connected" but there's obviously no device attached.]
Here is the Code of the USB-Receiver:
//Initial USB Settings Receiver
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
// is usb permission has been granted, try to open a connection
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
// call method to set up device communication
Constants result = mcp2221.open();
if (result != Constants.SUCCESS) {
//nothing by now
} else {
openConnectionToMCP2221();
}
}
}
}
}
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
// close the connection and release all resources
closeAllResources();
// leave a bit of time for the COM thread to close
try {
Thread.sleep(20);
}catch(InterruptedException e){e.printStackTrace();}
mcp2221Comm = null;
Toast.makeText(getApplicationContext(), "Device detached",
Toast.LENGTH_SHORT).show();
}
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
Toast.makeText(getApplicationContext(), "Device attached",
Toast.LENGTH_SHORT).show();
mStopUSBThread=false;
// only try to connect if an MCP2221 is attached
if (device.getVendorId() == MCP2221_VID && device.getProductId() == MCP2221_PID) {
Constants result = mcp2221.open();
switch (result) {
case SUCCESS:
openConnectionToMCP2221();
break;
case CONNECTION_FAILED:
Toast.makeText(getApplicationContext(), "ERROR: connection failed", Toast.LENGTH_SHORT).show();
break;
case NO_USB_PERMISSION:
Toast.makeText(getApplicationContext(), "ERROR: no USB permission", Toast.LENGTH_SHORT).show();
mcp2221.requestUsbPermission(mPermissionIntent);
break;
default:
break;
}
}
}
}
}
};
And here is the onCreate() part:
//USB Connection
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
final IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
registerReceiver(mUsbReceiver, filter);
//Checking if theres a Device already connected
.......
Got it!
It was an
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
</intent-filter>
that was declared in AndroidManifest.xml under <activity>.
I don't fully understand, why it caused this Bug, but removing it kept the functionality of my App while getting rid of the Problem.
Only 'negative' aspect might be, that now the App doesn't ask to open if the Sensor is attached to the phone.

Play Video using connected USB via OTG cable in Android?

I want to ask that there are application available in which user can connect USB to Android via OTG cable device and play the media (specially videos) contained by it.
i have made a Broadcast Receiver to detect the attached USB, i want to read the content also. I am using this code snippet.
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if(device != null){
//
Log.d("1","DEATTCHED-" + device);
}
}
}
//
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//
Log.d("1","ATTACHED-" + device);
}
}
else {
PendingIntent mPermissionIntent;
mPermissionIntent = PendingIntent.getBroadcast(MainActivity.this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_ONE_SHOT);
mUsbManager.requestPermission(device, mPermissionIntent);
}
}
}
//
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//
Log.d("1","PERMISSION-" + device);
}
}
}
}
}
};
I want to make such kind of application.
Do anyone have some idea about that?
After researches of many days i have found the solution
https://github.com/1hakr/AnExplorer
Dividing the video in multiple sub videos may work for you.
What I suggest : instead of saving full video in one temp path, divide that video in multiple sub videos and then replaced AVPlayerItem property of AVPlayer accordingly.
So now functionality is working same as video streaming . :)
You can also convert the CMSampleBuffer that the AVAssetReader returns into a CGImage and then a UIImage and display that in a UIImageView, to render the frames as they are pulled out of the original video file.
There is example code inside the AVFoundation Programming Guide that shows how to do this conversion.

BroadcastReceiver fires after the activity is already created

I want to use a BroadcastReceiver to get permission to communicate with a USB device. I am trying to implement it the same way it is done on android website http://developer.android.com/guide/topics/usb/host.html
It all works, kind of.
But the broadcastReceiver is fireing only after the main activity is created. Which means I am able to communicate with the device only after close the app and open it again (when I don't unregister the broadcastReceiver, when I do I can't communicate at all).
What can be the reason?
My code is like this:
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action))
{
synchronized (this)
{
device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
{
if(device != null)
{
//things I do when the permission is granted
}
}
else
{
devMessage = "permission denied for device ";
}
}
}
}
};
The part of the code where I register it:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext())
{
device = deviceIterator.next();
mUsbManager.requestPermission(device, mPermissionIntent);
}
// ...
if(device!=null)
{
// ...
}
else
{
// ...
}
tv.setText(devMessage);
}
Does anyone know why is this happening, what I might be doing wrong?
You're registering your broadcast receiver in you activity. That means that before you run that activity, you cannot receive broadcasts.
You should probably look at registering a reciever-tag in in you AndroidManifest.xml.
This is the docs for the receiver-tag. This allows you to register receivers without starting your activity.
This part is important:
The <application> element has its own enabled attribute that applies to all application components, including broadcast receivers. The <application> and <receiver> attributes must both be "true" for the broadcast receiver to be enabled. If either is "false", it is disabled; it cannot be instantiated.

Categories

Resources