NFC 기초

이 문서에서는 Android에서 개발자가 실행하는 기본 NFC 작업을 설명합니다. 여기에서는 컨테이너 이미지를 NDEF 메시지 형식으로 NFC 데이터를 수신하고 Android 프레임워크 API를 지원하는 살펴보겠습니다 비 NDEF 데이터 작업에 대한 논의를 포함하여 고급 주제의 경우 고급 NFC를 참조하세요.

NDEF 데이터 및 Android로 작업할 때 두 가지 주요 사용 사례가 있습니다.

NFC 태그에서 NDEF 데이터 읽기는 태그 전달로 처리됩니다. 시스템은 발견된 NFC 태그를 분석하고 데이터를 적절하게 분류하여 관심이 있는 애플리케이션을 만듭니다. 인코더-디코더 아키텍처를 스캔된 NFC 태그가 인텐트 필터를 선언하고 이 데이터를 처리할 수 있어야 합니다

Android BeamTM 기능을 통해 기기는 NDEF 메시지를 다른 장치를 물리적으로 함께 탭해서 얻습니다. 이 상호 작용을 통해 다른 무선 기술보다 데이터를 전송하는 데 더 많은 시간을 투자할 수 있습니다. NFC의 경우 수동 기기가 필요하지 않기 때문입니다. 검색 또는 페어링이 필요합니다. 두 대의 기기가 연결되면 자동으로 연결이 시작됩니다. 범위 내로 갈 수 있습니다. Android Beam은 일련의 NFC API를 통해 사용할 수 있으므로 모든 애플리케이션에서 장치 간의 정보. 예를 들어 주소록, 브라우저 및 YouTube 애플리케이션에서는 다른 기기와 연락처, 웹페이지, 동영상을 공유하는 Android Beam

태그 디스패치 시스템

Android 구동 기기는 일반적으로 화면이 켜져 있을 때 NFC 태그를 찾습니다. 잠금 해제됨(기기의 설정 메뉴에서 NFC가 사용 중지되어 있지 않음) Android 지원 기기가 NFC 태그를 발견하면 원하는 동작은 사용자에게 어떤 애플리케이션이 있는지 묻지 않고 가장 적절한 활동이 인텐트를 처리하도록 하는 것입니다. 있습니다. 기기는 매우 짧은 범위에서 NFC 태그를 스캔하기 때문에 활동을 선택하면 기기가 태그에서 이동되어 연결이 끊어지게 됩니다. Activity가 관심을 두는 NFC 태그만 처리하도록 Activity를 개발해야 합니다. 활동 선택기가 표시되지 않도록 할 수 있습니다.

이 목표를 돕기 위해 Android는 검사된 태그 디스패치 시스템을 분석하여 NFC 태그가 적용된 태그를 파싱한 후 스캔한 데이터에 관심이 있는 애플리케이션을 찾습니다. 그것은 다음을 수행합니다.

  1. NFC 태그를 파싱하고 MIME 유형 또는 데이터 페이로드를 식별하는 URI 계산 를 사용하지 마세요.
  2. MIME 유형 또는 URI와 페이로드를 인텐트에 캡슐화합니다. 이 처음 두 개의 NFC 태그가 MIME 유형 및 URI에 매핑되는 방법에 설명되어 있습니다.
  3. 인텐트에 기반하여 활동을 시작합니다. 자세한 내용은 NFC 태그가 애플리케이션에 디스패치되는 방법

NFC 태그가 MIME 유형 및 URI에 매핑되는 방법

NFC 애플리케이션을 작성하기 전에 이 API의 여러 기능에 대해 NFC 태그의 유형, 태그 디스패치 시스템이 NFC 태그를 파싱하는 방법, 태그가 수행하는 특수 작업 NDEF 메시지를 감지하면 이 작업을 수행합니다. NFC 태그는 다양한 방식으로 데이터를 쓸 수 있습니다. Android는 NFC 포럼에서 정의하는 NDEF 표준을 가장 잘 지원합니다.

NDEF 데이터는 메시지를 포함하는 메시지 (NdefMessage) 내에 캡슐화됩니다. 이상 레코드 (NdefRecord)를 추가합니다. 각 NDEF 레코드는 만들려는 레코드 유형의 사양을 입력합니다. Android의 경우 또한 NDEF 데이터를 포함하지 않는 다른 유형의 태그도 지원합니다. 이러한 태그는 android.nfc.tech 패키지의 클래스 자세히 알아보기 고급 NFC 주제를 참조하세요. 이러한 다른 유형의 태그로 작업하려면 태그와 통신하기 위해 자체 프로토콜 스택을 작성해야 하므로 개발이 용이하고 Android 구동 기기를 최대한 지원할 수 있습니다.

참고: 전체 NDEF 사양을 다운로드하려면 NFC 포럼 사양 및 신청 문서 사이트를 검토하여 방법의 예를 보려면 일반적인 유형의 NDEF 레코드 만들기 NDEF 레코드를 구성합니다.

이제 NFC 태그에 대한 배경 지식이 생겼으므로 다음 섹션에서 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)를 지정합니다. 유효한 RTD 값은 표 2에 설명되어 있습니다.
가변 길이 ID
레코드의 고유 식별자입니다. 이 필드는 자주 사용되지 않지만 태그를 고유하게 식별해야 하는 경우 ID를 만들 수 있습니다.
가변 길이 페이로드
읽거나 쓰고자 하는 실제 데이터 페이로드입니다. 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 인텐트의 데이터 필드에 캡슐화합니다. 외부 IP 주소가 있습니다 반면에 TNF_UNKNOWN 유형의 레코드를 발견하면 태그의 기술을 캡슐화하는 인텐트를 만듭니다. 하세요.

표 1. 지원되는 TNF 및 매핑

TNF(Type Name Format) 매핑
TNF_ABSOLUTE_URI 유형 필드를 기반으로 하는 URI.
TNF_EMPTY ACTION_TECH_DISCOVERED로 대체됩니다.
TNF_EXTERNAL_TYPE 유형 필드의 URN을 기반으로 하는 URI. URN은 단축된 형식: <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 레코드 유형 정의 (RTD)에 따른 MIME 유형 또는 URI이며 유형 필드에 입력됩니다. 자세한 내용은 표 2를 참조하세요. 사용 가능한 RTD와 매핑을 포함합니다.

표 2. TNF_WELL_KNOWN 및 관련 RTD 지원 매핑

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 태그와 태그 자체를 캡슐화하는 인텐트를 관심 있는 애플리케이션에 인텐트를 보내서 필터를 적용합니다. 둘 이상의 애플리케이션이 인텐트를 처리할 수 있는 경우 활동 선택기는 사용자가 활동을 선택할 수 있습니다. 태그 디스패치 시스템은 세 가지 인텐트를 정의합니다. 우선순위가 가장 높은 것에서 가장 낮은 순으로 나열됩니다.

  1. ACTION_NDEF_DISCOVERED: 이 인텐트는 NDEF 페이로드가 포함된 태그가 스캔되고 인식된 유형인 경우의 활동. 이것은 우선순위가 가장 높은 인텐트에 도달하고, 태그 디스패치 시스템은 이 인텐트로 액티비티를 시작하려고 시도합니다. (가능한 경우) 인텐트를 다른 인텐트보다 먼저 호출
  2. ACTION_TECH_DISCOVERED: 등록된 활동이 없는 경우 ACTION_NDEF_DISCOVERED 처리 인텐트에 도달하면 태그 디스패치 시스템이 이 인텐트로 애플리케이션을 시작하려고 시도합니다. 이 스캔된 태그가 있는 경우 인텐트도 직접 시작됩니다 (ACTION_NDEF_DISCOVERED를 먼저 시작하지 않음). MIME 유형 또는 URI에 매핑할 수 없는 NDEF 데이터가 포함되거나 태그에 NDEF가 포함되지 않은 경우 알려진 태그 기술을 사용하는 것입니다.
  3. ACTION_TAG_DISCOVERED: 이 인텐트가 시작됩니다. ACTION_NDEF_DISCOVERED 또는 ACTION_TECH_DISCOVERED를 처리하는 활동이 없는 경우 인텐트를 지정할 수 있습니다.

태그 디스패치 시스템의 기본 작동 방법은 다음과 같습니다.

  1. 태그 디스패치 시스템에서 만든 인텐트로 활동 시작 시도 NFC 태그를 파싱할 때 (또는 ACTION_NDEF_DISCOVERED 또는 ACTION_TECH_DISCOVERED).
  2. 이 인텐트에 관한 활동이 필터링되지 않으면 다음 인텐트로 활동을 시작해 보세요. 애플리케이션이 ACTION_TECH_DISCOVERED 또는 ACTION_TAG_DISCOVERED 인텐트를 전달하거나 태그 디스패치 시스템이 가능한 모든 인텐트를 시도할 때까지 기다립니다.
  3. 인텐트를 필터링하는 애플리케이션이 없는 경우 아무것도 하지 않습니다.
를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder"></ph>
그림 1. 태그 디스패치 시스템

가능하면 항상 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는 Android Beam 및 추가 기능을 사용하여 NDEF 메시지를 다른 기기로 더 쉽게 푸시하는 방법을 제공합니다. 편리한 메서드를 사용하여 NDEF 레코드를 만들 수 있습니다.
    <uses-sdk android:minSdkVersion="10"/>
    
  • 애플리케이션이 Google Play에 표시되는 uses-feature 요소 NFC 하드웨어가 있는 기기에서만 사용할 수 있습니다.
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    애플리케이션에서 NFC 기능을 사용하지만 NFC 기능을 사용하는 데 애플리케이션에서는 uses-feature 요소를 생략하고 다음 위치에서 NFC 사용 가능 여부를 확인할 수 있습니다. 확인하여 getDefaultAdapter() null입니다.

NFC 인텐트 필터링

처리하려는 NFC 태그가 스캔될 때 애플리케이션을 시작하려면 애플리케이션이 필요합니다. 하나, 둘 또는 세 개의 NFC 인텐트 모두를 필터링할 수 있습니다. 하지만 일반적으로 다음과 같이 ACTION_NDEF_DISCOVERED 인텐트를 필터링하려고 합니다. 제어해야 할 수도 있습니다 ACTION_TECH_DISCOVERED 인텐트는 다음을 필터링하는 애플리케이션이 없을 때 ACTION_NDEF_DISCOVERED의 대안입니다. ACTION_NDEF_DISCOVERED 또는 페이로드가 NDEF. 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

<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 집합은 기술 3개, 2개 또는 1개를 모두 지정해야 합니다. 그렇지 않으면 활동이 일치되도록 해야 합니다.

다음 샘플은 모든 기술을 정의합니다. 포함되지 않은 앱은 삭제해야 합니다. 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()에서 반환하는 기술의 하위 집합입니다. ANDOR를 제공합니다. 시맨틱스를 제공합니다 다음 예는 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에 대한 정보를 얻을 수 있습니다. 태그를 지정합니다. 인텐트는 검사된 태그에 따라 다음 추가 항목을 포함할 수 있습니다.

이러한 추가 항목을 얻으려면 활동이 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 레코드 유형 만들기

이 섹션에서는 메일을 작성할 때 도움이 되는 일반적인 유형의 NDEF 레코드를 만드는 방법을 설명합니다. NFC 태그 또는 Android Beam을 사용하여 데이터 전송 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 레코드를 만들 수 있습니다. :

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_외부_유형

다음에서 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>

둘 다 더 잘 지원하기 위해 더 일반적인 NFC 태그 배포에는 TNF_EXTERNAL_TYPE를 사용합니다. Android 구동 기기와 Android가 아닌 기기

참고: TNF_EXTERNAL_TYPE의 URN의 표준 형식은 다음과 같습니다. urn:nfc:ext:example.com:externalType이지만 NFC 포럼 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)는 애플리케이션이 시작되었는지 확신할 수 있어야 합니다. AAR에는 패키지 이름이 있음 NDEF 레코드 내부에 삽입되어 있습니다. NDEF의 모든 NDEF 레코드에 AAR을 추가할 수 있습니다. 오류 메시지(Android가 전체 NDEF 메시지에서 AAR을 검색하기 때문입니다. AAR을 찾으면 광고 캠페인이 시작됩니다 AAR 내의 패키지 이름을 기준으로 애플리케이션을 빌드합니다. 애플리케이션이 Google Play가 실행되어 애플리케이션을 다운로드합니다.

AAR은 다른 애플리케이션이 동일한 인텐트를 필터링하지 않도록 하고 싶은 경우에 유용합니다. 특정 태그를 처리할 수 있습니다. AAR은 다음에서만 지원됩니다. 패키지 이름 제약조건으로 인해 애플리케이션 수준이며, 활동 수준은 아닙니다. 인텐트 필터링 활동 수준에서 인텐트를 처리하려면 인텐트 필터를 사용합니다.

태그에 AAR이 포함된 경우 태그 디스패치 시스템은 다음과 같은 방식으로 디스패치합니다.

  1. 평상시처럼 인텐트 필터를 사용하여 활동을 시작해 봅니다. 사용자의 활동이 인텐트도 AAR과 일치하면 Activity를 시작합니다.
  2. 인텐트를 필터링하는 활동이 AAR이 여러 활동이 인텐트를 처리할 수 있거나 인텐트를 처리할 활동이 없는 경우 애플리케이션입니다.
  3. AAR로 시작할 수 있는 애플리케이션이 없는 경우 Google Play로 이동하여 적용할 수 있습니다

참고: 다음과 같이 AAR과 인텐트 디스패치 시스템을 재정의할 수 있습니다. 포그라운드 디스패치 시스템을 지원하므로 NFC 태그가 수신되면 포그라운드 활동이 우선순위를 가지도록 허용합니다. 있습니다. 이 메서드를 사용할 경우 AAR과 인텐트 디스패치 시스템을 빌드합니다.

AAR을 포함하지 않는 검사된 태그를 필터링하려는 경우 인텐트 필터를 정상적으로 사용하세요. 이는 애플리케이션이 다른 태그에 관심이 있는 경우에 유용합니다. AAR이 포함되지 않은 캠페인 예를 들어 애플리케이션이 기본 스레드의 귀하가 배포하는 독점 태그뿐만 아니라 제3자가 배포한 일반 태그도 포함됩니다. 유의사항 AAR이 Android 4.0 이상 기기에만 국한되므로 태그를 배포할 때 AAR과 MIME 유형/URI의 조합을 사용해 가장 광범위한 기기를 지원할 수 있습니다. 포함 또한 NFC 태그를 배포할 때는 NFC 태그를 작성하여 대부분의 기기 (Android 구동 기기 및 기타 기기)를 지원합니다. 방법은 다음과 같습니다. 상대적으로 고유한 MIME 유형 또는 URI를 정의하여 애플리케이션이 더 쉽게 구분할 수 있도록 합니다.

Android는 AAR을 생성하는 간단한 API를 제공합니다. createApplicationRecord() 필요한 모든 기능 NdefMessage의 아무 곳에나 AAR을 삽입하면 됩니다. 원하지 않는 NdefMessage의 첫 번째 레코드를 사용합니다. 단, AAR이 유일한 경우는 예외입니다. NdefMessage에 있는 레코드. 이는 Android가 시스템은 NdefMessage의 첫 번째 레코드를 확인하여 MIME 유형 또는 태그의 URI이며 애플리케이션이 필터링할 인텐트를 만드는 데 사용됩니다. 다음 코드는 다음과 같이 AAR을 생성하는 방법을 알아보세요.

Kotlin

val msg = NdefMessage(
        arrayOf(
                ...,
                NdefRecord.createApplicationRecord("com.example.android.beam")
        )
)

자바

NdefMessage msg = new NdefMessage(
        new NdefRecord[] {
            ...,
            NdefRecord.createApplicationRecord("com.example.android.beam")}
        );
)

NDEF 메시지를 다른 기기와 공유

Android Beam을 사용하면 두 대의 Android 구동 기기 간에 간편하게 P2P 데이터를 교환할 수 있습니다. 이 데이터를 다른 기기와 공유하려는 애플리케이션이 포그라운드에 있고 해당 기기가 잠겨 있지 않아야 합니다. 공유 장치가 전기 충격기와 충분히 접촉할 때 전송하는 경우 공유 기기에 '터치하여 공유하기' 메시지가 있습니다. 그런 다음 사용자는 수신 장치와 메시지 공유 여부입니다.

참고: 포그라운드 NDEF 푸시는 API 수준 10에서 사용할 수 있었지만 Android Beam과 유사한 기능을 제공합니다. 이후 이러한 API는 지원 중단되었지만 이전 기기도 지원할 수 있습니다. 자세한 내용은 enableForegroundNdefPush()를 참조하세요.

다음 두 가지 메서드 중 하나를 호출하여 애플리케이션에서 Android Beam을 사용하도록 설정할 수 있습니다.

  • setNdefPushMessage(): NdefMessage: 공유할 메시지로 설정합니다. 자동으로 메시지를 공유합니다. 두 기기가 충분히 가까이 있을 때 알림을 전송할 수 있습니다.
  • setNdefPushMessageCallback(): 다음이 포함된 콜백을 수락합니다. createNdefMessage() 이는 장치가 데이터를 공유할 범위 내에 있을 때 호출됩니다. 콜백을 사용하면 필요한 경우에만 NDEF 메시지를 전송합니다.

활동은 한 번에 하나의 NDEF 메시지만 푸시할 수 있으므로 setNdefPushMessageCallback()가 우선합니다. 둘 다 설정된 경우 setNdefPushMessage()를 통해 사용 방법 Android Beam을 사용하려면 다음 일반 가이드라인을 충족해야 합니다.

  • 데이터를 공유하는 활동은 포그라운드 상태여야 합니다. 두 기기 모두 화면이 잠금 해제되어 있어야 합니다.
  • 공유하는 데이터를 NdefMessage에서 캡슐화해야 합니다. 객체를 지정합니다.
  • 공유된 데이터를 수신하는 NFC 기기는 com.android.npp NDEF 푸시 프로토콜 또는 NFC 포럼의 SNEP (Simple NDEF Exchange) 프로토콜). API 수준 9 (Android)의 기기에는 com.android.npp 프로토콜이 필요합니다. API 수준 13 (Android 3.2)까지 가능합니다. com.android.npp 및 SNEP 모두 필수 API 수준 14 (Android 4.0) 이상

참고: 활동이 Android Beam을 사용 설정하고 포그라운드에서는 표준 인텐트 디스패치 시스템이 비활성화됩니다. 하지만 여러분의 활동이 사용 포그라운드 디스패치를 실행하는 경우에도 여전히 포그라운드 디스패치에 사용됩니다.

Android Beam을 사용 설정하려면 다음과 같이 하세요.

  1. NdefRecord가 포함된 NdefMessage 만들기 한 개 또는 한 개의 주소만 포함합니다.
  2. NdefMessagesetNdefPushMessage()를 호출하거나 다음 onCreate() 메서드에서 NfcAdapter.CreateNdefMessageCallback 객체를 전달하는 setNdefPushMessageCallback를 호출합니다. 확인할 수 있습니다. 이 메서드에는 Android에서 사용 설정하려는 활동이 하나 이상 필요합니다. 활성화할 다른 활동의 선택적 목록과 함께 Beam.

    일반적으로 활동이 다음 작업만 필요한 경우 setNdefPushMessage()를 사용합니다. 두 장치가 통신 범위 내에 있을 때 항상 동일한 NDEF 메시지를 푸시합니다. 당신이 사용하는 다음 조건을 충족하는 경우 setNdefPushMessageCallback 애플리케이션의 현재 컨텍스트를 중요하게 여기고 NDEF 메시지를 푸시하려고 함 사용자가 애플리케이션에서 수행하는 작업에 따라 달라질 수 있습니다

다음 샘플은 간단한 활동이 다음의 onCreate() 메서드에서 NfcAdapter.CreateNdefMessageCallback를 호출하는 방법을 보여줍니다. 활동 (AndroidBeamDemo 참고) 를 참조하세요. 이 예에는 MIME 레코드를 만드는 데 도움이 되는 메서드도 있습니다.

Kotlin

package com.example.android.beam

import android.app.Activity
import android.content.Intent
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.nfc.NfcAdapter.CreateNdefMessageCallback
import android.nfc.NfcEvent
import android.os.Bundle
import android.os.Parcelable
import android.widget.TextView
import android.widget.Toast
import java.nio.charset.Charset

class Beam : Activity(), NfcAdapter.CreateNdefMessageCallback {
    
    private var nfcAdapter: NfcAdapter? = null
    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        textView = findViewById(R.id.textView)
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show()
            finish()
            return
        }
        // Register callback
        nfcAdapter?.setNdefPushMessageCallback(this, this)
    }

    override fun createNdefMessage(event: NfcEvent): NdefMessage {
        val text = "Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis()
        return NdefMessage(
                arrayOf(
                        createMime("application/vnd.com.example.android.beam", text.toByteArray())
                )
                /**
                 * The Android Application Record (AAR) is commented out. When a device
                 * receives a push with an AAR in it, the application specified in the AAR
                 * is guaranteed to run. The AAR overrides the tag dispatch system.
                 * You can add it back in to guarantee that this
                 * activity starts when receiving a beamed message. For now, this code
                 * uses the tag dispatch system.
                 *///,NdefRecord.createApplicationRecord("com.example.android.beam")
        )
    }

    override fun onResume() {
        super.onResume()
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
            processIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent)
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    private fun processIntent(intent: Intent) {
        textView = findViewById(R.id.textView)
        // only one message sent during the beam
        intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMsgs ->
            (rawMsgs[0] as NdefMessage).apply {
                // record 0 contains the MIME type, record 1 is the AAR, if present
                textView.text = String(records[0].payload)
            }
        }
    }
}

자바

package com.example.android.beam;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.Charset;


public class Beam extends Activity implements CreateNdefMessageCallback {
    NfcAdapter nfcAdapter;
    TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.textView);
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        // Register callback
        nfcAdapter.setNdefPushMessageCallback(this, this);
    }

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        String text = ("Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis());
        NdefMessage msg = new NdefMessage(
                new NdefRecord[] { createMime(
                        "application/vnd.com.example.android.beam", text.getBytes())
         /**
          * The Android Application Record (AAR) is commented out. When a device
          * receives a push with an AAR in it, the application specified in the AAR
          * is guaranteed to run. The AAR overrides the tag dispatch system.
          * You can add it back in to guarantee that this
          * activity starts when receiving a beamed message. For now, this code
          * uses the tag dispatch system.
          */
          //,NdefRecord.createApplicationRecord("com.example.android.beam")
        });
        return msg;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    void processIntent(Intent intent) {
        textView = (TextView) findViewById(R.id.textView);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        textView.setText(new String(msg.getRecords()[0].getPayload()));
    }
}

이 코드는 삭제할 수 있는 AAR을 주석 처리합니다. AAR을 사용 설정하면 AAR에 지정된 애플리케이션은 항상 Android Beam 메시지를 수신합니다. 애플리케이션이 Google Play가 애플리케이션을 다운로드하기 시작합니다. 따라서 다음 인텐트는 Android 4.0 이상 기기에서는 AAR이 사용되는 경우 기술적으로 필터가 필요하지 않습니다.

<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>

이 인텐트 필터를 사용하면 이제 com.example.android.beam 애플리케이션을 시작할 수 있습니다. NFC 태그를 스캔하거나 AAR이 있는 Android Beam을 수신할 때 com.example.android.beam 유형 또는 NDEF 형식의 메일에 MIME 레코드가 포함된 경우 (유형: application/vnd.com.example.android.beam).

AAR은 애플리케이션의 시작 또는 다운로드를 보장하지만 인텐트 필터는 을(를) 사용할 수 있으므로 추천 탭에서 선택한 활동을 항상 AAR에 의해 지정된 패키지 내에서 기본 Activity를 시작하는 대신 애플리케이션을 실행합니다. AAR에는 활동 수준의 세분성이 없습니다. 또한 일부 Android 지원 기기는 AAR을 지원하는 경우 NDEF의 첫 번째 NDEF 레코드에 식별 정보를 포함해야 합니다. 만일의 경우에 대비해 메시지와 필터를 설정할 수도 있습니다. 공통 생성하기 NDEF 레코드 유형을 참조하세요.