Flutter и работа с нативным кодом на примере библиотеки для работы с NFC

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Как исправлять недочеты в нативных библиотеках при работе с флаттером на примере NFC

В большинстве случаев при работе с флаттером разработчику никак не приходится взаимодействовать с нативным кодом (Java/Kotlin и ObjectiveC/Swift), потому что инструментарий флаттера довольно богат. Но иногда возникают случаи, когда без этого не обойтись. Самым частым примером является работа с датчиками телефона.

Рассмотрим проблему: представим что вам нужно сделать чтение данных карты с NFC. Вы выбрали плагин, в нашем случае это был nfc_manager 3.1.0, который позволяет это делать, но на android из него не возвращается номер карты, который вам необходим. Что делать? С такой проблемой мы недавно столкнулись и сейчас расскажем как это решается.
Для решения данной проблемы нужно выполнить несколько шагов.
Во-первых необходимо скопировать код библиотеки к себе в проект. Должно получиться так:

Так же небольшой совет: при наличии нескольких таких пакетов лучше вынести их в отдельную папку на том же уровне вложенности и назвать ее, например, packages.

Затем нам необходимо локализовать момент, в котором не происходит считывание номера банковской карты. Для старта считывания из flutter вызывается метод "startSession", который, в свою очередь, вызывает нативный метод "Nfc#startSession". Внутри него все устроено довольно просто:

adapter.enableReaderMode(activity, {
val handle = UUID.randomUUID().toString()
tags[handle] = it
activity.runOnUiThread { channel.invokeMethod("onDiscovered", getTagMap(it).toMutableMap().apply { put("handle", handle) }) }
}, getFlags(call.argument<List<String>>("pollingOptions")!!), null)

Теперь нам необходимо немного модифицировать данный код, чтобы мы могли отправить в flutter номер карты.

Для этого сначала в файл build.gradle добавим импорт соответствующей нативной библиотеки:

implementation 'com.github.devnied.emvnfccard:library:3.0.1'

Затем нам нужно сделать реализацию для интерфейса из этой библиотеки IProvider, который передает команды на карту. Необходимая для нас реализация выглядит так:

class Provider : IProvider {
   private var mTagCom: IsoDep? = null
@Throws(CommunicationException::class)
   override fun transceive(pCommand: ByteArray): ByteArray {
       val response: ByteArray = try {
           // send command to emv card
           mTagCom!!.transceive(pCommand)
       } catch (e: IOException) {
           throw CommunicationException(e.message)
       }
       return response
   }
override fun getAt(): ByteArray {
       // For NFC-A
       return mTagCom!!.historicalBytes
       // For NFC-B
       // return mTagCom.getHiLayerResponse();
   }
fun setmTagCom(mTagCom: IsoDep?) {
       this.mTagCom = mTagCom
   }
}

Затем отредактируем непосредственно сам код перед отправкой данных в flutter в "onDiscovered". Для чтения данных карты нам необходимо добавить выше созданную реализацию интерфейса, а также конфиг и парсер. Код выглядит примерно так:

val provider: IProvider = Provider()
(provider as Provider).setmTagCom(IsoDep.get(it))
val config: EmvTemplate.Config = EmvTemplate.Config()
       .setContactLess(true) // Enable contact less reading (default: true)
       .setReadAllAids(true) // Read all aids in card (default: true)
       .setReadTransactions(true) // Read all transactions (default: true)
       .setReadCplc(false) // Read and extract CPCLC data (default: false)
       .setRemoveDefaultParsers(false) // Remove default parsers for GeldKarte and EmvCard (default: false)
       .setReadAt(true) // Read and extract ATR/ATS and description
val parser = EmvTemplate.Builder() //
       .setProvider(provider) // Define provider
       .setConfig(config) // Define config
       //.setTerminal(terminal) (optional) you can define a custom terminal implementation to create APDU
       .build()

Затем нам необходимо подключиться к карте и считать необходимые для нас данные:

val mIsoDep = IsoDep.get(it)
mIsoDep.connect()
val card = parser.readEmvCard()

И наконец отправим необходимы для нас данные в flutter, добавив к map полученные данные карты:

activity.runOnUiThread {
   channel.invokeMethod("onDiscovered", getTagMap(it).toMutableMap().apply {
       put("handle", handle)
       put("cardNumber", card.cardNumber)
       put("holderFirstName", card.holderFirstname)
       put("holderLastName", card.holderLastname)
       put("type", card.type.getName())
   })
}

Теперь мы можем получать данные карты с NFC.

Источник: https://habr.com/ru/articles/770842/


Интересные статьи

Интересные статьи

В этой статье вы увидите, как сделать генератор ASCII-арта из изображения.ASCII-арт — это метод графического дизайна, который использует компьютеры для презентации и он состоит из изображений, собранн...
Всем привет, читатели Habr! В этой статье я расскажу как ускорить работу и облегчить нам жизнь с помощью VS Code Tasks. Погнали!Мы пишем не только кодЭто правда, разработчики пишут  не только код...
Даты и время являются весьма непростыми объектами: месяца содержат различное число дней; года бывают високосными и нет; существуют различные временнЫе зоны; часы, минуты, дни исполь...
Здесь пылают костры в душах и городахКровь течёт, как вода, всюду ужас и мракБоль и слёзы везде, дальше некуда пастьТак людских страстей ад нам явил свою властьЭтот отрывок из кибер-оперы...
Сегодня в нашей рубрике — компания Тинькофф, которая рушит стереотипы о банковских продуктах и сервисах. Это постоянный участник ежегодных рейтингов ИТ-работодателей, кот...