Tutorial – NFC trên Android: Phần 1

NFC: Near Field Communication ( Giao tiếp tầm gần)

Tìm hiểu công nghệ giao tiếp tầm gần (ngắn) NFC trong Android

1. NFC là gì?

Là một công nghệ giao tiếp tầm gần (NFC) được phát triển dựa trên nguyên lý tần số vô tuyến nhận dạng (Radio-frequency identification - RFID) cho phép một gởi sóng radio đến một thẻ điện tử thụ động. NFC là một tập hợp các chuẩn cho các smartphones và các thiết bị tương tự để thiết lập liện lạc qua sóng vô tuyến với nhau bằng cách chạm chúng lại với nhau trong khoảng cách gần (một vài cm).

Google giới thiệu NFC vào năm 2010 và smartphone Nexus S trở thành thiết bị Android đầu tiên được hỗ trợ NFC.

Trên Android 4.0 (Ice Cream Sandwich) tính năng này được đặt tên là Android Beam giúp mở rộng khả năng kết nối và chia sẻ dữ liệu.

Tổng quan về NFC

Đặc điểm:

  • Near Field Communication

  • Là Công nghệ không dây tương tự như Bluetooth, Wifi

  • Truyền dữ liệu không dây tằm ngắn (từ 1-4 cm trên smartphones)

  • Low speed – Tốc độ truyền tải chậm ( 106 đến 414 kbps)

  • Thiết lập tương tác thấp (no discovery, no pairing)

  • Tương tác được với các thiết bị thu phát thụ động (không cần nguồn điện)

Dữ liệu có thể truyển tải:

  • Text
  • URL
  • Danh bạ (Contact info)
  • Media files ( bài hát, hình ảnh, video …)

Ứng dụng thực tế:

  • Chia sẻ tập tin

  • Làm thẻ kinh doanh điện tử (Electronic business card)

  • Chơi game trên di động: kết nối giữa 2 hay nhiều thiết bị để cùng chơi.

  • Mở rộng kết nối ( Android Beam: Sử dụng để kích hoạt Bluetooth, Wifi Direct để chia sẻ dữ liệu một cách nhanh chóng)

Ưu điểm:

  • Thiết lập kết nối dễ dàng (không phát hiện, không ghép nối)

  • Triển khai rẻ, chức năng giống như QR Codes

  • Yếu điểm:

  • Khoảng cách giao tiếp ngắn

  • Bảo mật kém

2. Demo sử dụng NFC API Framework trên Android

Dữ liệu được lưu trữ trong thẻ (tag) có thẻ được ghi bằng nhiều định dạng. Nhưng trong Android Framework API nó chỉ dựa trên một chuẩn của NFC Forum là NDEF (NFC Data Exchange Format)

Tiêu chuẩn của NDEF Message:

Standards – NDEF

Trên Android đối tượng NDEF message là 1 định dạng nhị phân được sử dụng để đóng gói các dữ liệu được định kiểu. Nó được quy định bởi NFC Forum cho việc truyền tải và lưu trữ với NFC.

NDEF định nghĩa các Messages và các Records. Đối tượng NDEF Record chứa đựng dữ liệu được định kiểu như MIME-type media, URI, hoặc một nội dung (payload) được tuỳ chỉnh.

DEMO được chia làm 2 Part

Part 1: Demo P2P (Android to Android) để chia sẻ text giữa 2 ứng dụng

Part 2: Write NFC tags (Sử dụng Android devices để ghi dữ liệu trên tag NFC)

PART 1:

Ứng dụng demo:

Tên: Sticky Notes

Chức năng: Truyền dữ liệu (text) qua lại giữa 2 điện thoại có hỗ trợ NFC

Yêu cầu:

  • Điện thoại Android:

  • Android API > 10 ( 2.3.3 – GINGERBREAD_MR1) Hỗ trợ NFC (Enable NFC function on both devices)

Coding:

Bắt đầu làm việc với NFC trên Android, triển khai NfcAdapter - lớp đại diện cho NFC trên device:

Trong phương thức (PT) onCreate() của lớp StickyNotesActivity:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mNote = (EditText) findViewById(R.id.note);
    mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

    if(mNfcAdapter == null) {
    mNote.setText("NFC not available on this device!");
    return;
    }

    //Add listener for EditText when text changed
    mNote.addTextChangedListener(mTextWatcher);

    // Handle all of our received NFC intents in this activity.
    mNfcPendingIntent = PendingIntent.getActivity(this, 0,
    new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

    // Intent filters for reading a note from a tag or exchanging over p2p (android to android).
    IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
    try {
        ndefDetected.addDataType("text/plain");
    } catch (MalformedMimeTypeException e) {
        e.printStackTrace();
    }
        mNdefExchangeFilters = new IntentFilter[] { ndefDetected };
}

Trong phương thức (PT) này triển khai những thứ cần thiết để cho p2p làm việc.

  • mNfcPendingIntent: là một PendingIntent để dẫn xuất tới chính activity StickyNotesActivity, với flag FLAG_ACTIVITY_SINGLE_TOP để sử dụng với PT onNewIntent().

  • ndefDetected: là IntentFilter chỉ lọc các hành động gửi NDEF message (NfcAdapter.ACTION_NDEF_DISCOVERED) với MIME type “text/plain“, vì vậy khi intent này được gửi đến, chúng ta sẽ lấy được nội dung message (payload).

Tiếp theo để cho phép gửi và nhận NDEF message, chúng ta tạo PT enableNdefExchangeMode() trong onResume():

private void enableNdefExchangeMode() {
    if(mNfcAdapter == null) { return; }

    if(Build.VERSION.SDK_INT < 14) {
    mNfcAdapter.enableForegroundNdefPush(this, getNoteAsNdef());
    } else {
    mNfcAdapter.setNdefPushMessage(getNoteAsNdef(), this);
    }

    /* Register foreground dispatch to handler notes from inside our application
    * This will give give priority to the foreground activity when dispatching a discovered Tag to an application. */
    mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mNdefExchangeFilters, null);
}

PT này cho phép thiết bị khởi tạo kết nối ngang hàng peer to peer (p2p) thông qua NFC.

  • enableForegroundNdefPush() sẽ gửi NDEF message (getNoteAsNdef()) tới thiết bị khác.

  • enableForegroundDispatch() cài đặt sự kiện lắng nghe (listener) cho intent và lọc hành động gửi NDEF message (NfcAdapter.ACTION_NDEF_DISCOVERED).

Sau khi nhận được message PT onNewIntent() được gọi:

protected void onNewIntent(Intent intent) {
    // NDEF exchange mode
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
    NdefMessage[] msgs = getNdefMessages(intent);
    //Replace current text with new pay-load
    promptForContent(msgs[0]);
    }
}

Tại đây chúng nhận về NDEF message qua PT getNdefMessages() và phân tích chúng qua PT promptForContent() để nhận nội dung (payload) được gửi tới.

Giải thích các PT:

getNoteAsNdef(): Cài đặt NDEF message để gửi đi

private NdefMessage getNoteAsNdef() {
    byte[] textBytes = mNote.getText().toString().getBytes();
    NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "text/plain".getBytes(),
    new byte[] {}, textBytes);
    return new NdefMessage(new NdefRecord[] {
    textRecord
});

}

  • textBytes: Mảng byte lưu dữ liệu (text) được nhập vào từ một EditText. Sau đó được đưa vào NdefRecord và đẩy vào NdefMessage.

promptForContent(NdefMessage[]):Thông báo tới người dùng để thay thế nội dung hiện tại thành nội dung (pay-load) được gửi tới

private void promptForContent(final NdefMessage msg) {
    new AlertDialog.Builder(this).setTitle("Replace current content?")
    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface arg0, int arg1) {
        String msgPayload = "Messages Received: \n";
        msgPayload += new String(msg.getRecords()[0].getPayload());
        String body = new String(msgPayload);
        setNoteBody(body);
    }
    })
    .setNegativeButton("No", null).show();
}

getNdefMessages(): Lấy về NDEF message từ Intent

private NdefMessage[] getNdefMessages(Intent intent) {
    // Parse the intent
    NdefMessage[] msgs = null;
    String action = intent.getAction();

    //when a tag with NDEF pay-load is discovered.
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsgs != null) {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; i++) {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }
        } else {
                // Unknown tag type
                byte[] empty = new byte[] {};
                NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
                NdefMessage msg = new NdefMessage(new NdefRecord[] {
                record
                });
                msgs = new NdefMessage[] {msg};
            }
            } else {
                Log.d(TAG, "Unknown intent.");
                finish();
            }
    return msgs;
}

Cuối cùng thêm permission để cho phép ứng dụng sử dụng NFC

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

Và thêm IntentFilter cho lớp StickyNotesActivity để lọc hành động gửi NDEF message:

<activity
android:name=".StickyNotesActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- Handle notes detected from outside our application -->
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="text/plain" />
</intent-filter>
</activity>

Mã nguồn : StickyNotes_NFC

Một số hình ảnh DEMO:

nfcnfc

Phần tiếp theo:

Part 2: Write NFC tags (Sử dụng Android devices để ghi dữ liệu trên tag NFC)

Tham khảo:


All Rights Reserved