web-dev-qa-db-fra.com

contourner la boîte de dialogue de confirmation des autorisations de l'hôte Android

Je veux utiliser Android dans l'industrie,

Je peux me connecter sans problème aux puces Serial Profil et Ftdi USB vers série avec la bibliothèque slickdevlabs.com.

L'application dispose d'un service et démarre au démarrage, connectez-vous au port série USB et effectuez les autres opérations.

mon problème est que le périphérique hôte n'a aucune interaction avec l'utilisateur,

alors quand l'Android demande 

Allow the app "MyAPP" to access the USB device ?
[checkmark]Use by default for this USB device
Cancel            OK

il n'y a personne sur qui cliquer, ok.

même si je coche l'utilisation par défaut ... case à cocher, si je réinsère l'USB ou si je redémarre le périphérique hôte, il me le demandera à nouveau au prochain démarrage.

J'ai couru le service et l'application avec le mode SuperUser, mais aucune différence, il demande à nouveau.

J'ai ajouté un filtre d'intention mais aucune différence, il me le demande à chaque fois.

        <intent-filter>
            <action Android:name="Android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            <action Android:name="Android.hardware.usb.action.USB_DEVICE_DETACHED" />
        </intent-filter>

        <meta-data
            Android:name="Android.hardware.usb.action.USB_DEVICE_ATTACHED"
            Android:resource="@xml/device_filter" />
        <meta-data
            Android:name="Android.hardware.usb.action.USB_DEVICE_DETACHED"
            Android:resource="@xml/device_filter" />

Tout avis, comment le contourner ou le désactiver?

J'ai un accès root et SU.

25
AliRezza

Je sais que c'est un peu tard, mais quand même ...

J'ai eu le même genre de problème et je pense avoir réussi à le résoudre. Il existe un service utilisé en interne par Android qui permet de gérer les périphériques et accessoires USB ..__ Ce service est masqué par les développeurs tiers et n'est pas documenté. Si vous vérifiez le code source de UsbPermissionActivity, vous serez en mesure de comprendre comment ce service s'appelle . Pour appeler le service, l'interface IUsbManager et la classe ServiceManager sont utilisées. Ces deux éléments sont également masqués, vous ne pouvez donc pas les utiliser directement. Mais ce que vous pouvez faire est de créer leurs stubs avec exactement les mêmes noms et dans les espaces de noms correspondants. Vous pourrez ensuite compiler ce code, tandis que l'environnement d'exécution utilisera les éléments réels.

La seule exigence est que votre application doit être une application système - c’est-à-dire qu’elle doit être située dans le répertoire/system/app /. Puisque votre appareil est enraciné, cela ne devrait pas poser de problème.

Vous devrez donc ajouter un package à votre projet: "Android.hardware.usb" et y placer un fichier nommé "IUsbManager.Java" avec le contenu suivant:

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 ) 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;
}

Puis un autre paquet: "Android.os" avec "ServiceManager.Java":

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!" );
    }
}

Notez que les interfaces de ces classes peuvent changer en fonction de la version d'Android. Dans mon cas, la version est 4.0.3 . Donc, si vous avez une autre version d'Android et que ce code ne fonctionne pas, vous devrez vérifier le code source de votre version de système d'exploitation.

Voici un exemple d'utilisation du service pour accorder des autorisations à tous les périphériques FTDI:

import Java.util.HashMap;
import Java.util.Iterator;

import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.content.pm.ApplicationInfo;
import Android.content.pm.PackageManager;
import Android.hardware.usb.IUsbManager;
import Android.hardware.usb.UsbDevice;
import Android.hardware.usb.UsbManager;
import Android.os.IBinder;
import Android.os.ServiceManager;

public class LaunchReceiver extends BroadcastReceiver
{
    public void onReceive( Context context, Intent intent )
    {
        String action = intent.getAction();
        if( action != null && action.equals( Intent.ACTION_BOOT_COMPLETED ) )
        {
            try
            {
                PackageManager pm = context.getPackageManager();
                ApplicationInfo ai = pm.getApplicationInfo( YOUR_APP_PACKAGE_NAMESPACE, 0 );
                if( ai != null )
                {
                    UsbManager manager = (UsbManager) context.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() == 0x0403 )
                            {
                                service.grantDevicePermission( device, ai.uid );
                                service.setDevicePackage( device, YOUR_APP_PACKAGE_NAMESPACE );
                            }
                    }
                }
            }
            catch( Exception e )
            {
                trace( e.toString() );
            }
        }
    }
}

Une dernière chose - vous devrez ajouter l’autorisation suivante à votre manifeste (Lint peut ne pas l’aimer, mais vous pouvez toujours changer le niveau de gravité dans les propriétés de votre projet): 

<uses-permission Android:name="Android.permission.MANAGE_USB" />
24
d_d_t

@d_d_t answer est génial, mais cela ne fonctionne pas avec le nouveau 4.2.2. Utilisez cette interface:

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 {
    private static final Java.lang.String DESCRIPTOR = "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!" );
    }

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

    @Override
    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);
    static final int TRANSACTION_allowUsbDebugging = (Android.os.IBinder.FIRST_CALL_TRANSACTION + 16);
    static final int TRANSACTION_denyUsbDebugging = (Android.os.IBinder.FIRST_CALL_TRANSACTION + 17);
}

/* 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, int userId)
        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, int userId)
        throws Android.os.RemoteException;

/* Clears default preferences and permissions for the package */
public void clearDefaults(Java.lang.String packageName, int userId)
        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;

/*
 * Allow USB debugging from the attached Host. If alwaysAllow is true, add
 * the the public key to list of Host keys that the user has approved.
 */
public void allowUsbDebugging(boolean alwaysAllow,
        Java.lang.String publicKey) throws Android.os.RemoteException;

/* Deny USB debugging from the attached Host */
public void denyUsbDebugging() throws Android.os.RemoteException;
}

Et modifiez le code en ajoutant l'ID utilisateur:

...
service.setDevicePackage( usbDevice, YOUR_APP_PACKAGE_NAMESPACE, ai.uid ); 
....
10
Alvins

Si vous avez la possibilité de compiler le système Android, vous ne pouvez rien faire.

Vous pouvez ajouter 

public void onStart() {
    super.onStart();
    mPermissionGranted = true;

    finish();
}

vers cadres/base/packages/SystemUI/src/com/Android/systemui/usb/UsbPermissionActivity.Java 

pour contourner le popup de confirmation de permission.

5
Lewisou

Android n'est vraiment pas conçu pour supporter ce type d'utilisation hors de la boîte. Personnellement, pour une utilisation non interactive, je serais tenté d’envisager l’utilisation du pilote série USB dans le noyau Linux et de sauter l’API Android. Mais vous devez être en mesure de modifier sérieusement l’installation Android - modifier la configuration du noyau et/ou charger un module, créer des fichiers de périphérique et définir leurs autorisations ou leurs propriétaires, éventuellement ajouter un groupe unix et une autorisation Android pour les applications autorisées. y accéder.

Vous pouvez également consulter la source Android et désactiver la confirmation de l'utilisateur. mais si vous ne disposez pas d'une version Android d'origine pour le périphérique, cela peut s'avérer plus délicat que l'idée de niveau Linux, car adapter Open Source à Android pour s'exécuter sur un périphérique du fournisseur peut être non trivial (à moins que quelqu'un ne propose déjà un -Source build qui est suffisamment fonctionnel pour le périphérique en question)

De manière indicative, l’accès root/su ne s’applique pas aux applications elles-mêmes. Cela signifie simplement qu’une application qui sait exécuter quel que soit l’outil utilisé par votre racine piratée puisse démarrer un programme d’aide fonctionnant en tant que root, mais que l’application ne ne peux pas. L'utilisation de root pour installer l'application sur la partition système peut vous procurer des autorisations Android atypiques, mais vous devez vérifier s'il en existe qui pourraient vous aider à utiliser l'USB.

4
Chris Stratton

Selon la documentation sur les développeurs Android, vous disposez déjà d'une autorisation sur le périphérique USB connecté lorsque votre application est lancée via votre filtre d'intention de manifeste. Peut-être devriez-vous essayer cette approche et écrire un filtre pour correspondre exactement au périphérique que vous souhaitez utiliser, afin d'éviter que d'autres applications souhaitent également communiquer avec le périphérique.

Voir la "Note" sur http://developer.Android.com/guide/topics/connectivity/usb/Host.html#permission-d

2
PieterAelse

Je pense que la liste blanche de l’accessoire que vous utilisez à l’avance sera la meilleure solution ..__ Pour ce faire, vous devez ajouter le fichier Usb_device_manager.xmlà cet emplacement/data/system/ utilisateurs/0
// Notez que 0 est l'ID utilisateur, il le sera probablement si vous n'avez pas ajouté d'utilisateurs dans Android, mais si vous avez modifié cet ID en conséquence.

Voici à quoi devrait ressembler le fichier:

<settings>
<preference package="<PACKAGE NAME OF APP YOU WANT TO START ON CONNECTIONCTION>">
    <usb-accessory manufacturer="<NAME OF MANUFECTURER LIKE ONE REGISTERED IN meta-data in the manifest>" model="<MODEL NAME LIKE ONE REGISTERED IN meta-data in the manifest>" version="<VERSION LIKE ONE REGISTERED IN meta-data in the manifest>" />
</preference>

Pour un forum comme celui-ci http://www.embeddedartists.com/products/app/aoa_kit.php c'est:

 <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<settings>
<preference package="com.embeddedartists.aoa">
    <usb-accessory manufacturer="Embedded Artists AB" model="AOA Board - Basic" version="1.0" />
</preference>

2
PSIXO

Pour y parvenir, notez que cela ne supprime pas la confirmation, mais plutôt de localiser l'emplacement de la variable checkbox et d'utiliser l'équivalent Android de la classe Robot pour le sélectionner, puis sélectionnez OK. Vous pouvez écrire une application qui s’exécute en arrière-plan. Elle pourrait même être appelée par le service de démarrage que vous avez mentionné, spécifiquement à cette fin.

2
cnexus

Lorsque cela est nécessaire pour la première fois, vous pouvez sélectionner "toujours", puis, même si le périphérique Android est mis hors tension et sous tension, votre application a toujours l'autorisation d'accéder à USB2Serial. Juste pour dire, une seule fois confirmer!

0
cantonics

J'ai eu le même problème, le popup de permission apparaît chaque fois que je branche le câble USB, pour le résoudre, je viens d'ajouter le filtre dans le manifeste et le fichier XML pour VID et PID, assurez-vous simplement que vous avez configuré le filtrage des périphériques USB comme suggéré le lien SO ci-dessus ou comme documenté ici, et vous mettez les bons VID et PID. C'était mon problème, je n'ai pas mis le VID et le PID qui correspondent à mon appareil 

0
lotfi Raghib

Je pense que nous pouvons le faire en apportant quelques modifications dans /etc/udev. Nous pourrions ajouter l'ID du fournisseur et l'ID du périphérique dans le fichier 51-Android.rules.

0
user1979609