Общая информация
Эта статья описывает интеграцию устройств Рутокен в мобильные приложения для платформы Android без использования приложения "Панель управления Рутокен".
Пример приложения, работающего по этой схеме: https://github.com/AktivCo/rutoken-demoshift-android/tree/local-pcsc-scheme
Поддерживаемые версии Android
Android 7.0 (API Level 24) и выше.
Настройка зависимостей в проекте
Для встраивания необходимо добавить в зависимости библиотеку rtpcscbridge:
implementation 'ru.rutoken.rtpcscbridge:rtpcscbridge:1.0.0'
implementation("ru.rutoken.rtpcscbridge:rtpcscbridge:1.0.0")
Библиотека доступна в репозитории Maven Central.
Инициализация библиотеки
Точкой входа встраивания является класс ru.rutoken.rtpcscbridge.RtPcscBridge, который необходим для инициализации библиотеки rtpcscbridge.
Для каждого процесса приложения, в котором происходит взаимодействие с устройствами Рутокен, необходимо вызвать статический метод setAppContext и передать ему в качестве параметра Android application context.
Типичное место вызова метода – внутри onCreate() класса-наследника Application.
public class App extends Application { @Override public void onCreate() { super.onCreate(); RtPcscBridge.setAppContext(this); } }
Режимы работы библиотеки
С библиотекой можно работать в двух режимах:
В данном режиме осуществляется явный вызов методов инициализации и финализации встраивания, а также управление считыванием устройств Рутокен с NFC.
Это обеспечивает полный контроль над поведением библиотеки со стороны приложения, например, при необходимости активации встраивания только для некоторых Activity приложения.
В данном режиме методы ручного API вызываются автоматически на определенных этапах жизненного цикла приложения.
Библиотека позволяет опционально включить автоматическую обработку NFC-устройств Рутокен для всех Activity, реализующих OnNewIntentProvider.
Остальные устройства Рутокен обрабатываются во всех Activity приложения.
Ручной API
Для работы с библиотекой в Ручном режиме используется интерфейс ru.rutoken.rttransport.RtTransport. Его инстанс можно получить с помощью метода RtPcscBridge.getTransport().
Рекомендуется следующий порядок вызова API:
Порядок | Метод | Описание | Место вызова |
---|---|---|---|
1 | RtTransport.initialize(context) | Инициализирует встраивание. Библиотека начинает отслеживать подключение и отключение устройств Рутокен (кроме подключений по NFC) и позволяет настроить дальнейшую работу с NFC | Рекомендуется:
|
2 | RtTransport.enableNfcForegroundDispatch(activity) | Включает NFC foreground dispatching для данной Activity | ТОЛЬКО из Main потока в методе Activity.onResume. |
3 | RtTransport.handleNfcIntent(intent) | Обрабатывает NFC интент, полученный при прикладывании устройств Рутокен. Интенты от устройств других производителей не обрабатываются. Применяется для дальнейшей установки соединения с Рутокен | При получении каждого NFC интента. Например. |
4 | RtTransport.disableNfcForegroundDispatch(activity) | Выключает NFC foreground dispatching для данной Activity | ТОЛЬКО из Main потока в методе Activity.onPause |
5 | RtTransport.finalize(context) | Завершает работу встраивания | Рекомендуется:
|
Автоматический API
Для работы с библиотекой в Автоматическом режиме используется интерфейс ru.rutoken.rttransport.RtTransportExtension. Его инстанс можно получить из метода RtPcscBridge.getTransportExtension().
Для включения Автоматического режима необходимо вызвать метод attachToLifecycle. Рекомендуемое место вызова: в методе onCreate() внутри класса-наследника Application.
Пример.
Инициализация библиотеки и включение автоматического режима:
public class App extends Application { @Override public void onCreate() { super.onCreate(); RtPcscBridge.setAppContext(this); RtPcscBridge.getTransportExtension().attachToLifecycle(this, true); } }
В параметры метода attachToLifecycle дополнительно можно передать флаг useAutoNfcHandling для включения/выключения автоматической обработки устройств Рутокен с NFC.
По умолчанию значение флага – true.
Автоматическая обработка устройств Рутокен с NFC осуществляется только для тех Activity, которые реализуют OnNewIntentProvider.
Если базовый класс Activity уже реализует интерфейс OnNewIntentProvider (как в случае с ComponentActivity), то явная реализация интерфейса не обязательна.
Для отключения Автоматического режима применяется метод RtTransportExtension.detachFromLifecycle(app).
Если взаимодействие с устройством Рутокен осуществляется на протяжении всей работы приложения, то данный метод можно не применять.
Автоматический API и жизненный цикл приложения
Жизненный цикл автоматического API непосредственно связан с жизненными циклами всех Activity приложения.
Вызов метода RtTransportExtension.attachToLifecycle(app) инициирует следующие операции внутри библиотеки:
- добавление подписчика ru.rutoken.rttransport.RtTransportProcessLifecycleObserver на жизненный цикл процесса приложения.
- добавление ru.rutoken.rttransport.RtTransportNfcLifecycleCallbacks в качестве Activity Lifecycle callbacks для данного приложения (если параметр useAutoNfcHandling = true и NFC адаптер физически существует).
Зависимость RtTransport от жизненного цикла Activity
Зависимость поведения RtTransport от жизненного цикла Activity при автоматическом режиме встраивания и включенном автоуправлении NFC приведена ниже:
После перехода первой Activity в состояние Started (событие Lifecycle.Event.ON_START) вызывается инициализация RtTransport.
После перехода последней Activity в состояние Stopped (событие Lifecycle.Event.ON_STOP) вызывается финализация RtTransport. Вызов финализации осуществляется с задержкой, что исключает лишнюю переинициализацию при:
- смене конфигурации (переворот экрана);
- быстром переключении между приложениями;
- быстром переключении на Home screen и обратно.
При включенном автоуправлении NFC дополнительно автоматически вызываются методы:
Метод | Описание | Условия вызова |
---|---|---|
RtTransport.enableNfcForegroundDispatch(activity) | Включает NFC foreground dispatching для данной Activity | Если метод Activity.onResume() переопределен – при super.onResume() Иначе – неявно во время перехода в состояние Resumed |
RtTransport.handleNfcIntent(intent) | Обрабатывает NFC интент, полученный при прикладывании устройств Рутокен. Интенты от устройств других производителей не обрабатываются. Применяется для дальнейшей установки соединения с Рутокен | Если метод Activity.onNewIntent(intent) переопределен – при super.onNewIntent(intent) Иначе – автоматически во время получения NFC интента |
RtTransport.disableNfcForegroundDispatch(activity) | Выключает NFC foreground dispatching для данной Activity | Если метод Activity.onPause() переопределен – при super.onPause() Иначе – неявно во время перехода в состояние Paused |
Когда Activity находится в стадии Resumed, библиотека реагирует на события о состоянии NFC адаптера через внутренний BroadcastReceiver:
- при переходе адаптера в состояние NfcAdapter.STATE_ON, вызывается enableNfcForegroundDispatch;
- при переходе адаптера в состояние NfcAdapter.STATE_OFF, вызывается disableNfcForegroundDispatch.
Отслеживание подключения (отключения) устройств Рутокен
Встраивание позволяет отслеживать подключение и отключение устройств Рутокен с помощью интерфейса ru.rutoken.rttransport.RtTransport.PcscReaderObserver.
Отслеживание подключения (отключения) устройств Рутокен может быть полезно при работе через КриптоПро CSP.
Отслеживание устройств доступно в любом режиме использования встраивания.
Для старта отслеживания (в любой момент работы со встраиванием) используются интерфейс ru.rutoken.rttransport.RtTransport и метод addPcscReaderObserver.
Допускается добавление нескольких подписчиков на события. При добавлении подписчика ему поступят события обо всех подключенных на данный момент к устройству Рутокенах. Для каждого Рутокена будет вызываться метод RtTransport.PcscReaderObserver.onReaderAdded(reader).
Для отключения отслеживания используется метод RtTransport.removePcscReaderObserver.
Если подписка производится внутри Activity или другого компонента, который может быть создан несколько раз за время жизни приложения, то необходимо своевременно отписываться во избежание утечки памяти.
Пример.
Если подписка была произведена внутри Activity.onStart(), то отписаться следует внутри Activity.onStop().
Требования для встраивания в зависимости от физического интерфейса устройства Рутокен
USB
Для работы с USB-устройствами Рутокен в Ручном режиме необходимо вызвать методы RtTransport.initialize(context) и RtTransport.finalize(context).
Для работы в Автоматическом режиме необходимо использовать метод attachToLifecycle(application).
При каждом подключении Рутокена система запрашивает у пользователя разрешение на использование этого USB-устройства.
Выданное пользователем разрешение действует до переподключения Рутокена.
Дополнительных runtime permission приложению получать не требуется.
Bluetooth
Для работы с Bluetooth-устройствами Рутокен в Ручном режиме необходимо вызвать методы RtTransport.initialize(context) и RtTransport.finalize(context).
Для работы в Автоматическом режиме необходимо использовать метод attachToLifecycle(application).
На Android версии 12 и выше требуется самостоятельно запросить permission BLUETOOTH_CONNECT для всех режимов встраивания.
NFC
Для работы с NFC-устройствами Рутокен в Ручном режиме необходимо вызвать все методы раздела "Ручной API".
Для работы в Автоматическом режиме необходимо передать флаг useAutoNfcHandling=true в метод RtTransportExtension.attachToLifecycle(application, boolean) или использовать метод attachToLifecycle(application)(по умолчанию включает авто-обработку NFC).
Дополнительных runtime permission приложению получать не требуется.
Работа встраивания в многопроцессных приложениях
Корректность работы встраивания не гарантируется при одновременном использовании устройств Рутокен несколькими процессами приложения.
Логирование
Уровень логирования в библиотеках по умолчанию – ERROR.
Для отладки можно расширить логирование до уровня DEBUG, который содержит информацию об:
- автоматической инициализации встраивания;
- автоматической финализации встраивания;
- обнаружении токенов по различным физическим интерфейсам.
Для расширения логирования необходимо вызвать RtPcscBridge.enableDebugLogs() перед началом работы со встраиванием, а именно – до вызова RtPcscBridge.setAppContext.
Конфигурация R8/ProGuard
При включении обфускации приложения для корректной работы библиотеки необходимо прописать следующие правила в proguard-rules.pro:
-dontwarn ru.rutoken.spi.SpiDevice -dontwarn ru.rutoken.spi.SpiManager -keep class ru.rutoken.rtcore.network.methodhandler.** { *; } -keep class ru.rutoken.rtpcscbridge.** { *; } -keep class * extends com.google.protobuf.GeneratedMessageLite { *; }
При использовании расширенного логирования (уровень DEBUG), для сохранения читаемости логов, необходимо прописать следующие правила в proguard-rules.pro:
-dontwarn ru.rutoken.spi.SpiDevice -dontwarn ru.rutoken.spi.SpiManager -keep class ru.rutoken.rttransport.** { *; } -keep class ru.rutoken.rtcore.** { *; } -keep class ru.rutoken.rtpcscbridge.** { *; } -keep class * extends com.google.protobuf.GeneratedMessageLite { *; }