1. 在<Android 学习操作NFC 1>说明了Android在处理NFC tag的机制、tag dispatch system的运作流程,以及三种
    ACTION_NDEF_DISCOVEREDACTION_TECH_DISCOVEREDACTION_TAG_DISCOVERED的处理方式与intent filter注册方法。
    该篇主要针对如何处理ACTION_NDEF_DISCOVEREDReaderWriter进行说明。
    首先说明如何撰写常用的NDEF Records
    Creating Common Types of NDEF Records
    上一篇介绍简单Reader的方式,该篇先由Write tag开始。因此,如果今天应用程序使用Android 4.0(API Level 14)使用createUri()
    的方法帮助自动建立一个URI records;使用Android 4.1(API level 16)则可透过createExternal()与createMime()帮助建立MIME
    external typeNDEF records。藉由使用这些方法以协助建立NDEF records
    以下便介绍操作NDEF message的第一个Record,来写入资料至NFC tagBeaming
    A. TNF_ABSOLUTE_URI
    建议使用RTD_URI类型取代TNF_ABSOLUTE_URI,因为RTD_URI是更有效的。
    Write:建立一个TNF_ABSOLUTE_URINdef record
  1. // 建立个NdefRecord,指定type与payload
  2. NdefRecord uriRecord = new NdefRecord(
  3. NdefRecord.TNF_ABSOLUTE_URI ,
  4. " http://developer.android.com/index.html ".getBytes(Charset.forName("US-ASCII")),
  5. new byte[0],
  6. new byte[0]);
  7. Read:定义intent filter取得Ndef record
  8. <intent-filter>
  9. <action android:name="android.nfc.action.NDEF_DISCOVERED" />
  10. <category android:name="android.intent.category.DEFAULT" />
  11. <data android:scheme="http"
  12. android:host="developer.android.com"
  13. android:pathPrefix="/index.html" />
  14. </intent-filter>
  1. 注册的Intent Filter只有在tag dispatch system侦测到对应的Ndef tag时才会触发。
    B. TNF_MIME_MEDIA
    Write
    (1) 建立一个TNF_MIME_MEDIA Ndef record:使用createMime()方法;(但仅在Android 4.1(API Level 16)以后才支援)
    // 指定MIME类型,再将内容转成byte[]
  1. NdefRecord mimeRecord = NdefRecord.createMime(
  2. "application/vnd.com.example.android.beam",
  3. "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));

(2) 建立一个TNF_MIME_MEDIA:使用NdefRecord对象:
// 指定Type、MIME Type与payload

  1. NdefRecord mimeRecord = new NdefRecord(
  2. NdefRecord.TNF_MIME_MEDIA ,
  3. "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
  4. new byte[0],
  5. "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));

Read:读取MIME:

  1. <intent-filter>
  2. <action android:name="android.nfc.action.NDEF_DISCOVERED" />
  3. <category android:name="android.intent.category.DEFAULT" />
  4. <!-- 定义要处理的MIME Type -->
  5. <data android:mimeType="application/vnd.com.example.android.beam" />
  6. </intent-filter>

C. TNF_WELL_KNOWN with RTD_TEXT:
Write:建立一个TNF_WELL_KNOWN的Ndef record:

  1. public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
  2. // 取得默认的编码格式
  3. byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
  4. // 准备转换成UTF-8的编码
  5. Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
  6. // 将内容依默认编码转成byte[]
  7. byte[] textBytes = payload.getBytes(utfEncoding);
  8. // 往下做字符转换的位移
  9. int utfBit = encodeInUtf8 ? 0 : (1 << 7);
  10. char status = (char) (utfBit + langBytes.length);
  11. byte[] data = new byte[1 + langBytes.length + textBytes.length];
  12. data[0] = (byte) status;
  13. System.arraycopy(langBytes, 0, data, 1, langBytes.length);
  14. System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
  15. // 建立TNF_WELL_KNOWN的Ndef record
  16. NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
  17. NdefRecord.RTD_TEXT, new byte[0], data);
  18. return record;
  19. }

Read:定义intent filter取得数据:

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

D. TNF_WELL_KNOWN with RTD_URI:
Write:建立TNF_WELL_KNOWN Ndef record,内容有RTD_URI;其方式与建立RTD_URI相似有分成二个:
(1) 建立URI有二个方式,一个由String –> URI;另一个是直接用URI对象,如下:

  1. NdefRecord rtdUriRecord1 = NdefRecord.createUri(" http://example.com ");
  2. // 上下为相同效果
  3. Uri uri = new Uri(" http://example.com ");
  4. NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
  5. byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII"));
  6. //add 1 for the URI Prefix
  7. byte[] payload = new byte[uriField.length + 1];
  8. //prefixes http://www. to the URI
  9. byte payload[0] = 0x01;
  10. //appends URI to payload
  11. System.arraycopy(uriField, 0, payload, 1, uriField.length);
  12. NdefRecord rtdUriRecord = new NdefRecord(
  13. NdefRecord.TNF_WELL_KNOWN,
  14. NdefRecord.RTD_URI,
  15. new byte[0],
  16. payload);

Read:定义要处理的intent filter:

  1. <intent-filter>
  2. <action android:name="android.nfc.action.NDEF_DISCOVERED" />
  3. <category android:name="android.intent.category.DEFAULT" />
  4. <data android:scheme="http"
  5. android:host="example.com"
  6. android:pathPrefix="" />
  7. </intent-filter>

E. TNF_EXTERNAL_TYPE:
Write:使用createExternal()方法;或使用NdefRecord的方法手动建立;

  1. //assign to your data
  2. byte[] payload;
  3. //usually your app's package name
  4. String domain = "com.example";
  5. String type = "externalType";
  6. // 指定domain, type, payload
  7. NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
  8. byte[] payload;
  9. ...
  10. // 注意写入的格式为: {domain}:{type}
  11. NdefRecord extRecord = new NdefRecord(
  12. NdefRecord.TNF_EXTERNAL_TYPE,
  13. "com.example:externalType",
  14. new byte[0],
  15. payload);

Read:注册要处理的intent filter:

  1. <intent-filter>
  2. <action android:name="android.nfc.action.NDEF_DISCOVERED" />
  3. <category android:name="android.intent.category.DEFAULT" />
  4. <data android:scheme="vnd.android.nfc"
  5. android:host="ext"
  6. android:pathPrefix="/com.example:externalType"/>
  7. </intent-filter>

使用TNF_EXTERNAL_TYPE是比较好用于一般的NFC tag,以支持Android或非Android系统可以读取到这些Tag。
另外,要注意TNF_EXTERNAL_TYPE的URNs定义格式,如下:「urn:nfc:ext:example.com:externalType」;
根据NFC Forum RTD规格宣告[urn:nfc:ext]在某些Ndef message会被省略掉,因此,需要额外定义 domain (例如:example.com)与
type (例如:externalType)。当dispatching TNF_EXTERNAL_TYPE时,Android转换 run:nfc:ext:example.com:externalType URN为
vnd.andorid.nfc://ext/example.com:externalType的URI,所以在定义intent filter时,在scheme为:vnd.android.nfc;host为ext;
patchPrefix为/example.com:externalType。
以上介绍了几个常用Ndef message与Ndef record type的撰写方式,需注意的是在Read的部分,在应用程序尚未被启动时,
如果系统侦测到有Ndef Tag,它会发出对应的Intent,让有注册Filter intent接收到这个intent,进一步让用户选择要执行的
应用程序。因此,如果应用程序本身支持多种不同的Filter intent均要记得加上去。
往下针对程序面说明要将上述的内容怎么发布给device或NFC tag。需要有那些重要的类别来加以完成。
参考< http://nfc.android.com/> 中的<StickyNotes sample code>范例来加以说明:
步骤0-1:建立项目,指定使用<uses-sdk />要大于等于10,并且加入必要的<uses-permission />;

  1. <uses-sdk android:minSdkVersion="10" />
  2. <uses-permission android:name="android.permission.NFC"></uses-permission>

步骤0-2:标记默认应用程序要处理的Intent Filter;

  1. <application android:icon="@drawable/icon" android:label="@string/app_name">
  2. <activity android:name=".MainActivity"
  3. android:label="@string/app_name">
  4. <intent-filter>
  5. <action android:name="android.intent.action.MAIN" />
  6. <category android:name="android.intent.category.LAUNCHER" />
  7. </intent-filter>

<!-- 注册在应用程序外,系统所广播出来的intent filter -->

  1. <intent-filter>
  2. <!-- 注册仅处理NDEF Tag,并指定预设启动的Activity与处理的Type -->
  3. <action android:name="android.nfc.action.NDEF_DISCOVERED" />
  4. <category android:name="android.intent.category.DEFAULT" />
  5. <data android:mimeType="text/plain" />
  6. </intent-filter>
  7. </activity>
  8. </application>

注册应用程序要处理的Intent Filter,此部分注册的是应用程序非在前景模式时,如果系统有侦测到NDEF tag发出intent,
应用程序注册了该intent filter则会被触发到,如果有多个注册相同的intent filter则会需要用户进行选择。
步骤1:处理应用程序注册的Intent Filter,透过OnResume()事件进行处理将读取的内容放置画面的EditText中;
1-1. 画面配置:

  1. <RelativeLayout xmlns:android=" http://schemas.android.com/apk/res/android "
  2. xmlns:tools=" http://schemas.android.com/tools "
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context=".MainActivity" >
  10. <LinearLayout
  11. android:id="@+id/linearLayout1"
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"
  14. android:orientation="vertical" >
  15. <Button
  16. android:id="@+id/write_tag"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:text="Write to Tag" >
  20. </Button>
  21. <EditText
  22. android:id="@+idte"
  23. android:layout_width="fill_parent"
  24. android:layout_height="388dp"
  25. android:gravity="top"
  26. android:text="Edit me." >
  27. </EditText>
  28. </LinearLayout>
  29. </RelativeLayout>

放置一个Button与EditText来显示读取到的内容,与负责写入资料至NDEF Tag。
1-2. override处理OnResume()收到由系统送来的intent;

  1. @Override
  2. protected void onResume()
  3. {
  4. super.onResume();
  5. // 处理由Android系统送出应用程序处理的intent filter内容
  6. if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
  7. // 取得NdefMessage
  8. NdefMessage[] messages = getNdefMessages(getIntent());
  9. // 取得实际的内容
  10. byte[] payload = messages[0].getRecords()[0].getPayload();
  11. setNoteBody(new String(payload));
  12. // 往下送出该intent给其他的处理对象
  13. setIntent(new Intent());
  14. }
  15. }

1-3. 拆解从Ndef Tag中取得的原始数据,并且转换成NdefMessage内容;

  1. NdefMessage[] getNdefMessages(Intent intent) {
  2. // Parse the intent
  3. NdefMessage[] msgs = null;
  4. String action = intent.getAction();
  5. // 识别目前的action为何
  6. if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
  7. || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
  8. // 取得parcelabelarrry的资料
  9. Parcelable[] rawMsgs =
  10. intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
  11. // 取出的内容如果不为null,将parcelable转成ndefmessage
  12. if (rawMsgs != null) {
  13. msgs = new NdefMessage[rawMsgs.length];
  14. for (int i = 0; i < rawMsgs.length; i++) {
  15. msgs[i] = (NdefMessage) rawMsgs[i];
  16. }
  17. } else {
  18. // Unknown tag type
  19. byte[] empty = new byte[] {};
  20. NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
  21. NdefMessage msg = new NdefMessage(new NdefRecord[] {
  22. record
  23. });
  24. msgs = new NdefMessage[] {
  25. msg
  26. };
  27. }
  28. } else {
  29. Log.d(TAG, "Unknown intent.");
  30. finish();
  31. }
  32. return msgs;
  33. }
  34. 1-4. 设得资料内容并回写至画面中;
  35. private void setNoteBody(String body) {
  36. Editable text = gNote.getText();
  37. text.clear();
  38. text.append(body);
  39. }

1-5. 让应用程序在前景模式下也能直接处理侦测到的Ndef Tdg,让系统侦测到Ndef Tag时无需再重新启动相同的应用程序;
为了让应用程序在前景也可以处理intent filter,需要建立几个必要的项目:
(1) 宣告PendingIntent:注册让应用程序的Activity负责处理所有接受到的NFC intents:
// 注册让该Activity负责处理所有接收到的NFC Intents。
gNfcPendingIntent = PendingIntent.getActivity(
this, 0,
// 指定该Activity为应用程序中的最上层Activity
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
在onCreate()中建立该PendingIntent,并且将gNfcPendingIntent宣告成全局变量。指定负责的Activity为最上层的Activity。
(2) 宣告IntentFilter[]:注册要在前景处理的Intent Filter类型;
// 建立要处理的Intent Filter负责处理来自Tag或p2p交换的数据。

  1. IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
  2. try {
  3. ndefDetected.addDataType("text/plain");
  4. } catch (MalformedMimeTypeException e) { }
  5. gNdefExchangeFilters = new IntentFilter[] { ndefDetected };

在onCreate()宣告要处理的IntentFilter,指定要处理的Data Type为MIME的文字,最后将IntentFilter加入全局变量的gNdefExchangeFilters。
(3) 覆写onRsume()事件,让Activity启动时启动NfcAdapter支持前景模式下处理NFC Intent;

  1. @Override
  2. protected void onResume()
  3. {
  4. super.onResume();
  5. gResumed = true;
  6. // 处理由Android系统送出应用程序处理的intent filter内容
  7. if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
  8. // 取得NdefMessage
  9. NdefMessage[] messages = getNdefMessages(getIntent());
  10. // 取得实际的内容
  11. byte[] payload = messages[0].getRecords()[0].getPayload();
  12. setNoteBody(new String(payload));
  13. // 往下送出该intent给其他的处理对象
  14. setIntent(new Intent());
  15. }
  16. // 启动前景模式支持Nfc intent处理
  17. enableNdefExchangeMode();
  18. }
  19. /**
  20. * 启动Ndef交换数据模式。
  21. */
  22. private void enableNdefExchangeMode() {
  23. // 让NfcAdapter启动能够在前景模式下进行intent filter的dispatch。
  24. gNfcAdapter.enableForegroundDispatch(
  25. this, gNfcPendingIntent, gNdefExchangeFilters, null);
  26. }

在onResume()中加入enableNdefExchangeMode()方法,里面使用了「gNfcAdapter.enableForegroundDispatch()」方法,
启动NfcAdapter支持前景模式下处理NFC Intent。
(4) 覆写onNewIntent()事件,补捉由其他应用程序或系统发出的Intent进行处理;

  1. @Override
  2. protected void onNewIntent(Intent intent) {
  3. // 覆写该Intent用于补捉如果有新的Intent进入时,可以触发的事件任务。
  4. // NDEF exchange mode
  5. if (!gWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
  6. NdefMessage[] msgs = getNdefMessages(intent);
  7. promptForContent(msgs[0]);
  8. }
  9. }
  10. /**
  11. * 应用程序补捉到Ndef Message,询问用户是否要取代目前画面中的文件。
  12. * @param msg
  13. */
  14. private void promptForContent(final NdefMessage msg) {
  15. new AlertDialog.Builder(this).setTitle("Replace current content?")
  16. .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
  17. @Override
  18. public void onClick(DialogInterface arg0, int arg1) {
  19. String body = new String(msg.getRecords()[0].getPayload());
  20. setNoteBody(body);
  21. }
  22. })
  23. .setNegativeButton("No", new DialogInterface.OnClickListener() {
  24. @Override
  25. public void onClick(DialogInterface arg0, int arg1) {
  26. }
  27. }).show();
  28. }

覆写onNewIntent()事件以补捉当Activity收到系统送来的Intent时可以直接进行处理,不需要重新建立一个新的Activity处理。
直接使用已存在的instance负责,另外增加promptForContent()方法来询问用户如果画面中有数据是否要清除。
完成步骤0至步骤1,即可以完成读取Ndef tag的功能。接下来步骤2要说明的是如何写入text/plain的内容至Ndef tag;
步骤2:要让App可以操作NFC,需要先取得NdefAdapter对象,才能启动写入数据至NFC tag或是其他应用程序;
2-1. 先针对画面中按钮、文字框二个控件,并且分加入对应的Listener;

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState)
  3. {
  4. // ...
  5. // 取得EditText与Button,并且注册对应的事件
  6. findViewById(R.id.write_tag).setOnClickListener(this.gTagWriter);
  7. gNote = (EditText)findViewById(R.id.note);
  8. gNote.addTextChangedListener(gTextWatcher);
  9. // ...
  10. }

a. Button注册OnClickListener(),实作事件以启动写入数据至Tag或应用程序;

  1. private View.OnClickListener gTagWriter = new View.OnClickListener() {
  2. @Override
  3. public void onClick(View v)
  4. {
  5. // 先停止接收任何的Intent,准备写入资料至tag;
  6. disableNdefExchangeMode();
  7. // 启动写入Tag模式,监测是否有Tag进入
  8. enableTagWriteMode();
  9. // 显示对话框,告知将Tag或手机靠近本机的NFC感应区
  10. new AlertDialog.Builder(MainActivity.this)
  11. .setTitle("Touch tag to write")
  12. .setOnCancelListener(new DialogInterface.OnCancelListener() {
  13. @Override
  14. public void onCancel(DialogInterface dialog)
  15. {
  16. // 在取消模式下,先关闭监侦有Tag准备写入的模式,再启动等待数据交换的模式。
  17. // 停止写入Tag模式,代表已有Tag进入
  18. disableTagWriteMode();
  19. // 启动数据交换
  20. enableNdefExchangeMode();
  21. }
  22. }).create().show();
  23. }
  24. };
  25. /**
  26. * 启动Ndef交换数据模式。
  27. */
  28. private void enableNdefExchangeMode()
  29. {
  30. // 让NfcAdatper启动前景Push数据至Tag或应用程序。
  31. gNfcAdapter.enableForegroundNdefPush(MainActivity.this, getNoteAsNdef());
  32. // 让NfcAdapter启动能够在前景模式下进行intent filter的dispatch。
  33. gNfcAdapter.enableForegroundDispatch(this, gNfcPendingIntent, gNdefExchangeFilters, null);
  34. }
  35. private void disableNdefExchangeMode()
  36. {
  37. gNfcAdapter.disableForegroundNdefPush(this);
  38. gNfcAdapter.disableForegroundDispatch(this);
  39. }
  40. /**
  41. * 启动Tag写入模式,注册对应的Intent Filter来前景模式监听是否有Tag进入的讯息。
  42. */
  43. private void enableTagWriteMode()
  44. {
  45. gWriteMode = true;
  46. IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
  47. gWriteTagFilters = new IntentFilter [] {tagDetected};
  48. gNfcAdapter.enableForegroundDispatch(this, gNfcPendingIntent, gWriteTagFilters, null);
  49. }
  50. /**
  51. * 停止Tag写入模式,取消前景模式的监测。
  52. */
  53. private void disableTagWriteMode()
  54. {
  55. gWriteMode = false;
  56. gNfcAdapter.disableForegroundDispatch(this);
  57. }

该按钮主要在点击后,注册对应的Intent Filter:ACTION_TAG_DISCOVERED,为了等待有Nfc Tag进入监侦范围所触发Intent事件,
因此,搭配在onNewIntent()里增加了写识别intent.action进一步将EditText的内容写入Tag中;
但在启动另一个监侦时,记得先将预先监侦的ACTION_NDEF_DISCOVERED先取消,以免冲突。等到onCancel()事件启动时,
再取消ACTION_TAG_DISCOVERED的监侦,重新启动ACTION_NDEF_DISCOVERED的监听。
=>另外需注意在enableNdefExchangedMode()里,也启动了前景模式发送信息至应用程序。
b. EditText注册TextChangedListener(),宣告一个TextWatcher,处理在afterTextChanged()下启动写数据至应用程序;

  1. private TextWatcher gTextWatcher = new TextWatcher() {
  2. @Override
  3. public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
  4. }
  5. @Override
  6. public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
  7. }
  8. @Override
  9. public void afterTextChanged(Editable arg0) {
  10. // 如果是在Resume的状态下,当编辑完后,启动前景发布讯息的功能。
  11. if (gResumed) {
  12. gNfcAdapter.enableForegroundNdefPush(MainActivity.this, getNoteAsNdef());
  13. }
  14. }
  15. };

在afterTextChanged()事件里,先识别目前是否从onResume()进入,如果是将启动NfcAdapter在前景模式推送讯息至其他App。
2-2. 增加onNewIntent()事件,处理当监侦到Ndef Tag时,写入数据至Tag中;

  1. @Override
  2. protected void onNewIntent(Intent intent)
  3. {
  4. // 覆写该Intent用于补捉如果有新的Intent进入时,可以触发的事件任务。
  5. // NDEF exchange mode
  6. if (!gWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
  7. NdefMessage [] msgs = getNdefMessages(intent);
  8. promptForContent(msgs[0]);
  9. }
  10. // 监测到有指定ACTION进入,代表要写入数据至Tag中。
  11. // Tag writing mode
  12. if (gWriteMode && NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
  13. Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
  14. writeTag(getNoteAsNdef(), detectedTag);
  15. }
  16. }

2-3. 写入Ndef数据的方法;

  1. boolean writeTag(NdefMessage message, Tag tag) {
  2. int size = message.toByteArray().length;
  3. try {
  4. Ndef ndef = Ndef.get(tag);
  5. if (ndef != null) {
  6. ndef.connect();
  7. if (!ndef.isWritable()) {
  8. toast("Tag is read-only.");
  9. return false;
  10. }
  11. if (ndef.getMaxSize() < size) {
  12. toast("Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size
  13. + " bytes.");
  14. return false;
  15. }
  16. ndef.writeNdefMessage(message);
  17. toast("Wrote message to pre-formatted tag.");
  18. return true;
  19. } else {
  20. NdefFormatable format = NdefFormatable.get(tag);
  21. if (format != null) {
  22. try {
  23. format.connect();
  24. format.format(message);
  25. toast("Formatted tag and wrote message");
  26. return true;
  27. } catch (IOException e) {
  28. toast("Failed to format tag.");
  29. return false;
  30. }
  31. } else {
  32. toast("Tag doesn't support NDEF.");
  33. return false;
  34. }
  35. }
  36. } catch (Exception e) {
  37. toast("Failed to write tag");
  38. }
  39. return false;
  40. }
  41. private void toast(String text) {
  42. Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
  43. }

writeTag()方法增加了一些判断的逻辑很值得参考。
2-4. 覆写onPasue()事件,让Activity暂停时关闭NfcAdapter的前景模式;

  1. @Override
  2. protected void onPause()
  3. {
  4. super.onPause();
  5. gResumed = false;
  6. // 由于NfcAdapter启动前景模式将相对花费更多的电力,要记得关闭。
  7. gNfcAdapter.disableForegroundNdefPush(this);
  8. }

[范例程序]
======
按照上方的说明应能实作出与NFC tag、应用程序交换数据的范例程序。该文章主要撷录<StickyNotes sample code>的内容,
有更多相关的程序细节还有待补充与了解。如果有撰写错误的地方,也请大家多多指教,谢谢。
References:
NFC Demo – Android sample code
Near Field Communication (重要)
NFC Basics & Advanced NFC
Android NFC 开发教程(1):概述
Android NFC 开发教程(2): ApiDemos->NFC->ForegoundDispatch
Android NFC 开发教程(3): Mifare Tag 读写示例
NFC Programming in Android & [Android] 简单范例: NFC Push
Developer Document & NXP TagWriter & StickyNotes sample code
onNewIntent调用时机 & onNewIntent的应用 & Activity – onNewIntent()
Dotblogs Tags: Android

Android – 学习操作NFC – 2的更多相关文章

  1. 九、Android学习第八天——广播机制与WIFI网络操作(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 九.Android学习第八天——广播机制与WIFI网络操作 今天熟悉了An ...

  2. Android学习一:文件操作

    最近在学习安卓相关的编程,对于一门新技术的学习,我想应该跟其他语言一样吧,如C++和C#,也是文件,网络,多线程以及数据库之类的学习了.所以决定先从文件下手,现在将文件的一点学习列在下面: 1.Jav ...

  3. 最全的android学习资料

    一.开发环境搭建 (已完成) 负责人:kris 状态:已完成 所整理标签为:搭建 SDK JDK NDK Eclipse ADT 模拟器 AVD 调试器(DEBUG) DDMS 测试 日志 Logca ...

  4. Android学习——windows下搭建NDK_r9环境

    1. NDK(Native Development Kit) 1.1 NDK简介 Android NDK是一套允许开发人员使用本地代码(如C/C++)进行Android APP功能开发的工具,通过这个 ...

  5. Android学习第三天-打包常用命令

    在前面<Android学习第一天-adb常用命令>和 <Android学习第二天-android常用命令>两篇博文中,我们重点讲解了adb和android的常用命令,下面我们讲 ...

  6. Android 学习资料收集

    收集整理这份资料灵感来自于 trip_to_iOS, 征得同意引用了该资料的开头描述 收集整理这份资料主要帮助初学者学习 Android 开发, 希望能快速帮助到他们快速入门, 找到适合自己学习资料, ...

  7. 十、Android学习第九天——小结(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 十.Android学习第九天——小结 通过这段时间的学习,今晚上来做个小小 ...

  8. 七、Android学习第六天——SQLite与文件下载(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 七.Android学习第六天——SQLite与文件下载 SQLite SQ ...

  9. 六、Android学习第五天——Handler的使用(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 六.Android学习第五天——Handler的使用 注意:有很多功能是不 ...

随机推荐

  1. DataTable在内存中的使用

    DataTable表示一个与内存有关的数据表,可以使用工具栏里面的控件拖放来创建和使用,也可以在编写程序过程中根据需要独立创建和使用,最常见的情况是作为DataSet的成员使用,在这种情况下就需要用在 ...

  2. 索引器、哈希表Hashtabl、字典Dictionary(转)

    一.索引器 索引器类似于属性,不同之处在于它们的get访问器采用参数.要声明类或结构上的索引器,使用this关键字. 示例:   索引器示例代码 /// <summary> /// 存储星 ...

  3. iOS五种本地缓存数据方式

    iOS五种本地缓存数据方式   iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...

  4. PHP filesystem attack vectors

    http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/ On Apr 07, 2008 I spoke with Kuza55 and ...

  5. 【HDU4578 Transformation】线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578 题意:有一个序列,有四种操作: 1:区间[l,r]内的数全部加c. 2:区间[l,r]内的数全部 ...

  6. php图片转为资源数据

    $file='C:\Users\feng\Desktop\images\banner.png';  //图片路径 $type=getimagesize($file);                 ...

  7. JS的Touch事件们,触屏时的js事件

    丫的,终于找到了JS在平板电脑上的事件!!!   iphone.ipod Touch.ipad触屏时的js事件   1.Touch事件简介   pc上的web页面鼠标会产生onmousedown.on ...

  8. error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCR...

    http://blog.csdn.net/playstudy/article/details/6661868 一,问题描述MSVCRTD.lib(crtexew.obj) : error LNK201 ...

  9. BizTalk 2013 Beta 新特性介绍

    BizTalk2013 Beta于2012年11月6日发布,下面来介绍一下BizTalk 2013 Beta的新特性. [核心更新功能] 1. 与云服务集成 BizTalk 2013 Server提供 ...

  10. node exports与 module.exports的区别

    你肯定非常熟悉nodejs模块中的exports对象,你可以用它创建你的模块.例如:(假设这是rocker.js文件) exports.name = function() { console.log( ...