В этом документе описаны основные задачи NFC, которые вы выполняете в Android. В нем объясняется, как отправлять и получать данные NFC в форме сообщений NDEF, и описываются API-интерфейсы платформы Android, которые поддерживают эти функции. Более сложные темы, включая обсуждение работы с данными, не относящимися к NDEF, см. в разделе Advanced NFC .
Чтение данных NDEF из тега NFC обрабатывается системой диспетчеризации тегов , которая анализирует обнаруженные теги NFC, соответствующим образом классифицирует данные и запускает приложение, заинтересованное в классифицированных данных. Приложение, которое хочет обрабатывать отсканированную метку NFC, может объявить фильтр намерений и запросить обработку данных.
Система отправки тегов
Устройства на базе Android обычно ищут метки NFC, когда экран разблокирован, если только NFC не отключен в меню настроек устройства. Когда устройство под управлением Android обнаруживает метку NFC, желательно, чтобы наиболее подходящее действие обрабатывало намерение, не спрашивая пользователя, какое приложение использовать. Поскольку устройства сканируют метки NFC на очень небольшом расстоянии, вполне вероятно, что если пользователям придется выбирать действие вручную, им придется отодвинуть устройство от метки и разорвать соединение. Вам следует разработать свою деятельность так, чтобы она обрабатывала только те NFC-теги, которые важны для вашей деятельности, чтобы предотвратить появление средства выбора активности.
Чтобы помочь вам в достижении этой цели, Android предоставляет специальную систему отправки тегов, которая анализирует отсканированные теги NFC, анализирует их и пытается найти приложения, которым интересны отсканированные данные. Это делается путем:
- Анализ тега NFC и определение типа MIME или URI, который идентифицирует полезные данные в теге.
- Инкапсуляция типа MIME или URI и полезных данных в намерение. Эти первые два шага описаны в разделе «Как теги NFC сопоставляются с типами MIME и URI» .
- Запускает действие на основе намерения. Это описано в разделе «Как теги NFC отправляются в приложения» .
Как теги NFC сопоставляются с типами MIME и URI
Прежде чем приступить к написанию приложений NFC, важно понять различные типы тегов NFC, как система отправки тегов анализирует теги NFC и какую специальную работу выполняет система отправки тегов при обнаружении сообщения NDEF. В тегах NFC используется широкий спектр технологий, и данные могут быть записаны разными способами. Android имеет наибольшую поддержку стандарта NDEF, определенного NFC Forum .
Данные NDEF инкапсулируются внутри сообщения ( NdefMessage
), которое содержит одну или несколько записей ( NdefRecord
). Каждая запись NDEF должна иметь правильный формат в соответствии со спецификацией типа записи, которую вы хотите создать. Android также поддерживает другие типы тегов, не содержащие данных NDEF, с которыми вы можете работать, используя классы в пакете android.nfc.tech
. Дополнительную информацию об этих технологиях см. в разделе «Расширенный NFC» . Работа с другими типами тегов предполагает написание собственного стека протоколов для взаимодействия с тегами, поэтому мы рекомендуем по возможности использовать NDEF для упрощения разработки и максимальной поддержки устройств на базе Android.
Примечание. Чтобы загрузить полные спецификации NDEF, перейдите на сайт «Спецификации и документы приложений NFC Forum» и ознакомьтесь с примерами создания записей NDEF в разделе «Создание общих типов записей NDEF».
Теперь, когда вы имеете некоторый опыт работы с тегами NFC, в следующих разделах более подробно описывается, как Android обрабатывает теги в формате NDEF. Когда устройство под управлением Android сканирует тег NFC, содержащий данные в формате NDEF, оно анализирует сообщение и пытается определить тип MIME данных или идентифицирующий URI. Для этого система считывает первую NdefRecord
внутри NdefMessage
, чтобы определить, как интерпретировать все сообщение NDEF (сообщение NDEF может иметь несколько записей NDEF). В правильно сформированном сообщении NDEF первая NdefRecord
содержит следующие поля:
- 3-битный TNF (формат имени типа)
- Указывает, как интерпретировать поле типа переменной длины. Допустимые значения описаны в Таблице 1 .
- Тип переменной длины
- Описывает тип записи. При использовании
TNF_WELL_KNOWN
используйте это поле для указания определения типа записи (RTD). Действительные значения RTD описаны в Таблице 2 . - Идентификатор переменной длины
- Уникальный идентификатор записи. Это поле используется нечасто, но если вам нужно однозначно идентифицировать тег, вы можете создать для него идентификатор.
- Полезная нагрузка переменной длины
- Фактические полезные данные, которые вы хотите прочитать или записать. Сообщение NDEF может содержать несколько записей NDEF, поэтому не предполагайте, что вся полезная нагрузка находится в первой записи NDEF сообщения NDEF.
Система отправки тегов использует поля TNF и type, чтобы попытаться сопоставить тип MIME или URI с сообщением NDEF. В случае успеха он инкапсулирует эту информацию внутри намерения ACTION_NDEF_DISCOVERED
вместе с фактической полезной нагрузкой. Однако бывают случаи, когда система диспетчеризации тегов не может определить тип данных на основе первой записи NDEF. Это происходит, когда данные NDEF не могут быть сопоставлены с типом MIME или URI или когда тег NFC изначально не содержит данных NDEF. В таких случаях объект Tag
, содержащий информацию о технологиях тега и полезной нагрузке, вместо этого инкапсулируется внутри намерения ACTION_TECH_DISCOVERED
.
В таблице 1 описано, как система диспетчеризации тегов сопоставляет поля TNF и типа с типами MIME или URI. Он также описывает, какие TNF нельзя сопоставить с типом MIME или URI. В этих случаях система отправки тегов возвращается к ACTION_TECH_DISCOVERED
.
Например, если система диспетчеризации тегов обнаруживает запись типа TNF_ABSOLUTE_URI
, она сопоставляет поле типа переменной длины этой записи с URI. Система отправки тегов инкапсулирует этот URI в поле данных намерения ACTION_NDEF_DISCOVERED
вместе с другой информацией о теге, например полезной нагрузкой. С другой стороны, если он встречает запись типа TNF_UNKNOWN
, он вместо этого создает намерение, которое инкапсулирует технологии тега.
Таблица 1. Поддерживаемые TNF и их сопоставления
Тип Формат имени (TNF) | Картирование |
---|---|
TNF_ABSOLUTE_URI | URI на основе поля типа. | TNF_EMPTY | Возвращается к ACTION_TECH_DISCOVERED . | TNF_EXTERNAL_TYPE | URI на основе URN в поле типа. URN кодируется в поле типа NDEF в сокращенной форме: <domain_name>:<service_name> . Android сопоставляет это с URI в форме: vnd.android.nfc://ext/ <domain_name>:<service_name> . | TNF_MIME_MEDIA | Тип MIME на основе поля типа. | TNF_UNCHANGED | Недопустимо в первой записи, поэтому возвращается к ACTION_TECH_DISCOVERED . | TNF_UNKNOWN | Возвращается к ACTION_TECH_DISCOVERED . | TNF_WELL_KNOWN | Тип MIME или URI в зависимости от определения типа записи (RTD), которое вы установили в поле типа. См. Таблицу 2 для получения дополнительной информации о доступных RTD и их сопоставлениях. |
Таблица 2. Поддерживаемые RTD для TNF_WELL_KNOWN и их сопоставления
Определение типа записи (RTD) | Картирование |
---|---|
RTD_ALTERNATIVE_CARRIER | Возвращается к ACTION_TECH_DISCOVERED . | RTD_HANDOVER_CARRIER | Возвращается к ACTION_TECH_DISCOVERED . | RTD_HANDOVER_REQUEST | Возвращается к ACTION_TECH_DISCOVERED . | RTD_HANDOVER_SELECT | Возвращается к ACTION_TECH_DISCOVERED . | RTD_SMART_POSTER | URI на основе анализа полезной нагрузки. | RTD_TEXT | MIME-тип text/plain . | RTD_URI | URI на основе полезной нагрузки. |
Как теги NFC передаются приложениям
Когда система диспетчеризации тегов завершает создание намерения, которое инкапсулирует тег NFC и его идентификационную информацию, она отправляет намерение заинтересованному приложению, которое фильтрует это намерение. Если с намерением могут справиться несколько приложений, отображается окно выбора действия, позволяющее пользователю выбрать действие. Система отправки тегов определяет три намерения, которые перечислены в порядке от высшего к низшему приоритету:
-
ACTION_NDEF_DISCOVERED
: это намерение используется для запуска действия, когда тег, содержащий полезную нагрузку NDEF, сканируется и имеет распознанный тип. Это намерение с наивысшим приоритетом, и система отправки тегов пытается запустить действие с этим намерением раньше, чем с любым другим намерением, когда это возможно.Примечание. Начиная с Android 16, сканирование тегов NFC, в которых хранятся URL-ссылки (т. е. схема URI — «htttps://» или «http://»), активирует намерение
ACTION_VIEW
вместо намеренияACTION_NDEF_DISCOVERED
. -
ACTION_TECH_DISCOVERED
: если не зарегистрировано никаких действий для обработки намеренияACTION_NDEF_DISCOVERED
, система диспетчеризации тегов пытается запустить приложение с этим намерением. Это намерение также запускается напрямую (без предварительного запускаACTION_NDEF_DISCOVERED
), если сканируемый тег содержит данные NDEF, которые невозможно сопоставить с типом MIME или URI, или если тег не содержит данных NDEF, но относится к известной технологии тегов. -
ACTION_TAG_DISCOVERED
: это намерение запускается, если никакие действия не обрабатывают намеренияACTION_NDEF_DISCOVERED
илиACTION_TECH_DISCOVERED
.
Основной принцип работы системы отправки тегов заключается в следующем:
- Попробуйте запустить Activity с намерением, которое было создано системой диспетчеризации тегов при разборе тега NFC (либо
ACTION_NDEF_DISCOVERED
, либоACTION_TECH_DISCOVERED
). - Если никакие действия не фильтруются для этого намерения, попробуйте запустить действие со следующим намерением с наименьшим приоритетом (
ACTION_TECH_DISCOVERED
илиACTION_TAG_DISCOVERED
), пока приложение не отфильтрует намерение или пока система отправки тегов не перепробует все возможные намерения. - Если ни одно из приложений не фильтрует ни одно из намерений, ничего не делайте.

По возможности работайте с сообщениями NDEF и намерением ACTION_NDEF_DISCOVERED
, поскольку оно является наиболее конкретным из трех. Это намерение позволяет вам запустить приложение в более подходящее время, чем два других намерения, предоставляя пользователю лучший опыт.
Запросить доступ NFC в манифесте Android
Прежде чем вы сможете получить доступ к оборудованию NFC устройства и правильно обработать намерения NFC, объявите эти элементы в файле AndroidManifest.xml
:
- Элемент NFC
<uses-permission>
для доступа к оборудованию NFC:<uses-permission android:name="android.permission.NFC" />
- Минимальная версия SDK, которую может поддерживать ваше приложение. Уровень API 9 поддерживает только ограниченную отправку тегов через
ACTION_TAG_DISCOVERED
и предоставляет доступ к сообщениям NDEF только через дополнительную опциюEXTRA_NDEF_MESSAGES
. Никакие другие свойства тега или операции ввода-вывода недоступны. Уровень API 10 включает в себя комплексную поддержку чтения и записи, а также активную отправку NDEF, а уровень API 14 предоставляет дополнительные удобные методы для создания записей NDEF.<uses-sdk android:minSdkVersion="10"/>
- Элемент
uses-feature
, чтобы ваше приложение отображалось в Google Play только для устройств, оснащенных оборудованием NFC:<uses-feature android:name="android.hardware.nfc" android:required="true" />
Если ваше приложение использует функциональность NFC, но эта функциональность не имеет решающего значения для вашего приложения, вы можете опустить элемент
uses-feature
и проверить доступность NFC во время выполнения, проверив, имеет лиgetDefaultAdapter()
значениеnull
.
Фильтр по намерениям NFC
Чтобы запустить приложение при сканировании тега NFC, который вы хотите обработать, ваше приложение может фильтровать одно, два или все три намерения NFC в манифесте Android. Однако обычно вы хотите отфильтровать намерение ACTION_NDEF_DISCOVERED
, чтобы максимально контролировать время запуска вашего приложения. Намерение ACTION_TECH_DISCOVERED
является запасным вариантом для ACTION_NDEF_DISCOVERED
, когда никакие приложения не фильтруют ACTION_NDEF_DISCOVERED
или когда полезные данные не являются NDEF. Фильтрация для ACTION_TAG_DISCOVERED
обычно является слишком общей категорией, чтобы ее можно было фильтровать. Многие приложения будут фильтровать ACTION_NDEF_DISCOVERED
или ACTION_TECH_DISCOVERED
перед ACTION_TAG_DISCOVERED
, поэтому вероятность запуска вашего приложения мала. ACTION_TAG_DISCOVERED
доступен только в крайнем случае для приложений, подлежащих фильтрации, в тех случаях, когда не установлены другие приложения для обработки намерения ACTION_NDEF_DISCOVERED
или ACTION_TECH_DISCOVERED
.
Поскольку развертывание тегов NFC различается и во многих случаях находится вне вашего контроля, это не всегда возможно, поэтому при необходимости вы можете вернуться к двум другим намерениям. Если у вас есть контроль над типами записываемых тегов и данных, рекомендуется использовать NDEF для форматирования тегов. В следующих разделах описывается, как фильтровать намерения каждого типа.
ACTION_NDEF_DISCOVERED
Чтобы фильтровать намерения ACTION_NDEF_DISCOVERED
, объявите фильтр намерений вместе с типом данных, которые вы хотите фильтровать. В следующем примере фильтруются намерения ACTION_NDEF_DISCOVERED
с помощью MIME-типа text/plain
:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter>
В следующем примере фильтруется URI в форме https://developer.android.com/index.html
.
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
ACTION_TECH_DISCOVERED
Если ваша деятельность фильтрует намерение ACTION_TECH_DISCOVERED
, вы должны создать файл ресурсов XML, в котором указаны технологии, которые поддерживает ваша деятельность, в наборе tech-list
. Ваша деятельность считается совпадением, если набор tech-list
является подмножеством технологий, поддерживаемых тегом, который вы можете получить, вызвав getTechList()
.
Например, если сканируемый тег поддерживает MifareClassic, NdefFormatable и NfcA, в вашем наборе tech-list
должны быть указаны все три, две или одна технология (и ничего больше), чтобы ваша деятельность была сопоставлена.
В следующем примере определяются все технологии. Вы должны удалить те, которые не поддерживаются вашим тегом NFC. Сохраните этот файл (вы можете назвать его как угодно) в папке <project-root>/res/xml
.
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.NfcF</tech> <tech>android.nfc.tech.NfcV</tech> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> <tech>android.nfc.tech.MifareClassic</tech> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
Вы также можете указать несколько наборов tech-list
. Каждый из наборов tech-list
рассматривается независимо, и ваша деятельность считается совпадением, если какой-либо отдельный набор tech-list
является подмножеством технологий, возвращаемых getTechList()
. Это обеспечивает семантику AND
и OR
для сопоставления технологий. Следующий пример соответствует тегам, которые могут поддерживать технологии NfcA и Ndef или технологии NfcB и Ndef:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> </resources>
В файле AndroidManifest.xml
укажите только что созданный файл ресурсов в элементе <meta-data>
внутри элемента <activity>
, как показано в следующем примере:
<activity> ... <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>
Дополнительные сведения о работе с технологиями тегов и намерении ACTION_TECH_DISCOVERED
см. в разделе «Работа с поддерживаемыми технологиями тегов» в документе Advanced NFC.
ACTION_TAG_DISCOVERED
Чтобы отфильтровать ACTION_TAG_DISCOVERED
, используйте следующий фильтр намерений:
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
ACTION_VIEW
Начиная с Android 16, сканирование тегов NFC, в которых хранятся URL-ссылки, активирует намерение ACTION_VIEW
. Чтобы отфильтровать ACTION_VIEW
, обратитесь к this
. Используйте Android app links
, чтобы открыть приложение по URL-адресу.
Получить информацию из намерений
Если действие начинается из-за намерения NFC, вы можете получить информацию о отсканированной метке NFC из намерения. В зависимости от сканируемого тега намерения могут содержать следующие дополнительные элементы:
-
EXTRA_TAG
(обязательно): объектTag
, представляющий сканируемый тег. -
EXTRA_NDEF_MESSAGES
(необязательно): массив сообщений NDEF, проанализированных из тега. Это дополнение является обязательным для целейACTION_NDEF_DISCOVERED
. -
EXTRA_ID
(необязательно): низкоуровневый идентификатор тега.
Чтобы получить эти дополнительные возможности, проверьте, было ли ваше действие запущено с одним из намерений NFC, чтобы убедиться, что тег был отсканирован, а затем получите дополнительные возможности из намерения. В следующем примере проверяется намерение ACTION_NDEF_DISCOVERED
и получаются сообщения NDEF из дополнительного намерения.
Котлин
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) ... if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) { intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages -> val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage } // Process the messages array. ... } } }
Ява
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); ... if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMessages != null) { NdefMessage[] messages = new NdefMessage[rawMessages.length]; for (int i = 0; i < rawMessages.length; i++) { messages[i] = (NdefMessage) rawMessages[i]; } // Process the messages array. ... } } }
Альтернативно вы можете получить объект Tag
из намерения, который будет содержать полезную нагрузку и позволит вам перечислить технологии тега:
Котлин
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Ява
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Создание общих типов записей NDEF.
В этом разделе описывается, как создавать общие типы записей NDEF, которые помогут вам при записи в теги NFC. Начиная с Android 4.0 (уровень API 14), доступен метод createUri()
который помогает автоматически создавать записи URI. Начиная с Android 4.1 (уровень API 16), доступны функции createExternal()
и createMime()
которые помогут вам создавать записи MIME и NDEF внешнего типа. По возможности используйте эти вспомогательные методы, чтобы избежать ошибок при создании записей NDEF вручную.
В этом разделе также описывается, как создать соответствующий фильтр намерений для записи. Все эти примеры записей NDEF должны находиться в первой записи NDEF сообщения NDEF, которое вы записываете в тег.
TNF_ABSOLUTE_URI
Примечание. Мы рекомендуем использовать тип RTD_URI
вместо TNF_ABSOLUTE_URI
, поскольку он более эффективен.
Вы можете создать запись TNF_ABSOLUTE_URI
NDEF следующим образом:
Котлин
val uriRecord = ByteArray(0).let { emptyByteArray -> NdefRecord( TNF_ABSOLUTE_URI, "https://developer.android.com/index.html".toByteArray(Charset.forName("US-ASCII")), emptyByteArray, emptyByteArray ) }
Ява
NdefRecord uriRecord = new NdefRecord( NdefRecord.TNF_ABSOLUTE_URI , "https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")), new byte[0], new byte[0]);
Фильтр намерений для предыдущей записи NDEF будет выглядеть следующим образом:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
TNF_MIME_MEDIA
Запись TNF_MIME_MEDIA
NDEF можно создать следующими способами:
Используя метод createMime()
:
Котлин
val mimeRecord = NdefRecord.createMime( "application/vnd.com.example.android.beam", "Beam me up, Android".toByteArray(Charset.forName("US-ASCII")) )
Ява
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam", "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
Создание NdefRecord
вручную:
Котлин
val mimeRecord = Charset.forName("US-ASCII").let { usAscii -> NdefRecord( NdefRecord.TNF_MIME_MEDIA, "application/vnd.com.example.android.beam".toByteArray(usAscii), ByteArray(0), "Beam me up, Android!".toByteArray(usAscii) ) }
Ява
NdefRecord mimeRecord = new NdefRecord( NdefRecord.TNF_MIME_MEDIA , "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")), new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
Фильтр намерений для предыдущей записи NDEF будет выглядеть следующим образом:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/vnd.com.example.android.beam" /> </intent-filter>
TNF_WELL_KNOWN с RTD_TEXT
Вы можете создать запись TNF_WELL_KNOWN
NDEF следующим образом:
Котлин
fun createTextRecord(payload: String, locale: Locale, encodeInUtf8: Boolean): NdefRecord { val langBytes = locale.language.toByteArray(Charset.forName("US-ASCII")) val utfEncoding = if (encodeInUtf8) Charset.forName("UTF-8") else Charset.forName("UTF-16") val textBytes = payload.toByteArray(utfEncoding) val utfBit: Int = if (encodeInUtf8) 0 else 1 shl 7 val status = (utfBit + langBytes.size).toChar() val data = ByteArray(1 + langBytes.size + textBytes.size) data[0] = status.toByte() System.arraycopy(langBytes, 0, data, 1, langBytes.size) System.arraycopy(textBytes, 0, data, 1 + langBytes.size, textBytes.size) return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), data) }
Ява
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) { byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); byte[] textBytes = payload.getBytes(utfEncoding); int utfBit = encodeInUtf8 ? 0 : (1 << 7); char status = (char) (utfBit + langBytes.length); byte[] data = new byte[1 + langBytes.length + textBytes.length]; data[0] = (byte) status; System.arraycopy(langBytes, 0, data, 1, langBytes.length); System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); return record; }
Фильтр намерений для предыдущей записи NDEF будет выглядеть следующим образом:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter>
TNF_WELL_KNOWN с RTD_URI
Запись TNF_WELL_KNOWN
NDEF можно создать следующими способами:
Используя метод createUri(String)
:
Котлин
val rtdUriRecord1 = NdefRecord.createUri("https://example.com")
Ява
NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");
Используя метод createUri(Uri)
:
Котлин
val rtdUriRecord2 = Uri.parse("https://example.com").let { uri -> NdefRecord.createUri(uri) }
Ява
Uri uri = Uri.parse("https://example.com"); NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
Создание NdefRecord
вручную:
Котлин
val uriField = "example.com".toByteArray(Charset.forName("US-ASCII")) val payload = ByteArray(uriField.size + 1) //add 1 for the URI Prefix payload [0] = 0x01 //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.size) //appends URI to payload val rtdUriRecord = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, ByteArray(0), payload)
Ява
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII")); byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix payload[0] = 0x01; //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.length); //appends URI to payload NdefRecord rtdUriRecord = new NdefRecord( NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
Фильтр намерений для предыдущей записи NDEF будет выглядеть следующим образом:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="example.com" android:pathPrefix="" /> </intent-filter>
TNF_EXTERNAL_TYPE
Запись TNF_EXTERNAL_TYPE
NDEF можно создать следующими способами:
Используя метод createExternal()
:
Котлин
var payload: ByteArray //assign to your data val domain = "com.example" //usually your app's package name val type = "externalType" val extRecord = NdefRecord.createExternal(domain, type, payload)
Ява
byte[] payload; //assign to your data String domain = "com.example"; //usually your app's package name String type = "externalType"; NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
Создание NdefRecord
вручную:
Котлин
var payload: ByteArray ... val extRecord = NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".toByteArray(Charset.forName("US-ASCII")), ByteArray(0), payload )
Ява
byte[] payload; ... NdefRecord extRecord = new NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".getBytes(Charset.forName("US-ASCII")), new byte[0], payload);
Фильтр намерений для предыдущей записи NDEF будет выглядеть следующим образом:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="vnd.android.nfc" android:host="ext" android:pathPrefix="/com.example:externalType"/> </intent-filter>
Используйте TNF_EXTERNAL_TYPE
для более общего развертывания тегов NFC, чтобы лучше поддерживать устройства как под управлением Android, так и без него.
Примечание . URN для TNF_EXTERNAL_TYPE
имеют канонический формат: urn:nfc:ext:example.com:externalType
, однако спецификация NFC Forum RTD заявляет, что часть urn:nfc:ext:
URN должна быть исключена из записи NDEF. Таким образом, все, что вам нужно указать, — это домен ( example.com
в примере) и тип ( externalType
в примере), разделенные двоеточием. При отправке TNF_EXTERNAL_TYPE
Android преобразует urn:nfc:ext:example.com:externalType
в URI vnd.android.nfc://ext/example.com:externalType
, который и объявляет фильтр намерений в примере.
Записи приложений Android
Запись приложения Android (AAR), представленная в Android 4.0 (уровень API 14), обеспечивает большую уверенность в том, что ваше приложение запускается при сканировании метки NFC. AAR содержит имя пакета приложения, встроенное в запись NDEF. Вы можете добавить AAR к любой записи NDEF вашего сообщения NDEF, поскольку Android ищет AAR во всем сообщении NDEF. Если он находит AAR, он запускает приложение на основе имени пакета внутри AAR. Если приложение отсутствует на устройстве, запускается Google Play для его загрузки.
AAR полезны, если вы хотите запретить другим приложениям фильтровать те же цели и потенциально обрабатывать определенные развернутые вами теги. AAR поддерживаются только на уровне приложения из-за ограничения имени пакета, а не на уровне активности, как при фильтрации намерений. Если вы хотите обработать намерение на уровне активности, используйте фильтры намерений .
Если тег содержит AAR, система отправки тегов осуществляет отправку следующим образом:
- Попробуйте запустить действие, используя фильтр намерений, как обычно. Если действие, соответствующее намерению, также соответствует AAR, запустите действие.
- Если действие, которое фильтрует намерение, не соответствует AAR, если несколько действий могут обработать намерение или если ни одно действие не обрабатывает намерение, запустите приложение, указанное в AAR.
- Если ни одно приложение не может запуститься с AAR, перейдите в Google Play, чтобы загрузить приложение на основе AAR.
Примечание. Вы можете переопределить AAR и систему отправки намерений с помощью системы отправки на переднем плане , которая позволяет активности на переднем плане иметь приоритет при обнаружении метки NFC. При использовании этого метода действие должно быть на переднем плане, чтобы переопределить AAR и систему отправки намерений.
Если вы по-прежнему хотите фильтровать сканированные теги, не содержащие AAR, вы можете объявить фильтры намерений обычными. Это полезно, если ваше приложение заинтересовано в других тегах, не содержащих AAR. Например, возможно, вы хотите гарантировать, что ваше приложение обрабатывает собственные теги, которые вы развертываете, а также общие теги, развернутые третьими лицами. Имейте в виду, что AAR специфичны для устройств Android 4.0 или более поздних версий, поэтому при развертывании тегов вы, скорее всего, захотите использовать комбинацию AAR и типов/URI MIME для поддержки самого широкого спектра устройств. Кроме того, при развертывании тегов NFC подумайте о том, как вы хотите записать теги NFC, чтобы обеспечить поддержку большинства устройств (под управлением Android и других устройств). Это можно сделать, определив относительно уникальный тип MIME или URI, чтобы приложениям было легче их различать.
Android предоставляет простой API для создания AAR — createApplicationRecord()
. Все, что вам нужно сделать, это встроить AAR в любое место вашего NdefMessage
. Вы не хотите использовать первую запись вашего NdefMessage
, если только AAR не является единственной записью в NdefMessage
. Это связано с тем, что система Android проверяет первую запись NdefMessage
, чтобы определить тип MIME или URI тега, который используется для создания намерения приложений фильтровать. Следующий код показывает, как создать AAR:
Котлин
val msg = NdefMessage( arrayOf( ..., NdefRecord.createApplicationRecord("com.example.android.beam") ) )
Ява
NdefMessage msg = new NdefMessage( new NdefRecord[] { ..., NdefRecord.createApplicationRecord("com.example.android.beam")} ); )
Список разрешенных приложений для сканирования тегов NFC
Начиная с Android 16, пользователи получают уведомление, когда приложение получает первое намерение NFC сканировать теги NFC. Пользователю предоставляется возможность запретить приложению больше сканировать теги NFC в уведомлении.
- Приложения могут проверить, разрешил ли пользователь приложению сканировать теги NFC, используя
NfcAdapter.isTagIntentAllowed()
. - Приложения могут предложить пользователю снова разрешить сканирование тегов NFC, отправив намерение
ACTION_CHANGE_TAG_INTENT_PREFERENCE
.
Примечание. Список разрешенных приложений для сканирования меток NFC доступен в разделе Settings > Apps > Special app access > Launch via NFC
.
В этом документе описаны основные задачи NFC, которые вы выполняете в Android. В нем объясняется, как отправлять и получать данные NFC в форме сообщений NDEF, и описываются API-интерфейсы платформы Android, которые поддерживают эти функции. Более сложные темы, включая обсуждение работы с данными, не относящимися к NDEF, см. в разделе Advanced NFC .
Чтение данных NDEF из тега NFC обрабатывается системой диспетчеризации тегов , которая анализирует обнаруженные теги NFC, соответствующим образом классифицирует данные и запускает приложение, заинтересованное в классифицированных данных. Приложение, которое хочет обрабатывать отсканированную метку NFC, может объявить фильтр намерений и запросить обработку данных.
Система отправки тегов
Устройства на базе Android обычно ищут метки NFC, когда экран разблокирован, если только NFC не отключен в меню настроек устройства. Когда устройство под управлением Android обнаруживает метку NFC, желательно, чтобы наиболее подходящее действие обрабатывало намерение, не спрашивая пользователя, какое приложение использовать. Поскольку устройства сканируют метки NFC на очень небольшом расстоянии, вполне вероятно, что если пользователям придется выбирать действие вручную, им придется отодвинуть устройство от метки и разорвать соединение. Вам следует разработать свою деятельность так, чтобы она обрабатывала только те NFC-теги, которые важны для вашей деятельности, чтобы предотвратить появление средства выбора активности.
Чтобы помочь вам в достижении этой цели, Android предоставляет специальную систему отправки тегов, которая анализирует отсканированные теги NFC, анализирует их и пытается найти приложения, которым интересны отсканированные данные. Это делается путем:
- Анализ тега NFC и определение типа MIME или URI, который идентифицирует полезные данные в теге.
- Инкапсуляция типа MIME или URI и полезных данных в намерение. Эти первые два шага описаны в разделе «Как теги NFC сопоставляются с типами MIME и URI» .
- Запускает действие на основе намерения. Это описано в разделе «Как теги NFC отправляются в приложения» .
Как теги NFC сопоставляются с типами MIME и URI
Прежде чем приступить к написанию приложений NFC, важно понять различные типы тегов NFC, как система отправки тегов анализирует теги NFC и какую специальную работу выполняет система отправки тегов при обнаружении сообщения NDEF. В тегах NFC используется широкий спектр технологий, и данные могут быть записаны разными способами. Android имеет наибольшую поддержку стандарта NDEF, определенного NFC Forum .
Данные NDEF инкапсулируются внутри сообщения ( NdefMessage
), которое содержит одну или несколько записей ( NdefRecord
). Каждая запись NDEF должна иметь правильный формат в соответствии со спецификацией типа записи, которую вы хотите создать. Android также поддерживает другие типы тегов, не содержащие данных NDEF, с которыми вы можете работать, используя классы в пакете android.nfc.tech
. Дополнительную информацию об этих технологиях см. в разделе «Расширенный NFC» . Работа с другими типами тегов предполагает написание собственного стека протоколов для взаимодействия с тегами, поэтому мы рекомендуем по возможности использовать NDEF для упрощения разработки и максимальной поддержки устройств на базе Android.
Примечание. Чтобы загрузить полные спецификации NDEF, перейдите на сайт «Спецификации и документы приложений NFC Forum» и ознакомьтесь с примерами создания записей NDEF в разделе «Создание общих типов записей NDEF».
Теперь, когда вы имеете некоторый опыт работы с тегами NFC, в следующих разделах более подробно описывается, как Android обрабатывает теги в формате NDEF. Когда устройство под управлением Android сканирует тег NFC, содержащий данные в формате NDEF, оно анализирует сообщение и пытается определить тип MIME данных или идентифицирующий URI. Для этого система считывает первую NdefRecord
внутри NdefMessage
, чтобы определить, как интерпретировать все сообщение NDEF (сообщение NDEF может иметь несколько записей NDEF). В правильно сформированном сообщении NDEF первая NdefRecord
содержит следующие поля:
- 3-битный TNF (формат имени типа)
- Указывает, как интерпретировать поле типа переменной длины. Допустимые значения описаны в Таблице 1 .
- Тип переменной длины
- Описывает тип записи. При использовании
TNF_WELL_KNOWN
используйте это поле для указания определения типа записи (RTD). Действительные значения RTD описаны в Таблице 2 . - Идентификатор переменной длины
- Уникальный идентификатор записи. Это поле используется нечасто, но если вам нужно однозначно идентифицировать тег, вы можете создать для него идентификатор.
- Полезная нагрузка переменной длины
- Фактические полезные данные, которые вы хотите прочитать или записать. Сообщение NDEF может содержать несколько записей NDEF, поэтому не предполагайте, что вся полезная нагрузка находится в первой записи NDEF сообщения NDEF.
Система отправки тегов использует поля TNF и type, чтобы попытаться сопоставить тип MIME или URI с сообщением NDEF. В случае успеха он инкапсулирует эту информацию внутри намерения ACTION_NDEF_DISCOVERED
вместе с фактической полезной нагрузкой. Однако бывают случаи, когда система диспетчеризации тегов не может определить тип данных на основе первой записи NDEF. Это происходит, когда данные NDEF не могут быть сопоставлены с типом MIME или URI или когда тег NFC изначально не содержит данных NDEF. В таких случаях объект Tag
, содержащий информацию о технологиях тега и полезной нагрузке, вместо этого инкапсулируется внутри намерения ACTION_TECH_DISCOVERED
.
В таблице 1 описано, как система диспетчеризации тегов сопоставляет поля TNF и типа с типами MIME или URI. Он также описывает, какие TNF нельзя сопоставить с типом MIME или URI. В этих случаях система отправки тегов возвращается к ACTION_TECH_DISCOVERED
.
Например, если система диспетчеризации тегов обнаруживает запись типа TNF_ABSOLUTE_URI
, она сопоставляет поле типа переменной длины этой записи с URI. Система диспетчеризации тегов инкапсулирует этот URI в поле данных намерения ACTION_NDEF_DISCOVERED
вместе с другой информацией о теге, например полезной нагрузкой. С другой стороны, если он встречает запись типа TNF_UNKNOWN
, он вместо этого создает намерение, которое инкапсулирует технологии тега.
Таблица 1. Поддерживаемые TNF и их сопоставления
Тип Формат имени (TNF) | Картирование |
---|---|
TNF_ABSOLUTE_URI | URI на основе поля типа. | TNF_EMPTY | Возвращается к ACTION_TECH_DISCOVERED . | TNF_EXTERNAL_TYPE | URI на основе URN в поле типа. URN кодируется в поле типа NDEF в сокращенной форме: <domain_name>:<service_name> . Android сопоставляет это с URI в форме: vnd.android.nfc://ext/ <domain_name>:<service_name> . | TNF_MIME_MEDIA | Тип MIME на основе поля типа. | TNF_UNCHANGED | Недопустимо в первой записи, поэтому возвращается к ACTION_TECH_DISCOVERED . | TNF_UNKNOWN | Возвращается к ACTION_TECH_DISCOVERED . | TNF_WELL_KNOWN | Тип MIME или URI в зависимости от определения типа записи (RTD), которое вы установили в поле типа. См. Таблицу 2 для получения дополнительной информации о доступных RTD и их сопоставлениях. |
Таблица 2. Поддерживаемые RTD для TNF_WELL_KNOWN и их сопоставления
Определение типа записи (RTD) | Картирование |
---|---|
RTD_ALTERNATIVE_CARRIER | Возвращается к ACTION_TECH_DISCOVERED . | RTD_HANDOVER_CARRIER | Возвращается к ACTION_TECH_DISCOVERED . | RTD_HANDOVER_REQUEST | Возвращается к ACTION_TECH_DISCOVERED . | RTD_HANDOVER_SELECT | Возвращается к ACTION_TECH_DISCOVERED . | RTD_SMART_POSTER | URI на основе анализа полезной нагрузки. | RTD_TEXT | MIME-тип text/plain . | RTD_URI | URI на основе полезной нагрузки. |
Как теги NFC передаются приложениям
Когда система диспетчеризации тегов завершает создание намерения, которое инкапсулирует тег NFC и его идентификационную информацию, она отправляет намерение заинтересованному приложению, которое фильтрует это намерение. Если с намерением могут справиться несколько приложений, отображается окно выбора действия, позволяющее пользователю выбрать действие. Система отправки тегов определяет три намерения, которые перечислены в порядке от высшего к низшему приоритету:
-
ACTION_NDEF_DISCOVERED
: это намерение используется для запуска действия, когда тег, содержащий полезную нагрузку NDEF, сканируется и имеет распознанный тип. Это намерение с наивысшим приоритетом, и система отправки тегов пытается запустить действие с этим намерением раньше, чем с любым другим намерением, когда это возможно.Примечание. Начиная с Android 16, сканирование тегов NFC, в которых хранятся URL-ссылки (т. е. схема URI — «htttps://» или «http://»), активирует намерение
ACTION_VIEW
вместо намеренияACTION_NDEF_DISCOVERED
. -
ACTION_TECH_DISCOVERED
: если не зарегистрировано никаких действий для обработки намеренияACTION_NDEF_DISCOVERED
, система диспетчеризации тегов пытается запустить приложение с этим намерением. Это намерение также запускается напрямую (без предварительного запускаACTION_NDEF_DISCOVERED
), если сканируемый тег содержит данные NDEF, которые невозможно сопоставить с типом MIME или URI, или если тег не содержит данных NDEF, но относится к известной технологии тегов. -
ACTION_TAG_DISCOVERED
: это намерение запускается, если никакие действия не обрабатывают намеренияACTION_NDEF_DISCOVERED
илиACTION_TECH_DISCOVERED
.
Основной принцип работы системы отправки тегов заключается в следующем:
- Попробуйте запустить Activity с намерением, которое было создано системой диспетчеризации тегов при разборе тега NFC (либо
ACTION_NDEF_DISCOVERED
, либоACTION_TECH_DISCOVERED
). - Если никакие действия не фильтруются для этого намерения, попробуйте запустить действие со следующим намерением с наименьшим приоритетом (
ACTION_TECH_DISCOVERED
илиACTION_TAG_DISCOVERED
), пока приложение не отфильтрует намерение или пока система отправки тегов не перепробует все возможные намерения. - Если ни одно из приложений не фильтрует ни одно из намерений, ничего не делайте.

По возможности работайте с сообщениями NDEF и намерением ACTION_NDEF_DISCOVERED
, поскольку оно является наиболее конкретным из трех. Это намерение позволяет вам запустить приложение в более подходящее время, чем два других намерения, предоставляя пользователю лучший опыт.
Запросить доступ NFC в манифесте Android
Прежде чем вы сможете получить доступ к оборудованию NFC устройства и правильно обработать намерения NFC, объявите эти элементы в файле AndroidManifest.xml
:
- Элемент NFC
<uses-permission>
для доступа к оборудованию NFC:<uses-permission android:name="android.permission.NFC" />
- Минимальная версия SDK, которую может поддерживать ваше приложение. Уровень API 9 поддерживает только ограниченную отправку тегов через
ACTION_TAG_DISCOVERED
и предоставляет доступ к сообщениям NDEF только через дополнительную опциюEXTRA_NDEF_MESSAGES
. Никаких других свойств тега или операций ввода -вывода не доступны. API Уровень 10 включает в себя всестороннюю поддержку читателей/писателей, а также толкание на переднем плане NDEF, а API -уровень 14 предоставляет дополнительные методы удобства для создания записей NDEF.<uses-sdk android:minSdkVersion="10"/>
- Элемент
uses-feature
, чтобы ваше приложение отображалось в Google Play только для устройств, которые имеют оборудование NFC:<uses-feature android:name="android.hardware.nfc" android:required="true" />
Если ваше приложение использует функциональность NFC, но эта функциональность не имеет решающей степени для вашего приложения, вы можете опустить элемент
uses-feature
и проверить наличие NFC во время выполнения, проверив, является лиgetDefaultAdapter()
null
.
Фильтр для NFC намерения
Чтобы запустить ваше приложение, когда тег NFC, с которым вы хотите обработать, отсканируется, ваше приложение может фильтровать для одного, двух или всех трех из намерений NFC в манифесте Android. Тем не менее, вы обычно хотите отфильтровать для намерения ACTION_NDEF_DISCOVERED
для наибольшего управления, когда ваше приложение запускается. Намерение ACTION_TECH_DISCOVERED
- это отступление для ACTION_NDEF_DISCOVERED
, когда приложения не фильтруют для ACTION_NDEF_DISCOVERED
или когда полезная нагрузка не является NDEF. Фильтрация для ACTION_TAG_DISCOVERED
, как правило, слишком общая категория для фильтрации. Многие приложения будут отфильтровать для ACTION_NDEF_DISCOVERED
или ACTION_TECH_DISCOVERED
до ACTION_TAG_DISCOVERED
, поэтому ваше приложение имеет низкую вероятность запуска. ACTION_TAG_DISCOVERED
доступен только в качестве последней среды для приложений для фильтрации в тех случаях, когда не установлено никакие другие приложения для обработки намерения ACTION_NDEF_DISCOVERED
или ACTION_TECH_DISCOVERED
.
Поскольку развертывание тегов NFC варьируется и много раз не под вашим контролем, это не всегда возможно, поэтому вы можете отступить на два других намерения, когда это необходимо. Если у вас есть контроль над типами тегов и написанных данных, рекомендуется использовать NDEF для форматирования ваших тегов. В следующих разделах описывается, как фильтровать для каждого типа намерения.
Action_ndef_discovered
Чтобы отфильтровать для ACTION_NDEF_DISCOVERED
ints, объявьте фильтр намерений вместе с типом данных, для которых вы хотите отфильтровать. Следующий пример фильтров для ACTION_NDEF_DISCOVERED
intents с типом text/plain
:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter>
Следующий пример фильтров для URI в форме https://developer.android.com/index.html
.
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
Action_tech_discovered
Если ваша деятельность фильтрует для намерения ACTION_TECH_DISCOVERED
, вы должны создать файл ресурса XML, который определяет технологии, которые ваша деятельность поддерживает в наборе tech-list
. Ваша деятельность считается совпадением, если набор tech-list
является подмножеством технологий, которые поддерживаются тегом, которые вы можете получить, позвонив getTechList()
.
Например, если сканированный тег поддерживает MifareClassic, Ndefformatable и NFCA, ваш набор tech-list
должен указать все три, две или одну из технологий (и ничего другого), чтобы соответствовать вашей деятельности.
Следующий образец определяет все технологии. Вы должны удалить те, которые не поддерживаются вашим тегом NFC. Сохраните этот файл (вы можете назвать его все, что пожелаете) в папке <project-root>/res/xml
.
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.NfcF</tech> <tech>android.nfc.tech.NfcV</tech> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> <tech>android.nfc.tech.MifareClassic</tech> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
Вы также можете указать несколько наборов tech-list
. Каждый из наборов tech-list
считается независимо, и ваша деятельность считается совпадением, если какой-либо отдельный набор tech-list
является подмножеством технологий, которые возвращаются getTechList()
. Это обеспечивает AND
OR
семантику для соответствующих технологий. Следующий пример соответствует тегам, которые могут поддерживать технологии NFCA и NDEF или могут поддерживать технологии NFCB и NDEF:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> </resources>
В вашем файле AndroidManifest.xml
укажите только файл ресурса, который вы только что создали в элементе <meta-data>
внутри элемента <activity>
, как в следующем примере:
<activity> ... <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>
Для получения дополнительной информации о работе с Tag Technologies и намерением ACTION_TECH_DISCOVERED
см. В работе с поддерживаемыми технологиями тегов в расширенном документе NFC.
Action_tag_discovered
Для фильтрации для ACTION_TAG_DISCOVERED
Используйте следующий фильтр намерения:
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
Action_view
Запуск Android 16, сканирование тегов NFC, которые хранят ссылки на URL, запустит намерение ACTION_VIEW
. Чтобы фильтровать для ACTION_VIEW
См. this
. Используйте Android app links
, чтобы открыть ваше приложение для URL.
Получить информацию из намерений
Если деятельность начинается из -за намерения NFC, вы можете получить информацию о отсканированном теге NFC из намерения. Намерения могут содержать следующие дополнения в зависимости от отсканирования тега:
-
EXTRA_TAG
(требуется): объектTag
, представляющий отсканированный тег. -
EXTRA_NDEF_MESSAGES
(необязательно): массив сообщений ndef, проанализированного из тега. Это дополнительное обязательное наACTION_NDEF_DISCOVERED
ints. -
EXTRA_ID
(необязательно): идентификатор низкого уровня тега.
Чтобы получить эти дополнения, проверьте, чтобы увидеть, была ли ваша деятельность запущена с одним из намерений NFC, чтобы убедиться, что метка была отсканирована, а затем вы получите дополнения. В следующем примере проверяется намерение ACTION_NDEF_DISCOVERED
и получает сообщения NDEF из дополнительного намерения.
Котлин
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) ... if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) { intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages -> val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage } // Process the messages array. ... } } }
Ява
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); ... if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMessages != null) { NdefMessage[] messages = new NdefMessage[rawMessages.length]; for (int i = 0; i < rawMessages.length; i++) { messages[i] = (NdefMessage) rawMessages[i]; } // Process the messages array. ... } } }
В качестве альтернативы, вы можете получить объект Tag
из намерения, который будет содержать полезную нагрузку и позволить вам перечислять технологии тега:
Котлин
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Ява
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Создать общие типы записей NDEF
В этом разделе описывается, как создавать общие типы записей NDEF, чтобы помочь вам при написании в теги NFC. Начиная с Android 4.0 (уровень API 14), метод createUri()
доступен для автоматического создания записей URI. Начиная с Android 4.1 (уровень API 16), createExternal()
и createMime()
доступны, чтобы помочь вам создать записи NDEF MIME и внешнего типа. Используйте эти вспомогательные методы, когда это возможно, чтобы избежать ошибок при вручную создавать записи NDEF.
В этом разделе также описывается, как создать соответствующий фильтр намерения для записи. Все эти примеры записи NDEF должны быть в первой записи NDEF сообщения NDEF, которое вы пишете на тег.
TNF_ABSOLUTE_URI
Примечание. Мы рекомендуем использовать тип RTD_URI
вместо TNF_ABSOLUTE_URI
, потому что он более эффективен.
Вы можете создать запись TNF_ABSOLUTE_URI
NDEF следующим образом:
Котлин
val uriRecord = ByteArray(0).let { emptyByteArray -> NdefRecord( TNF_ABSOLUTE_URI, "https://developer.android.com/index.html".toByteArray(Charset.forName("US-ASCII")), emptyByteArray, emptyByteArray ) }
Ява
NdefRecord uriRecord = new NdefRecord( NdefRecord.TNF_ABSOLUTE_URI , "https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")), new byte[0], new byte[0]);
Фильтр намерений для предыдущей записи NDEF будет выглядеть так:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
Tnf_mime_media
Вы можете создать запись TNF_MIME_MEDIA
ndef следующими способами:
Используя метод createMime()
:
Котлин
val mimeRecord = NdefRecord.createMime( "application/vnd.com.example.android.beam", "Beam me up, Android".toByteArray(Charset.forName("US-ASCII")) )
Ява
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam", "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
Создание NdefRecord
вручную:
Котлин
val mimeRecord = Charset.forName("US-ASCII").let { usAscii -> NdefRecord( NdefRecord.TNF_MIME_MEDIA, "application/vnd.com.example.android.beam".toByteArray(usAscii), ByteArray(0), "Beam me up, Android!".toByteArray(usAscii) ) }
Ява
NdefRecord mimeRecord = new NdefRecord( NdefRecord.TNF_MIME_MEDIA , "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")), new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
Фильтр намерений для предыдущей записи NDEF будет выглядеть так:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/vnd.com.example.android.beam" /> </intent-filter>
Tnf_well_ известно с rtd_text
Вы можете создать запись TNF_WELL_KNOWN
ndef следующим образом:
Котлин
fun createTextRecord(payload: String, locale: Locale, encodeInUtf8: Boolean): NdefRecord { val langBytes = locale.language.toByteArray(Charset.forName("US-ASCII")) val utfEncoding = if (encodeInUtf8) Charset.forName("UTF-8") else Charset.forName("UTF-16") val textBytes = payload.toByteArray(utfEncoding) val utfBit: Int = if (encodeInUtf8) 0 else 1 shl 7 val status = (utfBit + langBytes.size).toChar() val data = ByteArray(1 + langBytes.size + textBytes.size) data[0] = status.toByte() System.arraycopy(langBytes, 0, data, 1, langBytes.size) System.arraycopy(textBytes, 0, data, 1 + langBytes.size, textBytes.size) return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), data) }
Ява
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) { byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); byte[] textBytes = payload.getBytes(utfEncoding); int utfBit = encodeInUtf8 ? 0 : (1 << 7); char status = (char) (utfBit + langBytes.length); byte[] data = new byte[1 + langBytes.length + textBytes.length]; data[0] = (byte) status; System.arraycopy(langBytes, 0, data, 1, langBytes.length); System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); return record; }
Фильтр намерений для предыдущей записи NDEF будет выглядеть так:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter>
Tnf_well_ известно с rtd_uri
Вы можете создать запись TNF_WELL_KNOWN
NDEF следующими способами:
Используя метод createUri(String)
:
Котлин
val rtdUriRecord1 = NdefRecord.createUri("https://example.com")
Ява
NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");
Используя метод createUri(Uri)
:
Котлин
val rtdUriRecord2 = Uri.parse("https://example.com").let { uri -> NdefRecord.createUri(uri) }
Ява
Uri uri = Uri.parse("https://example.com"); NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
Создание NdefRecord
вручную:
Котлин
val uriField = "example.com".toByteArray(Charset.forName("US-ASCII")) val payload = ByteArray(uriField.size + 1) //add 1 for the URI Prefix payload [0] = 0x01 //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.size) //appends URI to payload val rtdUriRecord = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, ByteArray(0), payload)
Ява
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII")); byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix payload[0] = 0x01; //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.length); //appends URI to payload NdefRecord rtdUriRecord = new NdefRecord( NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
Фильтр намерений для предыдущей записи NDEF будет выглядеть так:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="example.com" android:pathPrefix="" /> </intent-filter>
Tnf_external_type
Вы можете создать запись TNF_EXTERNAL_TYPE
ndef следующими способами:
Используя метод createExternal()
:
Котлин
var payload: ByteArray //assign to your data val domain = "com.example" //usually your app's package name val type = "externalType" val extRecord = NdefRecord.createExternal(domain, type, payload)
Ява
byte[] payload; //assign to your data String domain = "com.example"; //usually your app's package name String type = "externalType"; NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
Создание NdefRecord
вручную:
Котлин
var payload: ByteArray ... val extRecord = NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".toByteArray(Charset.forName("US-ASCII")), ByteArray(0), payload )
Ява
byte[] payload; ... NdefRecord extRecord = new NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".getBytes(Charset.forName("US-ASCII")), new byte[0], payload);
Фильтр намерений для предыдущей записи NDEF будет выглядеть так:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="vnd.android.nfc" android:host="ext" android:pathPrefix="/com.example:externalType"/> </intent-filter>
Используйте TNF_EXTERNAL_TYPE
для более общих развертываний тегов NFC, чтобы лучше поддержать как Android-мощные, так и не Android-мощные устройства.
Примечание . Урны для TNF_EXTERNAL_TYPE
имеют канонический формат: urn:nfc:ext:example.com:externalType
, однако спецификация RTD NFC заявляет, что urn:nfc:ext:
часть URN должна быть опущена из записи NDEF. Таким образом, все, что вам нужно предоставить, это домен ( example.com
в примере) и тип ( externalType
в примере), разделенный толстой кишкой. При отправке TNF_EXTERNAL_TYPE
Android преобразует urn:nfc:ext:example.com:externalType
urn в vnd.android.nfc://ext/example.com:externalType
uri, что является тем, что является намеренным фильтром в примере.
Android -записи
Представленная в Android 4.0 (API -уровне 14), запись приложения Android (AAR) обеспечивает более сильную уверенность в том, что ваше приложение запускается при сканировании тега NFC. AAR имеет название пакета приложения, встроенного в запись NDEF. Вы можете добавить AAR в любую запись NDEF вашего сообщения NDEF, потому что Android ищет все сообщение NDEF для AAR. Если он находит AAR, он запускает приложение на основе имени пакета внутри AAR. Если приложение не присутствует на устройстве, Google Play запускается для загрузки приложения.
AARS полезны, если вы хотите предотвратить фильтрацию других приложений для того же намерения и потенциально обрабатывать конкретные теги, которые вы развернули. AARs поддерживаются только на уровне приложения из -за ограничения имени пакета, а не на уровне активности, как при фильтрации намерения. Если вы хотите справиться с намерением на уровне активности, используйте намерения фильтры .
Если тег содержит AAR, система диспетчерской тегов посылает следующим образом:
- Попробуйте запустить деятельность, используя фильтр намерения как обычно. Если деятельность, соответствующая намерению, также соответствует AAR, запустите деятельность.
- Если деятельность, которая фильтровала для намерения, не соответствует AAR, если несколько действий могут обрабатывать намерение, или если действие не обрабатывает намерение, запустите приложение, указанное AAR.
- Если приложение не может начать с AAR, перейдите в Google Play, чтобы загрузить приложение на основе AAR.
ПРИМЕЧАНИЕ. Вы можете переопределить AARS и систему отправки намерений с помощью системы отправки переднего плана , которая позволяет на переднем плане иметь приоритет при обнаружении тега NFC. С помощью этого метода деятельность должна быть на переднем плане, чтобы переопределить AARS и систему отправки намерений.
Если вы все еще хотите отфильтровать для сканируемых тегов, которые не содержат AAR, вы можете объявить о намерениях фильтры как обычно. Это полезно, если ваше приложение заинтересовано в других тегах, которые не содержат AAR. Например, возможно, вы хотите гарантировать, что ваше приложение обрабатывает проприетарные теги, которые вы используете, а также общие теги, развернутые третьими лицами. Имейте в виду, что AARs специфичны для устройств Android 4.0 или позже, поэтому при развертывании тегов вы, скорее всего, хотите использовать комбинацию AAR и типов MIME/URI для поддержки самого широкого диапазона устройств. Кроме того, когда вы развернете теги NFC, подумайте о том, как вы хотите написать теги NFC, чтобы обеспечить поддержку для большинства устройств (мощность Android и другие устройства). Вы можете сделать это, определив относительно уникальный тип MIME или URI, чтобы приложения были проще для различения.
Android предоставляет простой API для создания AAR, createApplicationRecord()
. Все, что вам нужно сделать, это встроить AAR в любом месте вашего NdefMessage
. Вы не хотите использовать первую запись вашей NdefMessage
, если только AAR не является единственной записью в NdefMessage
. Это связано с тем, что система Android проверяет первую запись NdefMessage
, чтобы определить тип MIME или URI тега, которая используется для создания намерения для фильтрации. Следующий код показывает вам, как создать AAR:
Котлин
val msg = NdefMessage( arrayOf( ..., NdefRecord.createApplicationRecord("com.example.android.beam") ) )
Ява
NdefMessage msg = new NdefMessage( new NdefRecord[] { ..., NdefRecord.createApplicationRecord("com.example.android.beam")} ); )
Приложение AllingList для сканирования тегов NFC
Запуск Android 16 пользователи уведомляются, когда приложение получает первое намерение NFC, чтобы сканировать теги NFC. Пользователю предоставляется возможность отказаться от приложения от сканирования тегов NFC в уведомлении.
- Приложения могут проверить, позволил ли пользователь приложение сканировать теги NFC, используя
NfcAdapter.isTagIntentAllowed()
. - Приложения могут побудить пользователю снова разрешить сканирование тегов NFC, отправив намерение
ACTION_CHANGE_TAG_INTENT_PREFERENCE
.
ПРИМЕЧАНИЕ. Приложение Scan Scan Scan NFC -Scan List доступно в Settings > Apps > Special app access > Launch via NFC
.