Comment empêcher Android de demander la permission avant d'autoriser l'accès au périphérique USB

19

J'ai une application exécutée sur une tablette Android rootée sans nom exécutant ICS 4.0.3 qui contrôle un périphérique USB via l'interface du mode hôte USB. Le fichier android.hardware.usb.host.xml est présent dans / system / etc / permissions et tout fonctionne à merveille. Sauf...

Lorsque j'exécute l'application pour la première fois après un redémarrage puis que je branche le périphérique USB, j'obtiens une fenêtre contextuelle disant "Autoriser l'application APPNAME à accéder au périphérique USB? [] Utiliser par défaut pour ce périphérique USB. Annuler OK" et Je dois appuyer sur OK avant de pouvoir commencer à utiliser l'appareil.

Je dois désactiver la confirmation de l'utilisateur pour que l'application puisse utiliser l'appareil immédiatement. Comment puis-je faire cela? J'ai semblé quelques suggestions sur l'utilisation d'un générateur de touches pour simuler l'utilisateur en appuyant sur le bouton à l'écran, mais je préférerais éviter ce genre d'approche et configurer les choses afin que la demande de confirmation ne se produise tout simplement pas.

Je ne peux probablement pas demander au fournisseur de créer un noyau personnalisé pour moi, mais je devrais pouvoir obtenir la clé de signature du micrologiciel pour que je puisse signer mon application en tant qu'application système, si cela peut aider.

Un problème associé: cocher la case "Utiliser par défaut pour ce périphérique USB" ne semble pas aider - si je débranche et rebranche le périphérique, je reçois à nouveau l'invite de confirmation. J'ai remarqué dans cette situation que le numéro de périphérique dans / dev / bus / usb / 001 / change chaque fois que je débranche et rebranche (001, 002, 003, etc.), ce qui explique peut-être cette problème particulier.

kbro
la source
Que se passe-t-il si vous déployez l'application dans / system / app? Vous pouvez essayer cela avec et sans signature du système. J'écris ceci en tant que commentaire car (a) je ne l'ai pas essayé, et (b) je ne sais pas si ce modèle de déploiement est à votre disposition.
Rob Pridham

Réponses:

10

Cette question et réponse est essentiellement un doublon de
/programming//a/15151075/588476
Voir le lien ci-dessus pour un exemple de programme et une discussion plus approfondie.

Pour autant que je sache, il existe deux façons d'obtenir la fenêtre contextuelle de la permission USB:

  1. Demandez l'autorisation explicitement à votre application en utilisant UsbManager.requestPermission (...)
  2. Enregistrez un filtre d'intention sur votre accessoire et laissez le système demander la permission lorsque l'appareil est connecté

Dans le cas de 1, j'ai constaté que la case à cocher dans la fenêtre contextuelle pour mémoriser l'autorisation n'a aucun effet.

Pour moi, j'ai supprimé tout le code lié aux autorisations de mon logiciel et j'ai simplement mis le filtre d'intention dans mon manifeste. Lorsque le périphérique USB est branché, s'il n'a pas déjà reçu l'autorisation, la boîte d'autorisation USB apparaîtra. Si l'utilisateur clique sur OK sans cocher la case à retenir, la boîte apparaîtra à nouveau la prochaine fois que l'appareil sera connecté. Cependant, si l'utilisateur coche la case et appuie sur OK, la boîte ne doit plus jamais s'afficher (sauf si le logiciel est désinstallé puis réinstallé).

Je ne sais pas s'il y a un bug quelque part lié à votre appareil qui apparaît comme / dev / bus / usb / 001, puis 002 etc - faites-moi savoir si vous utilisez le filtre d'intention, car sans cela la case à cocher souvenir ne fais rien.

Je ne connais aucun moyen d’éviter complètement la fenêtre d’autorisation. Je soupçonne qu'il n'y a aucun moyen de le faire sans creuser dans le code Android comme vous l'avez dit.

Wayne Uroda
la source
1
Êtes-vous sûr? Je vois toujours la demande d'autorisation lorsque l'appareil est débranché et reconnecté. Ce comportement est cohérent avec la documentation dans developer.android.com/guide/topics/connectivity/usb/host.html . La section "Utilisation d'un filtre d'intention" indique "Si les utilisateurs acceptent, votre application est automatiquement autorisée à accéder à l'appareil jusqu'à ce que l'appareil soit déconnecté"
kbro
Je ne peux garantir que le Nexus 7, le Galaxy S3 et le Galaxy Note, sur ces appareils, je n'ai à accepter l'autorisation qu'une seule fois (l'appareil Android fonctionne en mode hôte) - à condition d'activer la case à cocher pour mémoriser la décision. Quel appareil / version d'Android utilisez-vous, j'ai l'impression qu'il s'agit d'un appareil personnalisé / OEM?
Wayne Uroda
Il s'agit d'une tablette OEM de 7 pouces basée sur le WonderMedia WM8850-mid SOM exécutant leur version d'Android 4.0.3.
kbro
Les filtres d'intention ne fonctionnent que pour la session de démarrage en cours. Oui, je branche un périphérique USB sur mon téléphone et il accorde automatiquement l'autorisation
user924
7

Suite à mon commentaire, j'ai jeté un œil au code Android sous-jacent.

J'ai une réponse possible, mais avec pas moins de quatre mises en garde et obstacles majeurs:

  1. Je ne l'ai pas essayé, car je n'ai pas de périphérique USB approprié à portée de main.
  2. Vous avez besoin d'une nouvelle autorisation
  3. L'autorisation nécessite que vous soyez une application système
  4. Le code nécessite l'accès à quelque chose qui n'est pas dans l'API publique

Oubliez cela si vous déployez des applications après-vente ordinaires!

La première condition préalable est que vous ayez l' MANAGE_USBautorisation. Cela est décrit ici .

Cependant, à son tour, les conditions préalables à cela sont que vous vous connectez avec la clé système et que vous installez votre application dans / system / app.

Quoi qu'il en soit, si cela vous convient, voici un code:

   IBinder b = ServiceManager.getService(USB_SERVICE);
   IUsbManager service = IUsbManager.Stub.asInterface(b);
   service.grantDevicePermission(mDevice, uid);

mDevice est l'appareil d'avant.

uidest l'UID de votre propre application et vous pouvez le rechercher. Un exemple de la façon de procéder est la première réponse ici .

Tout bon? No. ServiceManagerest android.os.ServiceManageret n'est donc pas une API publique. C'est, dans cet exemple, votre moyen de mettre la main sur le IUsbManagerservice (il peut y avoir d'autres itinéraires). Maintenant, contourner cela dépasse la portée de ma réponse; Autrefois, vous pouviez utiliser la réflexion, mais je ne sais pas si vous le pouvez toujours.

Après tous ces manigances, il semble que vous n'ayez plus besoin de demander la permission, et si vous le faites, il reviendra immédiatement sans dialogue.

Rob Pridham
la source