본문 바로가기

안드로이드/JAVA

[JAVA] NFC Reader, Writer example

728x90

 

https://developer.android.com/guide/topics/connectivity/nfc?hl=ko 

 

NFC(근거리 무선통신) 개요  |  Android 개발자  |  Android Developers

NFC(근거리 무선통신) 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. NFC(근거리 무선통신)는 단거리 무선 기술로, 일반적으로 연결을 시작하려면 거리

developer.android.com

 

 

 

AndroidManifest.xml 은 기본

<uses-permission android:name="android.permission.NFC" />

 

NFC Reader

public class MainActivity extends AppCompatActivity {

    private NfcAdapter nfcAdapter;
    private PendingIntent pendingIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // NFC Adapter 가져오기
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);

        // PendingIntent 설정
        Intent intent = new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // NFC Foreground Dispatch 설정
        if (nfcAdapter != null) {
            nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // NFC Foreground Dispatch 해제
        if (nfcAdapter != null) {
            nfcAdapter.disableForegroundDispatch(this);
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        // NFC 태그 읽기 작업 수행
        String nfcText = readNfcTag(intent);
        if (nfcText != null) {
            Toast.makeText(this, "Read NFC Tag: " + nfcText, Toast.LENGTH_LONG).show();
        }
    }

    // NFC 태그 읽기 메서드
    private String readNfcTag(Intent intent) {
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            Ndef ndef = Ndef.get((Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
            if (ndef != null) {
                try {
                    ndef.connect();
                    NdefMessage ndefMessage = ndef.getNdefMessage();
                    NdefRecord[] records = ndefMessage.getRecords();
                    if (records != null && records.length > 0) {
                        NdefRecord record = records[0];
                        String payload = new String(record.getPayload(), StandardCharsets.UTF_8);
                        return payload;
                    }
                } catch (IOException | FormatException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        ndef.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }
}

 

NFC Writer

public class MainActivity extends AppCompatActivity {

    private NfcAdapter nfcAdapter;
    private PendingIntent pendingIntent;
    private IntentFilter[] writeTagFilters;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // NFC 어댑터 가져오기
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC not supported on this device", Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        // 인텐트 설정
        Intent intent = new Intent(this, getClass());
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        // 인텐트 필터 설정
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        writeTagFilters = new IntentFilter[] { tagDetected };
    }

    @Override
    protected void onResume() {
        super.onResume();
        nfcAdapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null);
    }

    @Override
    protected void onPause() {
        super.onPause();
        nfcAdapter.disableForegroundDispatch(this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
            // NFC 태그가 감지되었을 때, NDEF 메시지를 작성하여 태그에 씁니다.
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            NdefMessage message = createNdefMessage();
            writeTag(tag, message);
        }
    }

    private void writeTag(Tag tag, NdefMessage message) {
        try {
            Ndef ndefTag = Ndef.get(tag);
            if (ndefTag == null) {
                // 태그가 NDEF 형식이 아닐 경우, NDEF 메시지를 작성하고 태그를 포맷
                NdefFormatable formatableTag = NdefFormatable.get(tag);
                if (formatableTag != null) {
                    formatableTag.connect();
                    formatableTag.format(message);
                    formatableTag.close();
                    Toast.makeText(this, "Tag formatted and written successfully.", Toast.LENGTH_LONG).show();
                } else {
                    // 태그가 포맷 가능한 형식이 아닐 경우, 작업을 취소하고 오류 메시지를 표시
                    Toast.makeText(this, "Tag is not NDEF formatable.", Toast.LENGTH_LONG).show();
                    return;
                }
            } else {
                // 태그가 이미 NDEF 형식일 경우, 메시지를 씁니다.
                ndefTag.connect();
                if (ndefTag.isWritable()) {
                    ndefTag.writeNdefMessage(message);
                    Toast.makeText(this, "Tag written successfully.", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(this, "Tag is read-only.", Toast.LENGTH_LONG).show();
                }
                ndefTag.close();
            }
        } catch (Exception e) {
            Toast.makeText(this, "Failed to write tag.", Toast.LENGTH_LONG).show();
        }
    }

   private NdefMessage getNdefMessage(String message) {
    byte[] textBytes = message.getBytes();
    NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], textBytes);
    NdefMessage ndefMessage = new NdefMessage(new NdefRecord[] {textRecord});
    return ndefMessage;
}

private void writeNdefMessage(Tag tag, NdefMessage ndefMessage) {
    try {
        if (tag == null) {
            Toast.makeText(this, "Tag object cannot be null", Toast.LENGTH_SHORT).show();
            return;
        }

        Ndef ndef = Ndef.get(tag);
        if (ndef == null) {
            // Tag is not NDEF formatted
            NdefFormatable ndefFormatable = NdefFormatable.get(tag);
            if (ndefFormatable != null) {
                try {
                    ndefFormatable.connect();
                    ndefFormatable.format(ndefMessage);
                    Toast.makeText(this, "Tag written successfully", Toast.LENGTH_SHORT).show();
                } catch (IOException e) {
                    Toast.makeText(this, "Error formatting tag", Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }
            } else {
                Toast.makeText(this, "Tag is not compatible with NDEF", Toast.LENGTH_SHORT).show();
            }
            return;
        }

        ndef.connect();
        if (!ndef.isWritable()) {
            Toast.makeText(this, "Tag is read-only", Toast.LENGTH_SHORT).show();
            ndef.close();
            return;
        }

        ndef.writeNdefMessage(ndefMessage);
        Toast.makeText(this, "Tag written successfully", Toast.LENGTH_SHORT).show();
        ndef.close();
    } catch (Exception e) {
        Toast.makeText(this, "Error writing tag", Toast.LENGTH_SHORT).show();
        e.printStackTrace();
    }
}
}

NFC 태그에 NDEF 메시지를 쓰는 기능을 구현

getNdefMessage() 메서드를 사용하여 문자열 메시지를 NDEF 메시지로 변환하고, writeNdefMessage() 메서드를 사용하여 NDEF 메시지를 NFC 태그에 write한다.

NFC 태그가 이미 NDEF 형식으로 되어 있으면 Ndef.writeNdefMessage() 메서드를 사용하여 쓰기를 시도하고, 그렇지 않은 경우 NdefFormatable.format() 메서드를 사용하여 NDEF 형식으로 포맷한 후에 쓰기를 시도한다.

쓰기 작업이 성공적으로 완료되면, "Tag written successfully" 메시지가 표시된다

 

728x90