Разрешение отказа: доступ к сервису ComponentInfo {...} из pid = -1

Я пытаюсь использовать службу распознавания активности Google. Несколько дней назад все работало как шарм, т.е. Я мог подключиться к службе, чтобы получить информацию о деятельности. Но сегодня я обнаружил, что больше не могу получать. Посмотрев на журнал, я обнаружил эту ошибку:

 05-15 21:19:27.196: W/ActivityManager(765): Permission Denial: Accessing service
 ComponentInfo{edu.umich.si.inteco.captureprobe/edu.umich.si.inteco.captureprobe.
 contextmanager.ActivityRecognitionService} from pid=-1, uid=10220 that is not exported   
 from uid 10223

Я перезагрузил телефон, а затем снова работал. Однако после повторной установки приложения снова появилась та же проблема. Может ли кто-нибудь указать, что такое "настоящая" проблема? Это что-то связано с "pid = -1"? У меня есть разрешение в файле манифеста

<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>

Я искал ответы на Google, но большинство проблем заключается в том, что они не размещали разрешения в файле манифеста. Мне это кажется другой проблемой... Может ли кто-нибудь мне помочь? Спасибо!

UPDATE: Проблема всегда может быть решена путем перезагрузки телефона. Однако он всегда появляется, когда я удаляю приложение и переустанавливаю его через Eclipse. Согласованная, но странная модель (по крайней мере, для меня). Мне интересно, помнит ли телефон приложение и останавливает его для доступа к сервису Google Play после его удаления (или по какой-то причине служба Google Play просто не позволяет моему приложению получить к нему доступ). Любые идеи?

Ответ 1

Я понял решение. Причина связана с комбинацией двух вещей:

  • Переустановка создает новый другой uid одного и того же приложения (обратите внимание, что при переустановке я имел в виду удалить приложение с телефона, а затем использовать Eclipse для переустановки).

  • По умолчанию в теге службы значение "экспортировано" равно false, как описано здесь

Независимо от того, могут ли компоненты других приложений вызывать службу или взаимодействовать с ней - "истина", если они могут, и "ложь", если нет. Когда значение "ложно", только компоненты одного приложения или приложений с одним и тем же идентификатором пользователя могут запустить службу или привязать ее к ней. Значение по умолчанию зависит от того, содержит ли служба фильтры намерений. Отсутствие каких-либо фильтров означает, что его можно вызвать только путем указания его точного имени класса. Это означает, что служба предназначена только для внутреннего использования приложения (так как другие не знают имя класса). Поэтому в этом случае значением по умолчанию является "false". С другой стороны, наличие по меньшей мере одного фильтра подразумевает, что служба предназначена для внешнего использования, поэтому значение по умолчанию "true" .

Итак, я решил проблему, просто установив флаг в значение "true" . (пример кода распознавания активности Google использует значение "false" вместо "true" .)

     <service
        android:name="edu.umich.si.inteco.captureprobe.contextmanager.ActivityRecognitionService"
        android:enabled="true"
        android:exported="true"
        >
    </service>

Интересно, что тот же код работает на Android 4.3 или ниже. Я протестировал свой код на четырех разных телефонах с другой версией Android, и проблема удаления/переустановки произошла только на телефоне Android 4.4. Поэтому, почему я был озадачен этой проблемой. Почему этого не случилось раньше? В любом случае, если вы столкнетесь с одной и той же проблемой (то есть одно и то же приложение не сможет использовать службу после ее переустановки), отметьте флажок "экспортированный".

Ответ 2

Это не относится к распознаванию активности; это, по-видимому, улучшение безопасности в 4.4, PendingIntents зарегистрированы в системе, и лучшим решением является отмена текущего ожидающего намерения (используя PendingIntent.FLAG_CANCEL_CURRENT).

https://code.google.com/p/android/issues/detail?id=61850