Сервис 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 где-то в приложении "Настройки" (возможно, также в настройках "Нажми и плати").
Другие вопросы по тегам