프로그래밍/Android

[Android] Ndef 읽기 쓰기

흔한티벳여우 2020. 9. 15. 18:07
반응형

이번에는 NFC를 이용하여 Ndef Message를 NFC에 읽고 쓰는 방법에 대해 알아봅시다.

 

일단 안드로이드에서 Empty Project를 하나 생성합니다.

 

AndroidManifest.xml 을 열고 <aplication /> 위쪽에 다음과 같은 내용을 넣습니다.

<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />

문법의 설명처럼 NFC의 권한을 넣고, 하드웨어에서 NFC 기능이 필요하다 라고 명시해 놓은겁니다.

 

package com.antoine.ndef

import android.app.PendingIntent
import android.content.Intent
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.Ndef
import android.nfc.tech.NdefFormatable
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.io.IOException

class MainActivity : AppCompatActivity() {
    private var TAG: String = "MainActivity"
    private lateinit var nfcPendingIntent: PendingIntent
    private lateinit var nfcAdapter: NfcAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        nfcPendingIntent = PendingIntent.getActivity(
                this, 0,
                Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0
        )
    }

    override fun onResume() {
        super.onResume()
        nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, null, null);
    }

    override fun onPause() {
        super.onPause()
        nfcAdapter.disableForegroundDispatch(this);
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        val detectedTag : Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        val writeValue : String = "http://www.naver.com";
        val message: NdefMessage = createTagMessage(writeValue);

        writeTag(message, detectedTag);
    }

    private fun createTagMessage(msg: String): NdefMessage {
        return NdefMessage(NdefRecord.createUri(msg))
    }

    fun writeTag(message: NdefMessage, tag: Tag) {
        val size = message.toByteArray().size
        try {
            val ndef = Ndef.get(tag)
            if (ndef != null) {
                ndef.connect()
                if (!ndef.isWritable) {
                    Toast.makeText(applicationContext, "can not write NFC tag", Toast.LENGTH_SHORT).show()
                }
                if (ndef.maxSize < size) {
                    Toast.makeText(applicationContext, "NFC tag size too large", Toast.LENGTH_SHORT).show()
                }
                ndef.writeNdefMessage(message)
                Toast.makeText(applicationContext, "NFC tag is writted", Toast.LENGTH_SHORT).show()
            }
        } catch (e: Exception) {
            Log.i(TAG,e.message);
        }
    }
}

 

이제 NFC를 찍으면 onNewIntent가 호출되고 Tag정보와 우리가 쓰기를 원하는 Message정보를 writeTag 함수에서 처리하게 됩니다.

정상적으로 NFC Tag가 입력되면 "NFC tag is writted" 라는 Toast가 발생됩니다.

 

반대로 읽기를 해봅시다.

override fun onNewIntent(intent: Intent) {
	super.onNewIntent(intent)

	if (intent.action == NfcAdapter.ACTION_NDEF_DISCOVERED){
    	val messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
        if (messages == null){
        	return
		}

		for (i in messages.indices) showMsg(messages[i] as NdefMessage)
	}
}

fun showMsg(mMessage: NdefMessage) {
	val recs = mMessage.records
    for (i in recs.indices) {
    	val record = recs[i]
        if (Arrays.equals(record.type, NdefRecord.RTD_URI)) {
        	val u: Uri = record.toUri()
            val j = Intent(Intent.ACTION_VIEW)
            j.data = u
            startActivity(j)
            finish()
		}
	}
}

 

반응형