Android中NFC编程
你可以在Android的NFC支持页面找到相关的API文档和NFC的示例代码:
http://developer.android.com/reference/android/nfc/package-summary.html
接下来该怎么做呢?通常需要硬件的支持(手机支持NFC)和添加你的应用的权限。
这需要你修改你的AndroidManifest.xml文件,将最低的SDK版本更改为10,也就是Android2.3.3及以上版本:
<uses-sdkandroid:minSdkVersion="10"/>
还有就是你的手机需要支持NFC,应用必须获取与硬件交互的权限:
<uses-featureandroid:name="android.hardware.nfc"android:required="true"/> <uses-permissionandroid:name="android.permission.NFC"/>
你也可以通过定义Intent来对NFC扫描获取的数据进行过滤处理。这里仅仅是使用ACTION_NDEF_DISCOVERED处理字符数据。当然也有其他的NFC规格的数据类型的定义。
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <categoryandroid:name="android.intent.category.DEFAULT"/> <dataandroid:mimeType="text/plain"/> </intent-filter>
NFC数据交换格式
NdefMessage包含传输在NDEF中的数据,每个NdefMessage由定义在NdefRecord的多个记录组成。每个NdefRecord根据它指明的3-bit的TNF进行解释。查看完整的TNF列表及其映射,最常用的TNF是TNF_WELL_KNOWN 和 TNF_MIME_MEDIA。标签调度系统通过三个Intent处理解包的NFC数据(通过Intent传递数据)。根据优先级的先后,它们是ACTION_NDEF_DISCOVERED,ACTION_TECH_DISCOVERED,和ACTION_TAG_DISCOVERED。
这里是官方的描述:“只要可能,尽可能的使用NDEF消息和ACTION_NDEF_DISCOVERED,因为三个Intent中最详细的。这个Intent可以比其他两个Intent在更加合适的时间启动你的应用,给用户更好的体验”。
在Android中读取NFC标签 和贴纸
正如我们在前一节提到,NdefMessage 是交换NFC数据最常用的方式。当然,你仍然可以定义你自己的non-NDEF 数据,但是这超出了本教程的范围。为了说明数据是如何被标签调度系统解析和处理的,我们仅在我们的实例中使用简单的纯文本。对于其他类型,看一下官方网站。
NfcAdapter用来监测设备对NFC的支持。前台调度系统允许一个活动拦截一个意图并允许这个活动比其他处理相同意图的活动拥有更高的优先级。
在onNewIntent(),我们试图解析所有的NDEF消息和它们的记录。因为有几个不同的数据类型,这个例子仅仅试图解析由inNdefRecord.RTD_TEXT定义的文本类型。
packagecom.songsoft.NFC; importjava.util.Arrays; importandroid.app.Activity; importandroid.app.PendingIntent; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.nfc.NdefMessage; importandroid.nfc.NdefRecord; importandroid.nfc.NfcAdapter; importandroid.nfc.Tag; importandroid.nfc.tech.NfcF; importandroid.os.Bundle; importandroid.os.Parcelable; importandroid.util.Log; importandroid.widget.TextView; publicclass TagDispatch extends Activity { private TextView mTextView; private NfcAdapter mNfcAdapter; private PendingIntent mPendingIntent; private IntentFilter[] mIntentFilters; private String[][] mNFCTechLists; @Override public void onCreate(Bundle savedState){ super.onCreate(savedState); setContentView(R.layout.main); mTextView =(TextView)findViewById(R.id.tv); mNfcAdapter =NfcAdapter.getDefaultAdapter(this); if (mNfcAdapter != null) { mTextView.setText("读取一个NFC标签"); } else { mTextView.setText("不支持NFC。"); } mPendingIntent =PendingIntent.getActivity(this, 0, newIntent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); IntentFilter ndefIntent = newIntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndefIntent.addDataType("*/*"); mIntentFilters = newIntentFilter[] { ndefIntent }; } catch (Exception e) { Log.e("TagDispatch",e.toString()); } mNFCTechLists = newString[][] { new String[] { NfcF.class.getName() } }; } @Override public void onNewIntent(Intent intent){ String action =intent.getAction(); Tag tag =intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String s = action +"\n\n" + tag.toString(); Parcelable[] data =intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (data != null) { try { for (int i= 0; i < data.length; i++) { NdefRecord[] recs = ((NdefMessage)data[i]).getRecords(); for(int j = 0; j < recs.length; j++) { if(recs[j].getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(recs[j].getType(),NdefRecord.RTD_TEXT)) { byte[]payload = recs[j].getPayload(); StringtextEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" :"UTF-16"; intlangCodeLen = payload[0] & 0077; s+= ("\n\nNdefMessage[" + i + "], NdefRecord[" + j +"]:\n\"" + newString(payload, langCodeLen + 1, payload.length- langCodeLen - 1, textEncoding) + "\""); } } } } catch (Exceptione) { Log.e("TagDispatch",e.toString()); } } mTextView.setText(s); } @Override public void onResume() { super.onResume(); if (mNfcAdapter != null) mNfcAdapter.enableForegroundDispatch(this, mPendingIntent,mIntentFilters, mNFCTechLists); } @Override public void onPause() { super.onPause(); if (mNfcAdapter != null) mNfcAdapter.disableForegroundDispatch(this); } }
通过AndroidBeam将NFC数据传到其他设备
通过Android Beam的支持发送NFC数据,所以这个活动通常被成为“beaming”。许多NDEF数据可以被传递,当然可以定义你自己的格式。这个实例演示了如何创建一个纯文本类型的记录。大部分代码看起来很熟悉。
packagecom.songsoft.NFC; importjava.nio.charset.Charset; importjava.util.Locale; importandroid.app.Activity; importandroid.nfc.NdefMessage; importandroid.nfc.NdefRecord; importandroid.nfc.NfcAdapter; importandroid.os.Bundle; importandroid.widget.TextView; publicclass BeamData extends Activity { private NfcAdapter mNfcAdapter; private TextView mTextView; private NdefMessage mNdefMessage; @Override public void onCreate(Bundle savedState){ super.onCreate(savedState); setContentView(R.layout.main); mTextView =(TextView)findViewById(R.id.tv); mNfcAdapter =NfcAdapter.getDefaultAdapter(this); if (mNfcAdapter != null) { mTextView.setText("到另外一个设备"); } else { mTextView.setText("不支持NFC"); } mNdefMessage = newNdefMessage( newNdefRecord[] { createNewTextRecord("NDEF文本记录的第一个实例", Locale.ENGLISH, true), createNewTextRecord("NDEF文本记录的第二个实例", Locale.ENGLISH, true) }); } public static NdefRecordcreateNewTextRecord(String text, Locale locale, boolean encodeInUtf8) { byte[] langBytes =locale.getLanguage().getBytes(Charset.forName("US-ASCII")); Charset utfEncoding =encodeInUtf8 ? Charset.forName("UTF-8") :Charset.forName("UTF-16"); byte[] textBytes =text.getBytes(utfEncoding); int utfBit = encodeInUtf8 ? 0: (1 << 7); char status = (char)(utfBit +langBytes.length); byte[] data = new byte[1 +langBytes.length + textBytes.length]; data[0] = (byte)status; System.arraycopy(langBytes,0, data, 1, langBytes.length); System.arraycopy(textBytes,0, data, 1 + langBytes.length, textBytes.length); return newNdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); } @Override public void onResume() { super.onResume(); if (mNfcAdapter != null) mNfcAdapter.enableForegroundNdefPush(this,mNdefMessage); } @Override public void onPause() { super.onPause(); if (mNfcAdapter != null) mNfcAdapter.disableForegroundNdefPush(this); } }
总结
本NFC教程主要以强调一些关键的方面作为出发点,要想活的更多的信息,可以访问Android的官方网站。