Как остановить Android запрашивая разрешение, прежде чем разрешить доступ к USB-устройству

19

У меня есть приложение, работающее на планшете Android без имени с ОС ICS 4.0.3, которое управляет USB-устройством через интерфейс режима хоста USB. Файл android.hardware.usb.host.xml находится в / system / etc / permissions, и все прекрасно работает. Кроме...

Когда я запускаю приложение в первый раз после перезагрузки, а затем подключаю USB-устройство, я получаю всплывающее окно с надписью «Разрешить приложению APPNAME доступ к USB-устройству? [] Использовать по умолчанию для этого USB-устройства. Отмена OK» и Я должен нажать ОК, прежде чем он сможет начать использовать устройство.

Мне нужно отключить подтверждение пользователя, чтобы приложение могло сразу же использовать устройство. Как мне это сделать? У меня есть некоторые предложения по использованию генератора нажатий клавиш для имитации нажатия пользователем кнопки на экране, но я предпочел бы избегать такого подхода и настраивать его так, чтобы запрос подтверждения просто не происходил.

Я, вероятно, не могу заставить поставщика сделать собственную сборку ядра для меня, но я смогу получить от них ключ подписи прошивки, чтобы я мог подписать свое приложение как системное приложение, если это поможет.

Одна связанная проблема: установка флажка «Использовать по умолчанию для этого USB-устройства», похоже, не помогает - если я отключу и снова подключу устройство, то я получу запрос подтверждения снова. В этой ситуации я заметил, что номер устройства в / dev / bus / usb / 001 / меняется каждый раз, когда я отключаю и включаю (001, 002, 003 и т. Д.), Что, возможно, объясняет эту конкретную проблему.

kbro
источник
Что произойдет, если вы развернете приложение в / system / app? Вы можете попробовать это с и без подписи системы. Я пишу это как комментарий, потому что (а) я не пробовал, и (б) я не знаю, доступна ли вам эта модель развертывания.
Роб Придхам

Ответы:

10

Этот вопрос и ответ в основном являются дубликатом
/programming//a/15151075/588476.
См. Ссылку выше для примера программы и более подробное обсуждение.

Насколько я знаю, есть два способа получить всплывающее окно разрешения USB:

  1. Запросите разрешение прямо из вашего приложения, используя UsbManager.requestPermission (...)
  2. Зарегистрируйте интент-фильтр на вашем аксессуаре и позвольте системе запрашивать разрешение при подключении устройства

В случае 1 я обнаружил, что флажок во всплывающем окне для запоминания разрешения не имеет никакого эффекта.

Для меня я удалил весь код, связанный с разрешениями, из моего программного обеспечения и просто поместил фильтр намерений в свой манифест. Когда USB-устройство подключено, если ему еще не было предоставлено разрешение, появится окно с разрешением USB. Если пользователь нажимает кнопку «ОК», не устанавливая флажок «Запомнить», то при следующем подключении устройства оно снова появится. Однако, если пользователь установит флажок и нажмет OK, то этот флажок больше не должен отображаться (если только программное обеспечение не удалено, а затем установлено заново).

Я не уверен, есть ли где-то ошибка, связанная с тем, что ваше устройство отображается как / dev / bus / usb / 001, а затем 002 и т. Д. - дайте мне знать, если вы используете фильтр намерений, так как без этого флажок запоминания будет ничего не делать.

Я не знаю ни одного способа, чтобы вы могли вообще избежать всплывающего окна с разрешениями. Я подозреваю, что нет способа сделать это, не копаясь в коде Android, как вы сказали.

Уэйн Урода
источник
1
Вы уверены? Я все еще вижу запрос на разрешение, когда устройство отключено и снова подключено. Это поведение согласуется с документацией на developer.android.com/guide/topics/connectivity/usb/host.html . В разделе «Использование фильтра намерений» написано «Если пользователи принимают, ваше приложение автоматически получает разрешение на доступ к устройству до тех пор, пока оно не будет отключено»
kbro
Я могу поручиться только за Nexus 7, Galaxy S3 и Galaxy Note, на этих устройствах я должен принять разрешение только один раз (устройство Android работает в режиме хоста) - при условии, что я установил флажок, чтобы запомнить решение. Какое устройство / версию андроида вы используете, у меня такое ощущение, что это кастомное / OEM устройство?
Уэйн Урода
Это OEM-7-дюймовый планшет на базе SOM WonderMedia WM8850, работающий под управлением Android 4.0.3.
Кбро
Intent-фильтры работают только для текущего сеанса загрузки. Да, я подключаю USB-устройство к своему телефону, и оно автоматически дает разрешение
user924
7

В дополнение к моему комментарию я изучил основной код Android.

У меня есть возможный ответ, но с не менее чем четырьмя основными оговорками и препятствиями:

  1. Я не пробовал, потому что у меня нет подходящих USB-устройств.
  2. Вам нужно новое разрешение
  3. Разрешение требует, чтобы вы были системным приложением
  4. Код требует доступа к чему-то не в публичном API

Забудьте об этом, если развертываете обычные сторонние приложения!

Первым условием является то, что у вас есть MANAGE_USBразрешение. Это описано здесь .

Однако, в свою очередь, для этого необходимо, чтобы вы подписали системный ключ и установили свое приложение в / system / app.

В любом случае, если вы согласны с этим, вот код:

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

mDevice это устройство из ранее.

uidUID вашего собственного приложения, и вы можете посмотреть его. Примером того, как это сделать, является первый ответ здесь .

Все хорошо? Нет ServiceManager, android.os.ServiceManagerи, следовательно, не является публичным API. В данном примере это ваш способ получить IUsbManagerуслугу (могут быть и другие маршруты). Теперь обойти это выходит за рамки моего ответа; в старые времена ты мог использовать отражение, но я не знаю, сможешь ли ты все еще.

После всех этих махинаций, похоже, вам больше не нужно запрашивать разрешение, и если вы это сделаете, он немедленно вернется без диалога.

Роб Придхам
источник