Сервис HCE и разрешение BIND_NFC_SERVICE
Прежде всего, я довольно новичок в программировании приложений для Android. Мой язык программирования - Java. Я искал решение в Интернете и спрашивал других программистов без решения.
Ситуация: Я разработал приложение, которое использует сервис HCE. Это приложение запускается другим устройством, и данные передаются с помощью команд APDU ISO 7816-4. Все работает как положено, и приложение выбирается с помощью AID.
Проблема: приложение было разработано на NEXUS 4 с работающей Android 5.1.1. К тому времени, когда у меня на столе появились новые телефоны с поддержкой NFC для тестирования приложения. Все они Android 6 или новее. Ни один из них не работает с моим приложением. Похоже, что разрешение BIND_NFC_SERVICE не предоставлено. Поскольку способ обработки разрешений изменился с момента обновления Android 5-6, я реализовал новый метод, упомянутый в разрешениях приложений для запросов разработчиков Android (я также проверил соответствующие посты здесь). В разрешении просто отказано без дополнительной информации. На интерфейсе NFC APDU, пытающийся выбрать приложение по его AID, возвращается с 6999, что означает, что операция не разрешена.
На рутированном телефоне я вижу, что разрешение отклонено, и я попытался предоставить его вручную. Но после каждого запуска приложения оно снова отклоняется, и приложение никогда не сможет его использовать.
Похоже, что сама служба HCE должна запросить разрешение, но как?
Ниже вы можете найти мой AndroidManifest.xml и build.gradle. Я также пытался перейти на более высокий уровень API.
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.XXXXXXXX.hce_tests">
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<uses-feature
android:name="android.hardware.nfc.hce"
android:required="true" />
<uses-permission android:name="android.permission.BIND_NFC_SERVICE"/>
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
</activity>
<service
android:name=".MyHostApduService" android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
</intent-filter>
<meta-data
android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice" />
</service>
<activity android:name=".AutoTuneInterface"></activity>
</application>
</manifest>
build.gradle
android {
compileSdkVersion 23
buildToolsVersion "26.0.2"
defaultConfig {
applicationId "com.example.XXXXXXXX.hce_tests"
minSdkVersion 19
targetSdkVersion 22
versionCode 1
versionName "1.0"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-
core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
implementation project(':GraphView')
}
Спасибо за вашу помощь!
1 ответ
BIND_NFC_SERVICE Разрешение
Вы не должны запрашивать разрешение BIND_NFC_SERVICE
из вашего приложения. Это разрешение зарезервировано для системной службы NFC, и эта служба должна быть единственным приложением, которое имеет такое разрешение.
Вместо этого ваше приложение должно применять это разрешение, когда приложение пытается привязаться к компоненту службы HCE. Вы уже делаете это с
<service android:name=".MyHostApduService"
android:permission="android.permission.BIND_NFC_SERVICE"
Таким образом, Android предотвращает внедрение APDU в вашу службу HCE другими (вредоносными) приложениями, поскольку ни одно (вредоносное) приложение не может привязаться к вашей службе HCE.
Ошибка 6999
Почему Android не обнаруживает вашу службу HCE и возвращает 6999, чтобы указать, что AID не был найден, это более сложный вопрос. Я мог бы придумать несколько причин:
- Ваш сервис явно не помечен как экспортированный (добавьте атрибут
android:exported="true"
к сервисной составляющей). Однако это не должно иметь значения, поскольку служба HCE также объявляет фильтр намерений, который неявно устанавливает экспортируемый атрибут в значение true. - Если ваше приложение помечено как платежное приложение (в apduservice.xml), вам необходимо убедиться, что оно выбрано как платежное приложение ("Нажмите и оплатите" в приложении "Настройки").
- Некоторые устройства, по-видимому, не поддерживают HCE и защищенный элемент параллельно и имеют переключатель для выбора между защищенным элементом и HCE где-то в приложении "Настройки" (возможно, также в настройках "Нажми и плати").