4

I'm trying to figure out why my application does not start communicating with the USB accessory after the phone restarts. If I unplug the cable and plug it back in, the communication resumes. The application is targeted at Android API 19.

At the app install I set it to always be the Home app and when I first connect it to the accessory I check the box to always permit the access to the current accessory.

So when I restart the phone, the app opens up automatically, it goes through the steps of checking for permission (usbmanager.hasPermission) and it actually has the permission without any alert appearing, but the communication is not starting in OpenAccessory method.

Manifest:

        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
        </intent-filter>

        <meta-data
            android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
            android:resource="@xml/accessory_filter"></meta-data>

Comms:

// Init USB Manager
usbmanager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
context.registerReceiver(mUsbReceiver, filter);

// Resume Accessory
if (usbmanager.hasPermission(accessory)) {
                OpenAccessory(accessory);
            }
            else
            {
                synchronized (mUsbReceiver) {
                    if (!mPermissionRequestPending) {
                        Toast.makeText(global_context, "Request USB Permission", Toast.LENGTH_SHORT).show();
                        usbmanager.requestPermission(accessory,
                                mPermissionIntent);
                        mPermissionRequestPending = true;
                    }
                }
            }

// Broadcast Receiver
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action))
            {
                synchronized (this)
                {
                    UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
                    {
                        Toast.makeText(global_context, "Allow USB Permission", Toast.LENGTH_SHORT).show();
                        OpenAccessory(accessory);
                    }
                    else
                    {
                        Toast.makeText(global_context, "Deny USB Permission", Toast.LENGTH_SHORT).show();
                        Log.d("LED", "permission denied for accessory "+ accessory);

                    }
                    mPermissionRequestPending = false;
                }
            }
            else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action))
            {
                DestroyAccessory(true);
                //CloseAccessory();
            }else
            {
                Log.d("LED", "....");
            }
        }
    };

// OpenAccessory
private void OpenAccessory(UsbAccessory accessory)
    {
        filedescriptor = usbmanager.openAccessory(accessory);
        if(filedescriptor != null){
            usbaccessory = accessory;

            FileDescriptor fd = filedescriptor.getFileDescriptor();

            inputstream = new FileInputStream(fd);
            outputstream = new FileOutputStream(fd);
            /*check if any of them are null*/
            if(inputstream == null || outputstream==null){
                return;
            }

            if(READ_ENABLE == false){
                READ_ENABLE = true;
                readThread = new read_thread(inputstream);
                readThread.start();
            }

            // Initialize the serial port here
            SerialComm.getInstance().initPort();
        }
    }
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Macaret
  • 797
  • 9
  • 33

1 Answers1

1

in UsbManager and IntentFilter you use ACTION_USB_ACCESSORY_DETACHED and ACTION_USB_ACCESSORY_ATTACHED events that are triggered when plugging or unplugging the device.

if these events /actions occur the code is executed and the app works

( https://developer.android.com/reference/android/hardware/usb/UsbManager.html )

the problem is now that when the app is started at reboot these events /actions are not triggered and so the code that is linked to them will not be executed

it is not easy to circumvent this because an application gets an instance of the UsbAccessory class only via the ACTION_USB_ACCESSORY_ATTACHED intent :

An instance of this class is sent to the application via the ACTION_USB_ACCESSORY_ATTACHED Intent. The application can then call openAccessory(UsbAccessory) to open a file descriptor for reading and writing data to and from the accessory.

source : https://developer.android.com/reference/android/hardware/usb/UsbAccessory.html

it is not possible for the app to use a class ( the accessory ) if it has no instance of it ...

ralf htp
  • 9,149
  • 4
  • 22
  • 34
  • Actually, the Broadcast Receiver is called with permission to access the accessory and the code follows through the OpenAccessory but the communication is still not restarting. I tried both of your option without any luck. – Macaret Jan 19 '18 at 07:29
  • yes, this is possible. this is one of the security limitation in android. another possibility would be to trigger the action `ACTION_USB_ACCESSORY_ATTACHED` manually, however this seems also not possible, cf https://stackoverflow.com/questions/26654844/can-you-manually-fire-action-battery-low i edit answer .... – ralf htp Jan 19 '18 at 09:05
  • How did u make the UsbAccessory work ? i could not do it – obeid salem Feb 16 '23 at 00:46