bypass android usb host permission confirmation di

2019-02-26 01:08发布

I want to use android in industry,

I can connect to Profilic and Ftdi USB to Serial chips with slickdevlabs.com library without any problem.

The application has a service and it starts on boot,connect to the usb serial port and do the other things.

my problem is that the host device does not have any interaction with user,

so when the android asks

Allow the app "MyAPP" to access the USB device ? [checkmark]Use by default for this USB device Cancel OK there is no person to click on ok.

even when I check the use by default... checkbox,If I reinsert the USB ,or reboot the host device, it asks again on next boot.

and the answer is mentioned in this link : bypass android usb host permission confirmation dialog but the codes are for : "Note that interfaces of these classes may change depending on the version of Android. In my case the version is 4.0.3. So if you have another version of Android and this code doesn't work you will have to check the source code for your particular version of OS."

so i need the same codes for android 5.1 please

2条回答
乱世女痞
2楼-- · 2019-02-26 02:05

Have you tried using an intent-filter in the Manifest as described here: https://developer.android.com/guide/topics/connectivity/usb/host.html#using-intents

I had a similar issue - it seems like if you programmatically request a USB permission, it will ignore the ticked checkbox and ask you every time again.

Edit: If you are having issues because of the service, you might want to read this too: https://stackoverflow.com/a/15151075/3540885

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-02-26 02:10

It's been a while since you asked this... but in case it can help someone here is my answer.

The accepted answer in the initial question states:

So if you have another version of Android and this code doesn't work you will have to check the source code for your particular version of OS.

So you should get the files you need directly from the android source code. You can download the source code relative to your version or browse directly from the repo.

The IUsbManager interface you are searching for is normally under: /frameworks/base/android-branch-name/core/java/android/hardware/usb. As for the Service Manager it can be found under: /frameworks/base/android-branch-name/core/java/android/os/

I didn't post the code since I suppose you're not searching for it anymore after 2 years+ :)

=== EDIT ===

As asked, here is the code. I made it work for version 6.0.0, but I think functions calls are the same as 5.1. To be verified.

First, here is the android project structure you will get: enter image description here

Create the interface IUsbManager.java in android.harware.usb:

package android.hardware.usb;

public interface IUsbManager extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements android.hardware.usb.IUsbManager
    {
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            throw new RuntimeException( "Stub!" );
        }
        /**
         * Cast an IBinder object into an android.hardware.usb.IUsbManager interface,
         * generating a proxy if needed.
         */
        public static android.hardware.usb.IUsbManager asInterface( android.os.IBinder obj )
        {
            throw new RuntimeException( "Stub!" );
        }

        public android.os.IBinder asBinder()
        {
            throw new RuntimeException( "Stub!" );
        }

        public boolean onTransact( int code, android.os.Parcel data, android.os.Parcel reply, int flags ) throws android.os.RemoteException
        {
            throw new RuntimeException( "Stub!" );
        }

        static final int TRANSACTION_getDeviceList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_openDevice = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_getCurrentAccessory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
        static final int TRANSACTION_openAccessory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
        static final int TRANSACTION_setDevicePackage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
        static final int TRANSACTION_setAccessoryPackage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
        static final int TRANSACTION_hasDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
        static final int TRANSACTION_hasAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
        static final int TRANSACTION_requestDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
        static final int TRANSACTION_requestAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
        static final int TRANSACTION_grantDevicePermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);
        static final int TRANSACTION_grantAccessoryPermission = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);
        static final int TRANSACTION_hasDefaults = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12);
        static final int TRANSACTION_clearDefaults = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13);
        static final int TRANSACTION_setCurrentFunction = (android.os.IBinder.FIRST_CALL_TRANSACTION + 14);
        static final int TRANSACTION_setMassStorageBackingFile = (android.os.IBinder.FIRST_CALL_TRANSACTION + 15);
    }

    /* Returns a list of all currently attached USB devices */
    public void getDeviceList( android.os.Bundle devices ) throws android.os.RemoteException;
    /* Returns a file descriptor for communicating with the USB device.
     * The native fd can be passed to usb_device_new() in libusbhost.
     */
    public android.os.ParcelFileDescriptor openDevice( java.lang.String deviceName ) throws android.os.RemoteException;
    /* Returns the currently attached USB accessory */
    public android.hardware.usb.UsbAccessory getCurrentAccessory() throws android.os.RemoteException;
    /* Returns a file descriptor for communicating with the USB accessory.
     * This file descriptor can be used with standard Java file operations.
     */
    public android.os.ParcelFileDescriptor openAccessory( android.hardware.usb.UsbAccessory accessory ) throws android.os.RemoteException;
    /* Sets the default package for a USB device
     * (or clears it if the package name is null)
     */
    public void setDevicePackage(android.hardware.usb.UsbDevice device, java.lang.String packageName, int userId) throws android.os.RemoteException;
    /* Sets the default package for a USB accessory
     * (or clears it if the package name is null)
     */
    public void setAccessoryPackage( android.hardware.usb.UsbAccessory accessory, java.lang.String packageName ) throws android.os.RemoteException;
    /* Returns true if the caller has permission to access the device. */
    public boolean hasDevicePermission(android.hardware.usb.UsbDevice device) throws android.os.RemoteException;
    /* Returns true if the caller has permission to access the accessory. */
    public boolean hasAccessoryPermission( android.hardware.usb.UsbAccessory accessory ) throws android.os.RemoteException;
    /* Requests permission for the given package to access the device.
     * Will display a system dialog to query the user if permission
     * had not already been given.
     */
    public void requestDevicePermission( android.hardware.usb.UsbDevice device, java.lang.String packageName, android.app.PendingIntent pi ) throws android.os.RemoteException;
    /* Requests permission for the given package to access the accessory.
     * Will display a system dialog to query the user if permission
     * had not already been given. Result is returned via pi.
     */
    public void requestAccessoryPermission( android.hardware.usb.UsbAccessory accessory, java.lang.String packageName, android.app.PendingIntent pi ) throws android.os.RemoteException;
    /* Grants permission for the given UID to access the device */
    public void grantDevicePermission( android.hardware.usb.UsbDevice device, int uid ) throws android.os.RemoteException;
    /* Grants permission for the given UID to access the accessory */
    public void grantAccessoryPermission( android.hardware.usb.UsbAccessory accessory, int uid ) throws android.os.RemoteException;
    /* Returns true if the USB manager has default preferences or permissions for the package */
    public boolean hasDefaults( java.lang.String packageName ) throws android.os.RemoteException;
    /* Clears default preferences and permissions for the package */
    public void clearDefaults( java.lang.String packageName ) throws android.os.RemoteException;
    /* Sets the current USB function. */
    public void setCurrentFunction( java.lang.String function, boolean makeDefault ) throws android.os.RemoteException;
    /* Sets the file path for USB mass storage backing file. */
    public void setMassStorageBackingFile( java.lang.String path ) throws android.os.RemoteException;


}

Then create the java class ServiceManager.java in android.os:

package android.os;

import java.util.Map;

public final class ServiceManager
{
    public static IBinder getService( String name )
    {
        throw new RuntimeException( "Stub!" );
    }

    /**
     * Place a new @a service called @a name into the service
     * manager.
     *
     * @param name the name of the new service
     * @param service the service object
     */
    public static void addService( String name, IBinder service )
    {
        throw new RuntimeException( "Stub!" );
    }

    /**
     * Retrieve an existing service called @a name from the
     * service manager.  Non-blocking.
     */
    public static IBinder checkService( String name )
    {
        throw new RuntimeException( "Stub!" );
    }

    public static String[] listServices() throws RemoteException
    {
        throw new RuntimeException( "Stub!" );
    }

    /**
     * This is only intended to be called when the process is first being brought
     * up and bound by the activity manager. There is only one thread in the process
     * at that time, so no locking is done.
     *
     * @param cache the cache of service references
     * @hide
     */
    public static void initServiceCache( Map<String, IBinder> cache )
    {
        throw new RuntimeException( "Stub!" );
    }
}

Once this is done, don't forget to add the android.permission.MANAGE_USB in you AndroidManifest.

Then you can use those function calls:

/**
 * Verify if the application is a system app and has MANAGE_USB permission
 * before granting the USB permission for you specific USB devices
 */
private void manageUSBPermissions() {
    if ((this.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
        Log.i(TAG,"This is a system application");
        if (getApplicationContext().checkCallingOrSelfPermission("android.permission.MANAGE_USB") == PackageManager.PERMISSION_GRANTED) {
            Log.i(TAG,"I have android.permission.MANAGE_USB");
            grantUsbPermissions();
        } else {
            Log.i(TAG,"I do not have android.permission.MANAGE_USB");
        }
    } else {
        Log.i(TAG,"This is not a system application");
    }
}

/**
 * This is to avoid the android usb host permission confirmation dialog
 * The application need to be a system app and have MANAGE_USB permission for it to work
 */
private void grantUsbPermissions() {
    try {
        PackageManager pm = getPackageManager();
        ApplicationInfo ai = pm.getApplicationInfo( "com.your.package", 0 );
        if( ai != null ) {
            UsbManager manager = (UsbManager) getSystemService( Context.USB_SERVICE );
            IBinder b = ServiceManager.getService( Context.USB_SERVICE );
            IUsbManager service = IUsbManager.Stub.asInterface( b );

            HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
            Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
            while( deviceIterator.hasNext() ) {
                UsbDevice device = deviceIterator.next();
                if ( device.getVendorId() == 0x1234 ) {
                    service.grantDevicePermission( device, ai.uid );
                    service.setDevicePackage( device, "com.your.package", ai.uid );
                }
            }
        }
    }
    catch ( Exception e ) {
        Log.e(TAG, "Error granting USB permissions: " + e);
    }
}

There's a check on whether your application is a system application and if it has the correct permission, otherwise it would not work.

Also be aware that your vendor id is not in hexadecimal but in decimal.

查看更多
登录 后发表回答