TÌM HIỂU NFC TRÊN ANDROID: PHẦN 2

Tìm hiểu NFC trên Android: Phần 2

Tìm hiểu NFC trên Android: Phần 1

Trong bài trước chúng ta đã tìm hiểu tổng quan về công nghệ NFC trên Android, những ứng dụng thực tế của nó trong đời sống và demo sử dụng 2 thiết bị Android để truyền dữ liệu giữa 2 máy (Android to Android – P2P).

Trong phần này chúng ta tập trung vào việc làm thế nào để có thể đọc và ghi (read and write) dữ liệu trên 1 thẻ NFC (NFC Tag)!

Trên Android OS hỗ trợ các tiêu chuẩn của thẻ (NFC tag) và các lớp đại điện để làm việc với chúng trong bảng sau

Table 1. Các công nghệ thẻ được hỗ trợ

Các lớp Mô tả
TagTechnology Cài đặt interface này để có thể truy cập vào các công nghệ khác nhau và khả năng của chúng (nfc tag)
NfcA Cung cấp truy cập tới tiêu chuẩn NFC_A (ISO 14443-3A) và các hoạt động IO
NfcB Cung cấp truy cập tới tiêu chuẩn NFC-B (ISO 14443-3B) và các hoạt động IO
NfcF Cung cấp truy cập tới tiêu chuẩn NFC-F (JIS 6319-4) và các hoạt động IO
NfcV Cung cấp truy cập tới tiêu chuẩn NFC-V (ISO 15693) và các hoạt động IO
IsoDep Cung cấp truy cập tới tiêu chuẩn ISO-DEP (ISO 14443-4) và các hoạt động IO
Ndef Cung cấp truy cập tới các phương thức và dữ liệu NDEF trên thẻ NFC đã được định dạng (format) như NDEF
NdefFormatable Cũng cấp các phương thức để định dạng thẻ dưới dạng NDEF

Trong khuôn khổ bài này chúng ta demo làm việc với thẻ được định dạng dưới dạng NDEF (tiêu chuẩn của NFC forum như trong bài trước đã nói).

Ứng dụng demo:

Tên: NfcWriteTag

Chức năng: Ghi dữ liệu tới thẻ NFC và đọc dữ liệu vừa ghi được

Yêu cầu:

  • Điện thoại Android:

  • Android API > 10 ( 2.3.3 – GINGERBREAD_MR1)

  • Hỗ trợ NFC (Enable NFC function )

NFC tags (được định dạng dưới dạng NDEF)

Như trong bài trước chúng ta cài đặt các thuộc tính trong AndroidManifest.xml để có thể nhận dạng được thẻ NFC khi chạm vào thiết bị Android.

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/plain" />
</intent-filter>

Chú ý: Có các 3 loại IntentFilter sau khi làm việc với NFC

Trường Mô tả
String ACTION_NDEF_DISCOVERED Action của Intent để lọc các hành động khi 1 Tag với NDEF payload (nội dung đính kèm) được phát hiện
String ACTION_TAG_DISCOVERED Action của Intent để lọc các hành động khi 1 Tag được phát hiện
String ACTION_TECH_DISCOVERED Action của Intent để lọc các hành động khi 1 tag được phát hiện và các hoạt động đã được đăng ký cho các công nghệ cụ thể trên thẻ

Tiếp theo, trong onCreate() của lớp WriteTagActivity.class chúng cài đặt các đối tượng để làm việc với NFC:

mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter == null) {
    showToast("NFC not available on this device!");
    return;
}
//Register a pending intent to callback to this activity when NFC tag discovered
pendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

 //Filter NDEF Message
IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
ndefDetected.addDataType("text/plain");
nfcIntentFilter = new IntentFilter[] { ndefDetected };

Trong hàm này NfcAdapter là 1 lớp đại diện cho NFC tại thiết bị giúp chúng ta tương tác với NFC.

Chúng ta đăng ký 1 callback cho lớp này sử dụng PendingIntent để nhận dữ liệu khi NFC được phát hiện.

Chúng ta cũng đăng ký 1 bộ lọc để lọc các hoạt động khi NDEF message được gửi tới sử dụng IntentFilter với action NfcAdapter.ACTION_NDEF_DISCOVERED để lọc các hành động khi 1 Tag được phát hiện có đính kèm (payload) các chuỗi (text/plain).

Tiếp theo, trong onResume() chúng ta triển khai các phương thức để phân tích gói tin nhận được khi NFC tag được phát hiện

@Override
protected void onResume() {
  super.onResume();
    //Discovery Tag and clear old intent
    Intent intent = getIntent();
    discoveryTag(intent);
    enableNdefWriteMode();

}

discoveryTag() triển khai phân tích gói tin để nhận về payload

private void discoveryTag(Intent intent) {
		//NFC tag discovered
		if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
			NdefMessage[] mess = getNdefMessages(intent);
			String payload = new String(mess[0].getRecords()[0].getPayload());
			//Turn Light ON
			if(LIGHT_TAG.equals(payload)) {
				imgLight.setImageResource(R.drawable.light_on);
			}

			showToast(payload);
			setIntent(new Intent());
		}
	}

Cuối cùng, chúng ta muốn ghi dữ liệu trên thẻ NFC khi chúng được phát hiện, chúng ta triển khai trong hàm onNewIntent() (được gửi tới khi đăng ký sử IntentFilter với action FLAG_ACTIVITY_SINGLE_TOP)

@Override
protected void onNewIntent(Intent intent) {

	Log.d("NFC_TAG", "onNewIntent > " + intent.getAction());
	 if (isWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))     {
		Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
		NdefMessage message = getTagAsNdef();
		boolean success = writeTag(message, detectedTag);
		if(success) {
			showToast("Write NFC Success");
		} else {
			showToast("Write NFC Failed");
		}

		isWriteMode = false;
	}

}

Chúng ta lấy về đối tượng Tag đại diện cho thẻ được phát hiện, sau đó tổng hợp 1 nội dung message (NDEF message) qua phương thức getTagAsNdef() để ghi dữ liệu vào thẻ.

GetTagAsNdef(): Tổng hợp NDEF message để ghi vào NFC tag

private NdefMessage getTagAsNdef() {
	String uniqueId = LIGHT_TAG;//String value
	byte[] payload = uniqueId.getBytes(Charset.forName("US-ASCII"));
	NdefRecord rtdUriRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
			NdefRecord.RTD_TEXT, new byte[0], payload);
	return new NdefMessage(new NdefRecord[] { rtdUriRecord });
}

writeTag(): Ghi dữ liệu lên thẻ được phát hiện

public boolean writeTag(NdefMessage message, Tag tag) {
        int size = message.toByteArray().length;
        String mess = "";

        try {
            Ndef ndef = Ndef.get(tag);
            if (ndef != null) {
                ndef.connect();

                if (!ndef.isWritable()) {
                	showToast("Tag is read-only");
                    return false;

                }
                if (ndef.getMaxSize() < size) {
                    mess = "Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size
                            + " bytes.";
                	showToast(mess);
                    return false;
                }
                //Write NDEF Message to TAG
                ndef.writeNdefMessage(message);
                return true;
            } else {
                NdefFormatable format = NdefFormatable.get(tag);
                if (format != null) {
                    try {
                        format.connect();
                        format.format(message);
                        mess = "Formatted tag and wrote message";
                        showToast(mess);
                        return false;
                    } catch (IOException e) {
                        mess = "Failed to format tag.";
                        showToast(mess);
                        return false;
                    }
                } else {
                    mess = "Tag doesn't support NDEF.";
                    showToast(mess);
                    return false;
                }
            }
        } catch (Exception e) {
            mess = "Failed to write tag";
            showToast(mess);
            return false;
        }
    }

Full Source Code: NfcWriteTag

Một số hình ảnh:

nfcnfc

Tham khảo:


All Rights Reserved