이 문서에서는 Android에서 개발자가 실행하는 기본 NFC 작업을 설명합니다. NFC 데이터를 NDEF 메시지 형식으로 주고받는 방법과 이러한 기능을 지원하는 Android 프레임워크 API에 관해 설명합니다. 비 NDEF 데이터를 사용한 작업을 비롯한 고급 주제는 고급 NFC를 참고하세요.
NFC 태그에서 NDEF 데이터를 읽는 작업은 태그 디스패치 시스템에서 처리됩니다. 이 시스템은 검색된 NFC 태그를 분석하고 데이터를 적절하게 분류하며 분류된 데이터에 관심이 있는 애플리케이션을 시작합니다. 검사된 NFC 태그를 처리하려는 애플리케이션은 인텐트 필터를 선언하고 데이터 처리를 요청할 수 있습니다.
태그 전달 시스템
기기의 설정 메뉴에서 NFC가 중지되어 있지 않으면 화면 잠금이 해제될 때 일반적으로 Android 구동 기기에서 NFC 태그를 찾습니다. Android 지원 기기에서 NFC 태그를 감지하면 사용자에게 어떤 애플리케이션을 사용할지 묻지 않고 가장 적절한 활동이 인텐트를 처리하도록 하는 것이 좋습니다. 기기는 매우 근접한 범위에서 NFC 태그를 검사하므로 사용자가 직접 활동을 선택하도록 할 경우 기기를 태그에서 멀리 이동하게 하여 연결이 끊길 수 있습니다. 활동 선택기가 표시되지 않도록 활동이 관심을 갖는 NFC 태그만 처리하도록 활동을 개발해야 합니다.
이를 위해 Android는 검사된 NFC 태그를 분석하고 파싱한 후 검사된 데이터에 관심이 있는 애플리케이션을 찾는 특수 태그 디스패치 시스템을 제공합니다. 이를 위해 다음을 실행합니다.
- NFC 태그를 파싱하고 MIME 유형 또는 태그에서 데이터 페이로드를 식별하는 URI를 파악합니다.
- MIME 유형 또는 URI와 페이로드를 인텐트에 캡슐화합니다. 이 처음 두 단계는 NFC 태그가 MIME 유형 및 URI에 매핑되는 방법에 설명되어 있습니다.
- 인텐트에 기반하여 활동을 시작합니다. 이 단계는 NFC 태그가 애플리케이션에 디스패치되는 방법에서 설명합니다.
NFC 태그가 MIME 유형 및 URI에 매핑되는 방법
NFC 애플리케이션을 작성하기 전에 다양한 유형의 NFC 태그, 태그 디스패치 시스템이 NFC 태그를 파싱하는 방법, 태그 디스패치 시스템이 NDEF 메시지를 감지할 때 실행하는 특수 작업을 이해하는 것이 중요합니다. NFC 태그는 다양한 기술로 제공되며 NFC 태그에는 다양한 방식으로 데이터가 기록될 수 있습니다. Android는 NFC 포럼에서 정의하는 NDEF 표준을 가장 잘 지원합니다.
NDEF 데이터는 하나 이상의 레코드 (NdefRecord
)를 포함하는 메시지 (NdefMessage
) 내에 캡슐화됩니다. 각 NDEF 레코드는 만들려는 레코드 유형의 사양에 따라 올바른 형식이어야 합니다. Android는 NDEF 데이터를 포함하지 않는 다른 유형의 태그도 지원하며 개발자는 android.nfc.tech
패키지의 클래스를 사용하여 이러한 태그로 작업할 수 있습니다. 이러한 기술에 관해 자세히 알아보려면 고급 NFC 주제를 참고하세요. 이러한 다른 유형의 태그를 사용하려면 자체 프로토콜 스택을 작성하여 태그와 통신해야 하므로 개발 용이성과 Android 구동 기기 지원을 최대화 하기 위해 가능하면 NDEF를 사용하는 것이 좋습니다.
참고: NDEF 사양 전체를 다운로드하려면 NFC 포럼 사양 및 애플리케이션 문서 사이트로 이동하세요. NDEF 레코드를 구성하는 방법의 예는 일반적인 유형의 NDEF 레코드 만들기를 참고하세요.
이제 NFC 태그에 관한 배경 지식을 소개했으므로 다음 섹션에서는 Android에서 NDEF 형식의 태그를 처리하는 방법을 자세히 설명합니다. Android 구동 기기는 NDEF 형식의 데이터가 포함된 NFC 태그를 검사할 때 메시지를 파싱하고 데이터의 MIME 유형 또는 식별 URI를 파악하려고 합니다. 이를 위해 시스템은 NdefMessage
내에서 첫 번째 NdefRecord
를 읽고 전체 NDEF 메시지를 해석하는 방법을 결정합니다 (하나의 NDEF 메시지가 여러 NDEF 레코드를 가질 수 있음). 올바른 형식의 NDEF 메시지에는 첫 번째 NdefRecord
에 다음 필드가 포함됩니다.
- 3비트 TNF(Type Name Format)
- 가변 길이 유형 필드를 해석하는 방법을 나타냅니다. 유효한 값은 표 1에 설명되어 있습니다.
- 가변 길이 유형
- 레코드 유형을 설명합니다.
TNF_WELL_KNOWN
을 사용하는 경우 이 필드를 사용하여 RTD (Record Type Definition)를 지정합니다. 유효한 RTD 값은 표 2에 설명되어 있습니다. - 가변 길이 ID
- 레코드의 고유 식별자입니다. 이 필드는 자주 사용되지 않지만 태그를 고유하게 식별해야 하는 경우 ID를 만들 수 있습니다.
- 가변 길이 페이로드
- 읽거나 쓰고자 하는 실제 데이터 페이로드입니다. 하나의 NDEF 메시지에 여러 NDEF 레코드가 포함될 수 있으므로 전체 페이로드가 NDEF 메시지의 첫 번째 NDEF 레코드에 있다고 가정해서는 안 됩니다.
태그 디스패치 시스템은 TNF 및 유형 필드를 사용하여 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
유형의 레코드를 발견하면 대신 태그의 기술을 캡슐화하는 인텐트를 만듭니다.
TNF(Type Name Format) | 매핑 |
---|---|
TNF_ABSOLUTE_URI |
유형 필드를 기반으로 하는 URI. |
TNF_EMPTY |
ACTION_TECH_DISCOVERED 로 대체됩니다. |
TNF_EXTERNAL_TYPE |
유형 필드의 URN을 기반으로 하는 URI. URN은 <domain_name>:<service_name> 의 축약 형식으로 NDEF 유형 필드에 인코딩됩니다.
Android는 이를 vnd.android.nfc://ext/<domain_name>:<service_name> 형식으로 URI에 매핑합니다. |
TNF_MIME_MEDIA |
유형 필드를 기반으로 하는 MIME 유형. |
TNF_UNCHANGED |
첫 번째 레코드가 잘못되었으므로 ACTION_TECH_DISCOVERED 로 대체됩니다. |
TNF_UNKNOWN |
ACTION_TECH_DISCOVERED 로 대체됩니다. |
TNF_WELL_KNOWN |
유형 필드에서 설정한 RTD (Record Type Definition)에 따라 MIME 유형 또는 URI. 사용 가능한 RTD와 매핑에 관한 자세한 내용은 표 2를 참고하세요. |
RTD(Record Type Definition) | 매핑 |
---|---|
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 |
text/plain 의 MIME 유형. |
RTD_URI |
페이로드를 기반으로 하는 URI. |
NFC 태그가 애플리케이션에 디스패치되는 방법
태그 디스패치 시스템은 NFC 태그와 태그의 식별 정보를 캡슐화하는 인텐트를 만든 후 인텐트 필터링에 관심이 있는 애플리케이션에 인텐트를 전송합니다. 둘 이상의 애플리케이션에서 인텐트를 처리할 수 있는 경우 사용자가 활동을 선택할 수 있도록 활동 선택기가 표시됩니다. 태그 디스패치 시스템은 우선순위가 가장 높은 것부터 낮은 것 순으로 세 개의 인텐트를 정의합니다.
-
ACTION_NDEF_DISCOVERED
: 이 인텐트는 NDEF 페이로드가 포함된 태그가 검사될 때와 태그의 유형이 인식될 때 활동을 시작하기 위해 사용됩니다. 이 인텐트는 우선순위가 가장 높으며, 태그 디스패치 시스템은 가능한 경우 항상 다른 인텐트 이전에 이 인텐트로 활동을 시작하려고 합니다. ACTION_TECH_DISCOVERED
:ACTION_NDEF_DISCOVERED
인텐트를 처리하도록 등록된 활동이 없는 경우 태그 디스패치 시스템은 이 인텐트로 애플리케이션을 시작하려고 합니다. 태그에 MIME 유형 또는 URI에 매핑할 수 없는 NDEF 데이터가 포함되어 있거나 태그에 NDEF 데이터가 포함되어 있지 않지만 태그 기술이 알려진 경우 이 인텐트도 직접 시작됩니다 (먼저ACTION_NDEF_DISCOVERED
를 시작하지 않음).ACTION_TAG_DISCOVERED
:ACTION_NDEF_DISCOVERED
또는ACTION_TECH_DISCOVERED
인텐트를 처리할 활동이 없는 경우 이 인텐트가 시작됩니다.
태그 디스패치 시스템의 기본 작동 방법은 다음과 같습니다.
- NFC 태그 (
ACTION_NDEF_DISCOVERED
또는ACTION_TECH_DISCOVERED
)를 파싱할 때 태그 디스패치 시스템에서 만든 인텐트를 사용하여 활동을 시작해 봅니다. - 이 인텐트를 필터링하는 활동이 없는 경우 애플리케이션이 인텐트를 필터링하거나 태그 디스패치 시스템이 가능한 모든 인텐트를 시도할 때까지 우선순위가 다음으로 낮은 인텐트 (
ACTION_TECH_DISCOVERED
또는ACTION_TAG_DISCOVERED
)로 활동을 시작합니다. - 인텐트를 필터링하는 애플리케이션이 없는 경우 아무것도 하지 않습니다.
가능하면 NDEF 메시지와 ACTION_NDEF_DISCOVERED
인텐트로 작업합니다. 세 가지 중 가장 구체적이기 때문입니다. 이 인텐트를 사용하면 다른 두 인텐트보다 더 적절한 시간에 애플리케이션을 시작할 수 있으므로 사용자에게 더 나은 환경이 제공됩니다.
Android manifest에서 NFC 액세스 요청
기기의 NFC 하드웨어에 액세스하고 NFC 인텐트를 제대로 처리하려면 AndroidManifest.xml
파일에서 다음 항목을 선언합니다.
- NFC 하드웨어에 액세스하기 위한 NFC
<uses-permission>
요소:<uses-permission android:name="android.permission.NFC" />
- 애플리케이션이 지원할 수 있는 최소 SDK 버전. API 수준 9는
ACTION_TAG_DISCOVERED
를 통해 제한된 태그 디스패치만 지원하며EXTRA_NDEF_MESSAGES
엑스트라를 통해 NDEF 메시지에만 액세스하도록 허용합니다. 다른 태그 속성 또는 I/O 작업에는 액세스할 수 없습니다. API 수준 10에는 포괄적인 판독기/작성기 지원 및 포그라운드 NDEF 푸시가 포함되어 있으며 API 수준 14는 NDEF 레코드를 만들기 위한 편리한 추가 메서드를 제공합니다.<uses-sdk android:minSdkVersion="10"/>
- NFC 하드웨어가 있는 기기에서만 애플리케이션이 Google Play에 표시되도록 하는
uses-feature
요소:<uses-feature android:name="android.hardware.nfc" android:required="true" />
애플리케이션이 NFC 기능을 사용하지만 애플리케이션에서 이 기능이 중요하지 않은 경우에는
uses-feature
요소를 생략하고,getDefaultAdapter()
가null
인지 확인하여 런타임 시 NFC 가용성을 확인할 수 있습니다.
NFC 인텐트 필터링
처리하려는 NFC 태그가 스캔될 때 애플리케이션을 시작하려면 애플리케이션에서 Android 매니페스트의 NFC 인텐트 한두 개 또는 세 개를 모두 필터링하면 됩니다. 그러나 애플리케이션 시작 시기를 최대한 제어하기 위해 일반적으로 ACTION_NDEF_DISCOVERED
인텐트를 필터링하는 것이 좋습니다. ACTION_NDEF_DISCOVERED
용 애플리케이션 필터가 없거나 페이로드가 NDEF가 아닌 경우 ACTION_TECH_DISCOVERED
인텐트는 ACTION_NDEF_DISCOVERED
의 대체입니다. ACTION_TAG_DISCOVERED
의 필터링은 대개 필터링할 범주가 너무 일반적입니다. 많은 애플리케이션이 ACTION_TAG_DISCOVERED
전에 ACTION_NDEF_DISCOVERED
또는 ACTION_TECH_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>
다음 예에서는 https://developer.android.com/index.html
형식으로 URI를 필터링합니다.
<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
인텐트를 필터링하는 경우 tech-list
집합 내에서 활동이 지원하는 기술을 지정하는 XML 리소스 파일을 만들어야 합니다. 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
파일에서 다음 예와 같이 <activity>
요소 내 <meta-data>
요소에서 방금 만든 리소스 파일을 지정합니다.
<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
인텐트 작업에 관한 자세한 내용은 고급 NFC 문서의 지원되는 태그 기술 작업을 참고하세요.
ACTION_TAG_DISCOVERED
ACTION_TAG_DISCOVERED
를 필터링하려면 다음 인텐트 필터를 사용합니다.
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
인텐트에서 정보 가져오기
NFC 인텐트로 인해 활동이 시작되는 경우 인텐트에서 스캔된 NFC 태그에 관한 정보를 가져올 수 있습니다. 인텐트는 검사된 태그에 따라 다음 추가 항목을 포함할 수 있습니다.
EXTRA_TAG
(필수): 스캔된 태그를 나타내는Tag
객체입니다.EXTRA_NDEF_MESSAGES
(선택사항): 태그에서 파싱된 NDEF 메시지의 배열입니다. 이 추가 항목은ACTION_NDEF_DISCOVERED
인텐트에서 필수입니다.EXTRA_ID
(선택사항): 태그의 하위 수준 ID입니다.
이러한 추가 항목을 가져오려면 NFC 인텐트 중 하나로 활동이 실행되어 태그가 검사되었는지 확인한 다음 인텐트에서 추가 항목을 가져옵니다. 다음 예에서는 ACTION_NDEF_DISCOVERED
인텐트를 확인하고 인텐트 추가 항목에서 NDEF 메시지를 가져옵니다.
Kotlin
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
객체를 인텐트에서 가져올 수 있습니다.
Kotlin
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
자바
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
일반적인 NDEF 레코드 유형 만들기
이 섹션에서는 NFC 태그에 쓸 때 도움이 되도록 일반적인 유형의 NDEF 레코드를 만드는 방법을 설명합니다. Android 4.0 (API 수준 14)부터는 createUri()
메서드를 사용하여 URI 레코드를 자동으로 만들 수 있습니다. Android 4.1 (API 수준 16)부터는 createExternal()
및 createMime()
을 사용하여 MIME 및 외부 유형 NDEF 레코드를 만들 수 있습니다. NDEF 레코드를 수동으로 만들 때 실수를 피하려면 가능한 한 이러한 도우미 메서드를 사용합니다.
이 섹션에서는 레코드에 해당하는 인텐트 필터를 만드는 방법을 설명합니다. 이러한 모든 NDEF 레코드 예는 태그에 쓰려는 NDEF 메시지의 첫 번째 NDEF 레코드에 있어야 합니다.
TNF_ABSOLUTE_URI
참고: TNF_ABSOLUTE_URI
대신 RTD_URI
유형을 사용하는 것이 좋습니다. 효율성이 더 뛰어나기 때문입니다.
다음과 같은 방법으로 TNF_ABSOLUTE_URI
NDEF 레코드를 만들 수 있습니다.
Kotlin
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()
메서드 사용:
Kotlin
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
만들기:
Kotlin
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 with RTD_TEXT
다음과 같은 방법으로 TNF_WELL_KNOWN
NDEF 레코드를 만들 수 있습니다.
Kotlin
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 with RTD_URI
다음과 같은 방법으로 TNF_WELL_KNOWN
NDEF 레코드를 만들 수 있습니다.
createUri(String)
메서드 사용:
Kotlin
val rtdUriRecord1 = NdefRecord.createUri("https://example.com")
자바
NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");
createUri(Uri)
메서드 사용:
Kotlin
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
만들기:
Kotlin
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()
메서드 사용:
Kotlin
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
만들기:
Kotlin
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>
Android 지원 기기와 비 Android 지원 기기를 모두 더 잘 지원하도록 더 일반적인 NFC 태그 배포에는 TNF_EXTERNAL_TYPE
를 사용합니다.
참고: TNF_EXTERNAL_TYPE
용 URN의 표준 형식은 urn:nfc:ext:example.com:externalType
이지만 NFC Forum RTD 사양에서는 URN의 urn:nfc:ext:
부분을 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 (Android 애플리케이션 레코드)은 NFC 태그를 검사할 때 애플리케이션이 시작될 가능성을 크게 높여줍니다. AAR에는 NDEF 레코드 내에 포함된 애플리케이션의 패키지 이름이 있습니다. Android는 전체 NDEF 메시지에서 AAR을 검색하므로 NDEF 메시지의 모든 NDEF 레코드에 AAR을 추가할 수 있습니다. AAR을 찾으면 AAR 내의 패키지 이름에 따라 애플리케이션을 시작합니다. 기기에 애플리케이션이 없으면 Google Play가 실행되어 애플리케이션을 다운로드합니다.
다른 애플리케이션이 동일한 인텐트를 필터링하고 배포된 특정 태그를 처리하는 것을 방지하려는 경우 AAR이 유용합니다. AAR은 패키지 이름 제약 조건 때문에 애플리케이션 수준에서만 지원되며 인텐트 필터링처럼 활동 수준에서는 지원되지 않습니다. 활동 수준에서 인텐트를 처리하려면 인텐트 필터를 사용합니다.
태그에 AAR이 포함된 경우 태그 디스패치 시스템은 다음과 같은 방식으로 디스패치합니다.
- 평상시처럼 인텐트 필터를 사용하여 활동을 시작해 봅니다. 인텐트와 일치하는 활동이 AAR과도 일치하는 경우 활동을 시작합니다.
- 인텐트를 필터링하는 활동이 AAR과 일치하지 않거나, 여러 활동이 인텐트를 처리할 수 있거나, 인텐트를 처리할 활동이 없는 경우 AAR이 지정한 애플리케이션을 시작합니다.
- AAR로 시작할 수 있는 애플리케이션이 없는 경우 Google Play로 이동하여 AAR을 기반으로 애플리케이션을 다운로드합니다.
참고: AAR과 인텐트 디스패치 시스템을 포그라운드 디스패치 시스템으로 재정의할 수 있습니다. 그러면 NFC 태그가 검색될 때 포그라운드 활동이 우선순위를 갖게 됩니다. 이 방법을 사용할 경우 AAR 및 인텐트 디스패치 시스템을 재정의하려면 활동이 포그라운드에 있어야 합니다.
AAR이 포함되지 않은 스캔된 태그를 계속 필터링하려면 인텐트 필터를 평소와 같이 선언하면 됩니다. 이 방법은 애플리케이션이 AAR이 없는 다른 태그에 관심이 있는 경우에 유용합니다. 예를 들어 직접 배포한 독점 태그와 서드 파티에서 배포한 일반 태그를 애플리케이션이 모두 처리하도록 하고자 하는 경우입니다. AAR은 Android 4.0 이상의 기기에만 해당되므로 태그를 배포할 때 AAR과 MIME 유형/URI의 조합을 사용하면 가장 광범위한 기기를 지원할 수 있습니다. 또한 NFC 태그를 배포할 때 대부분의 기기 (Android 구동 기기 및 기타 기기)를 지원할 수 있도록 NFC 태그를 작성하는 방법에 관해 생각해 보세요. 이렇게 하려면 애플리케이션이 더 쉽게 구분할 수 있도록 상대적으로 고유한 MIME 유형 또는 URI를 정의하면 됩니다.
Android는 AAR, createApplicationRecord()
를 생성하는 간단한 API를 제공합니다. NdefMessage
에 AAR을 삽입하기만 하면 됩니다. AAR이 NdefMessage
의 유일한 레코드가 아니라면 NdefMessage
의 첫 번째 레코드를 사용하지 않는 것이 좋습니다. 이는 Android 시스템이 NdefMessage
의 첫 번째 레코드를 확인하여 태그가 필터링할 인텐트를 만드는 데 사용되는 태그의 MIME 유형 또는 URI를 확인하기 때문입니다. 다음 코드는 AAR을 만드는 방법을 보여줍니다.
Kotlin
val msg = NdefMessage( arrayOf( ..., NdefRecord.createApplicationRecord("com.example.android.beam") ) )
Java
NdefMessage msg = new NdefMessage( new NdefRecord[] { ..., NdefRecord.createApplicationRecord("com.example.android.beam")} ); )