# Android NFC开发 #
----------
----------
## 这里要说的是采用setNdefPushMessage的方式,手动发送一个NFC信息,属于NFC设备对NFC设备(p2p)的方式 ##
**PS:在这里我要吐槽一下,对于这个p2p方式的NFC数据传送,也是没谁了,要求手机的NFC传送点和点对上才能和平发送,就是手机后背有个NFC点,碰上,屏幕上才会弹出 "触摸发送" 选项,估计是塑料壳的原因吧,金属壳的不知道会不会更容易些,不吐了,上货!**
----------
**步骤1. 检查手机是否有NFC功能①,以及NFC和NFC_Beam功能②是否开启;**
**①:有NFC功能才能进行NFC的相关操作**
**②:NFC_Beam指的是设备和设备之间传输必须要开的(本人是这么理解的),不开仅仅可以设备扫卡(比如公交卡等NFC卡)**
**步骤2. 发送消息setNdefPushMessage**
**步骤3. 拦截(姑且称之为拦截)消息并处理**
**步骤4. 在MainFest文件中添加相应权限和activity-action**
----------
## 下面上代码,具体细节在注释中都能看见 ##
**对了,对NFC进行操作需要NfcAdapter这个类,是Android自带的**
**步骤3. 接收消息,并处理!处理!处理!这个才是重点,弱弱的说一下,有些地方都没搞懂- -也没去搞- -当然,没搞懂的地方我会标注/(ㄒoㄒ)/~~的**
**接收..步骤1. 需要重写这个方法,具体原因不是很清楚,反正是能接收到数据到Intent- -**
**接收..步骤2. 重写onResume() 在接收完数据的时候会回调这个方法,然后数据就通过onNewIntent传过来了,然后就能解析了/(ㄒoㄒ)/~~**
**重点来了,我们来处理,其实步骤就那样,一层一层的把数据取出来 intent中取出Message,Message中取出Record,Record中取出数据- -包的有够到紧的-_-**
**首先,我们从intent中取出Message**
**从Message中取出Record**
**取出最后的数据**
**注:Preconditions是一个格式验证的类,要是不懂可以用if_else替代,需要Jar包,如果不想百度 我也会在后面提供下载**
**哦哦 还有几个方法**
**判断是不是文字**
**Log日志类--DebugUtils**
**BobNdefMessage 直接拷贝的- -**
**最后附上Jar包地址,顺便带上触碰自动发送信息的源码,供大家参考(PS:- -Jar包地址明日加上- -可先自行百度- -)**
----------
**我参照了NFC实战详解(赵波的一本书),没有NFC基本知识了解的推荐去看这本书的前3章,1-2小时就看完了**
----------
## 这里要说的是采用setNdefPushMessage的方式,手动发送一个NFC信息,属于NFC设备对NFC设备(p2p)的方式 ##
**PS:在这里我要吐槽一下,对于这个p2p方式的NFC数据传送,也是没谁了,要求手机的NFC传送点和点对上才能和平发送,就是手机后背有个NFC点,碰上,屏幕上才会弹出 "触摸发送" 选项,估计是塑料壳的原因吧,金属壳的不知道会不会更容易些,不吐了,上货!**
----------
**步骤1. 检查手机是否有NFC功能①,以及NFC和NFC_Beam功能②是否开启;**
**①:有NFC功能才能进行NFC的相关操作**
**②:NFC_Beam指的是设备和设备之间传输必须要开的(本人是这么理解的),不开仅仅可以设备扫卡(比如公交卡等NFC卡)**
**步骤2. 发送消息setNdefPushMessage**
**步骤3. 拦截(姑且称之为拦截)消息并处理**
**步骤4. 在MainFest文件中添加相应权限和activity-action**
----------
## 下面上代码,具体细节在注释中都能看见 ##
**对了,对NFC进行操作需要NfcAdapter这个类,是Android自带的**
**步骤1. 我定义了一个方法,进行了NFC是否开启的判断**
private void checkNFCFunction() { // 获取NFCAdapter(这个是全局的,参数是一个Context) mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // mNfcAdapter为Null表示机器没有NFC功能 if (mNfcAdapter == null) { // 提示 (这里是自定义的Log日志类,没有定义过可以用Log.I进行替换或者直接吐司,我也会上传代码) DebugUtils.LogI("没有NFC功能", getClass()); } else { // 表示NFC功能未打开,就要弹出Dialog提示用户打开了 if (!mNfcAdapter.isEnabled()) { Dialog dialog = null; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("警告!"); builder.setMessage("NFC功能未开启,是否前往开启(不开启将无法继续)"); builder.setPositiveButton("开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); // ACTION_WIRELESS_SETTINGS(即跳入NFC功能开启界面) Intent setnfc = new Intent(Settings.ACTION_WIRELESS_SETTINGS); startActivity(setnfc); } }).setNegativeButton("不开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); finish(); } }); dialog = builder.create(); dialog.setCancelable(false); dialog.setCanceledOnTouchOutside(false); setDialogWidth(dialog).show(); return; // NFC功能开启之后 判断NFC_Beam功能是否开启 } else if (!mNfcAdapter.isNdefPushEnabled()) { Dialog dialog = null; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("警告!"); builder.setMessage("NFC_Beam功能未开启,是否前往开启(不开启将无法继续)"); builder.setPositiveButton("开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); // 同理 ACTION_NFCSHARING_SETTINGS跳入NFC_Beam设置界面 Intent setnfc = new Intent(Settings.ACTION_NFCSHARING_SETTINGS); startActivity(setnfc); } }).setNegativeButton("不开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); finish(); } }); dialog = builder.create(); dialog.setCancelable(false); dialog.show(); return; } } }
注意: 在Activity被加载的时候 需要首先调用这个方法,就是说需要放在onCreate中,当然 在onStart之前就可以
步骤2. 创建信息并且发送,NFC消息需要通过NdefMessage来装(就类似四大组件之间的消息需要用Intent来装一样)需要用到NdefMessage类,Android自带的- -,还需要一个BobNdefMessage类,不自带,一百度一大把,我这里也上传- -在下面
mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 步骤1 : 创建NDEF Msg (三个参数,源码在,请自查) NdefMessage message = BobNdefMessage.getNdefMsg_from_RTD_TEXT("我是要发送的消息", false, false); // 步骤2 : 发送信息 mNfcAdapter.setNdefPushMessage(message, ActNfc2.this); } });
**步骤3. 接收消息,并处理!处理!处理!这个才是重点,弱弱的说一下,有些地方都没搞懂- -也没去搞- -当然,没搞懂的地方我会标注/(ㄒoㄒ)/~~的**
**接收..步骤1. 需要重写这个方法,具体原因不是很清楚,反正是能接收到数据到Intent- -**
@Override protected void onNewIntent(Intent intent) { setIntent(intent); }
**接收..步骤2. 重写onResume() 在接收完数据的时候会回调这个方法,然后数据就通过onNewIntent传过来了,然后就能解析了/(ㄒoㄒ)/~~**
@Override protected void onResume() { super.onResume(); // 消息判别(判别是不是NDEF类型的消息) if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) { // 处理接受到的数据(同样定义了方法) resolveIntent(getIntent()); } }
**重点来了,我们来处理,其实步骤就那样,一层一层的把数据取出来 intent中取出Message,Message中取出Record,Record中取出数据- -包的有够到紧的-_-**
**首先,我们从intent中取出Message**
private void resolveIntent(Intent intent) { String action = intent.getAction(); // 程序的严谨性,再判断一遍 if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { NdefMessage[] messages = null; // 通过EXTRA_NDEF_MESSAGES_Key就能得到NFC发过来的Message数组了 -_- 就是数据转移- - Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMsgs != null) { messages = new NdefMessage[rawMsgs.length]; for (int i = 0; i < rawMsgs.length; i++) { messages[i] = (NdefMessage) rawMsgs[i]; } } else { // 未知TagType byte[] empty = new byte[]{}; NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty); NdefMessage msg = new NdefMessage(new NdefRecord[]{record}); messages = new NdefMessage[]{msg}; } // 从Message中取出Record(又定义了一个方法,) progressNDEFMsg(messages); } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { DebugUtils.LogI(Tag_ASSIST + "ACTION_TECH_DISCOVERED", getClass()); } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { DebugUtils.LogI(Tag_ASSIST + "ACTION_TAG_DISCOVERED", getClass()); } else { DebugUtils.LogI(Tag_ASSIST + "UnKnown TAG", getClass()); finish(); return; } }
**从Message中取出Record**
private void progressNDEFMsg(NdefMessage[] messages) { // 非空 if (messages == null || messages.length == 0) { return; } for (int i = 0; i < messages.length; i++) { int length = messages[i].getRecords().length; NdefRecord[] records = messages[i].getRecords(); // 几个记录(书上这里有点问题,我改了改- -具体可以看书) for (NdefRecord record : records) { // 首先需要确定是文字 if (isTextRecord(record)) { // 然后 取出最后的数据 parseRTD_TEXTRecord(record); } } } }
**取出最后的数据**
**注:Preconditions是一个格式验证的类,要是不懂可以用if_else替代,需要Jar包,如果不想百度 我也会在后面提供下载**
private void parseRTD_TEXTRecord(NdefRecord record) { // 记录格式验证 Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN); // 记录类型验证 Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)); String payloadStr = ""; byte[] payload = record.getPayload(); Byte statusByte = record.getPayload()[0]; // 这一块我就不懂了 start----- String textEncoding = ((statusByte & 0200) == 0) ? "UTF-8" : "UTF-16"; // 0x80=0200 ,获取状态字节编码 // 获取语言码长度 int languageCodeLength = statusByte & 0077;// & 0x3F=0077(bit 5 to 0) // 不懂 end ----- String languageCode = new String(payload, 1, languageCodeLength, Charset.forName("UTF-8")); try { payloadStr = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding); } catch (UnsupportedEncodingException e) { DebugUtils.LogI("异常信息" + e.getMessage(), getClass()); } }
**哦哦 还有几个方法**
**判断是不是文字**
private boolean isTextUri(NdefRecord record) { if (NdefRecord.TNF_WELL_KNOWN == record.getTnf()) { if (Arrays.equals(NdefRecord.RTD_TEXT, record.getType())) { return true; } else { return false; } } else { return false; } }## 工具类 ##
**Log日志类--DebugUtils**
/** * 提供打印日志的功能 */ public class DebugUtils { private static boolean logIsOpen = true; // 是否开启Log日志打印 public static void LogI(Object obj, Class clazz) { if (logIsOpen) { Log.i("RedWolf", "["+clazz.getSimpleName() + "]- " + obj); } } }
**BobNdefMessage 直接拷贝的- -**
public class BobNdefMessage { /** * @About:create a TNF_WELL_KNOW NDEF record as RTD_URI * @param uriFiledStr , The rest of the URI, or the entire URI (if * identifier code is 0x00). * @param identifierCode = prefixes(URI identifier code), 0x01=http://www. * ,0x02=https://www. , 0x03=http:// * @param flagAddAAR, true means add AAR * @return NdefMessage * @Ref: NFCForum-TS-RTD_URI_1.0 * @By SkySeraph-2013 */ public static NdefMessage getNdefMsg_from_RTD_URI(String uriFiledStr, byte identifierCode, boolean flagAddAAR) { byte[] uriField = uriFiledStr.getBytes(Charset.forName("US-ASCII")); byte[] payLoad = new byte[uriField.length + 1]; // add 1 for the URI // Prefix payLoad[0] = identifierCode; // 0x01 = prefixes http://www. to the URI // appends URI to payload System.arraycopy(uriField, 0, payLoad, 1, uriField.length); // Method1: NdefRecord rtdUriRecord1 = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payLoad); // Method2:only in API 14 String prefix = URI_PREFIX_MAP.get(identifierCode); NdefRecord rtdUriRecord2 = NdefRecord.createUri(prefix + uriFiledStr); // Method3:only in API 14 NdefRecord rtdUriRecord3 = NdefRecord.createUri(Uri.parse(prefix + uriFiledStr)); if (flagAddAAR) { // note: returns AAR for different app (nfcreadtag) return new NdefMessage(new NdefRecord[] { rtdUriRecord1, NdefRecord.createApplicationRecord("skyseraph.nfc_demo") }); // packageName } else { return new NdefMessage(new NdefRecord[] { rtdUriRecord1 }); } } /** * @About:create a TNF_WELL_KNOW NDEF record as RTD_TEXT * @param text , the really text data * @param encodeInUtf8 , false means TEXT encoded by UTF-8 * @param flagAddAAR , true means add AAR * @return NdefMessage * @Ref: NFCForum-TS-RTD_Text_1.0 * @By SkySeraph-2013 */ public static NdefMessage getNdefMsg_from_RTD_TEXT(String text, boolean encodeInUtf8, boolean flagAddAAR) { Locale locale = new Locale("en", "US"); // a new Locale is created with // US English. byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); // boolean encodeInUtf8 = false; Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); int utfBit = encodeInUtf8 ? 0 : (1 << 7); char status = (char)(utfBit + langBytes.length); // String text = "This is an RTD_TEXT exp"; byte[] textBytes = text.getBytes(utfEncoding); 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); NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); if (flagAddAAR) { // note: returns AAR for different app (nfcreadtag) return new NdefMessage(new NdefRecord[] { textRecord, NdefRecord.createApplicationRecord("skyseraph.nfc_demo") }); } else { return new NdefMessage(new NdefRecord[] { textRecord }); } } /** * @About: create a TNF_ABSOLUTE_URI NDEF record * @param absoluteUri ,the absolute Uri * @param flagAddAAR , true means add AAR * @return NdefMessage * @Note: TNF_ABSOLUTE_URI indicates the absolute form of a URI that follows * the absolute-URI rule defined by RFC 3986 * @Note: Recommend that you use the RTD_URI type instead of * TNF_ABSOLUTE_URI, because it is more efficient * @By SkySeraph-2013 */ public static NdefMessage getNdefMsg_from_ABSOLUTE_URI(String absoluteUri, boolean flagAddAAR) { // String absoluteUri = "http://developer.android.com/index.html"; byte[] absoluteUriBytes = absoluteUri.getBytes(Charset.forName("US-ASCII")); NdefRecord uriRecord = new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, new byte[0], new byte[0], absoluteUriBytes); if (flagAddAAR) { // note: returns AAR for different app (nfcreadtag) return new NdefMessage(new NdefRecord[] { uriRecord, NdefRecord.createApplicationRecord("skyseraph.nfc_demo") }); } else { return new NdefMessage(new NdefRecord[] { uriRecord }); } } /** * @About:create a TNF_MIME_MEDIA NDEF record * @param payLoad,the MIME data * @param mimeType,the MIME Type * @param flagAddAAR, true means add AAR * @return NdefMessage * @By SkySeraph-2013 */ @SuppressLint("NewApi") public static NdefMessage getNdefMsg_from_MIME_MEDIA(String payLoad, String mimeType, boolean flagAddAAR) { byte[] payLoadBytes = payLoad.getBytes(Charset.forName("US-ASCII")); // String mimeType = "application/skyseraph.nfc_demo"; // method1:Creating the NdefRecord manually NdefRecord mimeRecord1 = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeType.getBytes(Charset.forName("US-ASCII")), new byte[0], payLoadBytes); // the identfier of the record is given as 0, since it will be the first // record in the NdefMessage // method2:Using the createMime() method, in API-16 NdefRecord mimeRecord2 = NdefRecord.createMime(mimeType, payLoadBytes); if (flagAddAAR) { // note: returns AAR for different app (nfcreadtag) return new NdefMessage(new NdefRecord[] { mimeRecord1, NdefRecord.createApplicationRecord("skyseraph.nfc_demo") }); } else { return new NdefMessage(new NdefRecord[] { mimeRecord1 }); } } /** * @About:create a TNF_EXTERNAL_TYPE NDEF record * @param payLoad,the EXTERNAL data * @param flagAddAAR, true means add AAR * @return NdefMessage * @By SkySeraph-2013 */ @SuppressLint("NewApi") public static NdefMessage getNdefMsg_from_EXTERNAL_TYPE(String payLoad, boolean flagAddAAR) { byte[] payLoadBytes = payLoad.getBytes(); String domain = "skyseraph.nfc_demo"; // usually your app's package name String type = "externalType"; String externalType = domain + ":" + type; // method1:Creating the NdefRecord manually NdefRecord exteralRecord1 = new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, externalType.getBytes(), new byte[0], payLoadBytes); // method2:Using the createExternal() method, in API-16 NdefRecord exteralRecord2 = NdefRecord.createExternal(domain, type, payLoadBytes); if (flagAddAAR) { // note: returns AAR for different app (nfcreadtag) return new NdefMessage(new NdefRecord[] { exteralRecord1, NdefRecord.createApplicationRecord("skyseraph.nfc_demo") }); } else { return new NdefMessage(new NdefRecord[] { exteralRecord1 }); } } /** * checkSystemVersion() */ private boolean flagVersion = false; private void checkSystemVersion() { // TODO Auto-generated method stub // if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) String systemModel; String releaseVersion; String sdkVersion; systemModel = android.os.Build.MODEL; sdkVersion = android.os.Build.VERSION.SDK; releaseVersion = android.os.Build.VERSION.RELEASE; if (Integer.parseInt(sdkVersion) > 15) { flagVersion = true; } else { flagVersion = false; } } /** * NFC Forum "URI Record Type Definition" This is a mapping of * "URI Identifier Codes" to URI string prefixes, per section 3.2.2 of the * NFC Forum URI Record Type Definition document. */ private static final BiMap<Byte, String> URI_PREFIX_MAP = ImmutableBiMap .<Byte, String> builder().put((byte)0x00, "").put((byte)0x01, "http://www.") .put((byte)0x02, "https://www.").put((byte)0x03, "http://").put((byte)0x04, "https://") .put((byte)0x05, "tel:").put((byte)0x06, "mailto:") .put((byte)0x07, "ftp://anonymous:anonymous@").put((byte)0x08, "ftp://ftp.") .put((byte)0x09, "ftps://").put((byte)0x0A, "sftp://").put((byte)0x0B, "smb://") .put((byte)0x0C, "nfs://").put((byte)0x0D, "ftp://").put((byte)0x0E, "dav://") .put((byte)0x0F, "news:").put((byte)0x10, "telnet://").put((byte)0x11, "imap:") .put((byte)0x12, "rtsp://").put((byte)0x13, "urn:").put((byte)0x14, "pop:") .put((byte)0x15, "sip:").put((byte)0x16, "sips:").put((byte)0x17, "tftp:") .put((byte)0x18, "btspp://").put((byte)0x19, "btl2cap://").put((byte)0x1A, "btgoep://") .put((byte)0x1B, "tcpobex://").put((byte)0x1C, "irdaobex://") .put((byte)0x1D, "file://").put((byte)0x1E, "urn:epc:id:") .put((byte)0x1F, "urn:epc:tag:").put((byte)0x20, "urn:epc:pat:") .put((byte)0x21, "urn:epc:raw:").put((byte)0x22, "urn:epc:") .put((byte)0x23, "urn:nfc:").build(); }
**最后附上Jar包地址,顺便带上触碰自动发送信息的源码,供大家参考(PS:- -Jar包地址明日加上- -可先自行百度- -)**
/** * 触屏发送订单信息 */ // NfcAdapter.CreateNdefMessageCallBack 接口 应该是在两个Nfc设备接触的时候 被调用的.. public class ActNfc3 extends BaseActivity implements BaseInterface, NfcAdapter.CreateNdefMessageCallback { // NfcAdapter private NfcAdapter mNfcAdapter; // EditText 发送 private EditText etSend; // TextView 接收 private TextView tvReceive; private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.act_nfc3); mContext = this; checkNFCFunction(); initViews(); initDatas(); initEvent(); } @Override public void initViews() { etSend = (EditText) findViewById(R.id.et_send); tvReceive = (TextView) findViewById(R.id.tv_receive); } @Override public void initDatas() { mNfcAdapter.setNdefPushMessageCallback(this, this); } @Override public void initEvent() { } private void checkNFCFunction() { mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // 机器不支持Nfc功能 if (mNfcAdapter == null) { ToastUtils.showToastFroce(mContext, "抱歉,本机不支持NFC功能"); return; } else { // 检查机器NFC是否开启 if (!mNfcAdapter.isEnabled()) { // 机器Nfc未开启 提示用户开启 这里采用对话框的方式<PS:这个开启了 可以进行对NFC的信息读写> AlertDialog.Builder builder = new AlertDialog.Builder(mContext); builder.setTitle("警告").setMessage("本机NFC功能未开启,是否开启(不开启将无法继续)").setNegativeButton("开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent setNfc = new Intent(Settings.ACTION_NFC_SETTINGS); startActivity(setNfc); } }).setPositiveButton("不开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }).setCancelable(false).create().show(); return; } else { // NFC 已开启 检查NFC_Beam是否开启 只有这个开启了 才能进行p2p的传输 if (!mNfcAdapter.isNdefPushEnabled()) { // NFC_Beam未开启 点击开启 new AlertDialog.Builder(mContext).setTitle("警告!").setMessage("NFC_Beam功能未开启,是否开启(不开启将无法继续)").setNegativeButton("开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent setNfc = new Intent(Settings.ACTION_NFCSHARING_SETTINGS); startActivity(setNfc); } }).setPositiveButton("不开启", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }).setCancelable(false).create().show(); return; } } } } // 在Nfc设备相互接触的时候 调用这个方法 进行消息的发送 @Override public NdefMessage createNdefMessage(NfcEvent event) { DebugUtils.LogI("createNdefMessage", getClass()); // 1.创建NdefMessage NdefMessage message = BobNdefMessage.getNdefMsg_from_RTD_TEXT(etSend.getText().toString(), false, false); return message; } @Override protected void onNewIntent(Intent intent) { // 接收到消息的第一步 setIntent(intent); } @Override protected void onResume() { super.onResume(); // 需要从Intent中读出信息 // 消息判别 if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) { resolveIntent(getIntent()); } } private void resolveIntent(Intent intent) { String action = intent.getAction(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { NdefMessage[] messages = null; Parcelable[] rawMsg = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMsg != null) { messages = new NdefMessage[rawMsg.length]; for (int i = 0; i < messages.length; i++) { messages[i] = (NdefMessage) rawMsg[i]; } } else { // 未知Action byte[] empty = new byte[]{}; NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty); NdefMessage ndefMessage = new NdefMessage(ndefRecord); messages = new NdefMessage[]{ndefMessage}; } // 将Message中的Record解析出来 progressNdefMessage(messages); } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { } else { return; } } private void progressNdefMessage(NdefMessage[] messages) { if (messages == null || messages.length == 0) { DebugUtils.LogI("progressNdefMessage-message==null", getClass()); return; } for (int i = 0; i < messages.length; i++) { NdefRecord records[] = messages[i].getRecords(); for (NdefRecord record : records) { DebugUtils.LogI("progressNdefMessage - record", getClass()); if (isTextUri(record)) { parseTextUri(record); } } } } private void parseTextUri(NdefRecord record) { DebugUtils.LogI("isTextUri", getClass()); // 记录格式验证 Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN); // 记录类型验证 Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)); // 读出所有的PayLoad String payLoadStr = ""; byte[] payloads = record.getPayload(); byte statusByte = payloads[0]; // 得到编码方式 String textEncoding = ((statusByte & 0200) == 0) ? "UTF-8" : "UTF-16"; // 获取语言码的长度 int languageCodeLength = statusByte & 0077; String languageCode = new String(payloads, 1, languageCodeLength, Charset.forName("UTF-8")); // payloadStr = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding); // 真正的解析?? payLoadStr = new String(payloads, languageCodeLength + 1, payloads.length - languageCodeLength - 1, Charset.forName(textEncoding)); // 解析完毕,加载 tvReceive.setText("接收完毕!-->" + payLoadStr); } private boolean isTextUri(NdefRecord record) { if (NdefRecord.TNF_WELL_KNOWN == record.getTnf()) { if (Arrays.equals(NdefRecord.RTD_TEXT, record.getType())) { return true; } else { return false; } } else { return false; } } }
Android NFC开发实战详解 赵波
http://download.csdn.net/detail/redwolfchao/9663033http://download.csdn.net/detail/redwolfchao/9663054
作者:RedWolfChao 发表于2016/11/7 21:26:53 原文链接
阅读:6 评论:0 查看评论