NFC(10)NDEF uri格式规范及读写示例(解析与封装ndef uri)

  只有遵守NDEF uri 格式规范的数据才能写到nfc标签上.

NDEF uri 格式规范

  uri 只有两部分:

    第1个字节是uri协议映射值,如:0x01 表示uri以 http://www.开头.

    然后是uri的内容 ,如 www.g.cn

uri协议映射值表

 

示例

ReadWriteUriActivity.java

  1 import android.app.Activity;
  2 import android.content.Intent;
  3 import android.nfc.NdefMessage;
  4 import android.nfc.NdefRecord;
  5 import android.nfc.NfcAdapter;
  6 import android.nfc.Tag;
  7 import android.nfc.tech.Ndef;
  8 import android.os.Bundle;
  9 import android.view.View;
 10 import android.widget.TextView;
 11 import android.widget.Toast;
 12 
 13 /*
 14  * 本apk主activity,拦截nfc标签事件
 15  * 把读到的内容传给ShowNFCTagContentActivity
 16  * 把封装好的uri写到临近的nfc标签.
 17  */
 18 public class ReadWriteUriMainActivity extends Activity {
 19     private TextView mSelectUri;
 20     private String mUri;
 21 
 22     @Override
 23     public void onCreate(Bundle savedInstanceState) {
 24         super.onCreate(savedInstanceState);
 25         setContentView(R.layout.activity_read_write_uri_main);
 26         mSelectUri = (TextView) findViewById(R.id.textview_uri);
 27 
 28     }
 29 
 30     public void onClick_SelectUri(View view) {
 31         Intent intent = new Intent(this, UriListActivity.class);
 32         startActivityForResult(intent, 1);
 33 
 34     }
 35 
 36     @Override
 37     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 38         if (requestCode == 1 && resultCode == 1) {
 39             mUri = data.getStringExtra("uri");
 40             mSelectUri.setText(mUri);
 41         }
 42     }
 43 
 44     /*
 45      * 如果本aty中的mUri空,就读nfc标签内容存到mUri中,
 46      * 不空就封装uri并把它写到nfc标签中
 47      */
 48     @Override
 49     public void onNewIntent(Intent intent) {
 50         if (mUri == null) {//读nfc标签内容存到mUri中,并显示
 51             //把读到的内容传给ShowNFCTagContentActivity
 52             Intent myIntent = new Intent(this, ShowNFCTagContentActivity.class);
 53             myIntent.putExtras(intent);
 54             myIntent.setAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
 55             startActivity(myIntent);
 56         } else {// 封装uri并把它写到nfc标签中
 57             
 58             //封装uri并把它写到nfc标签 第1步,取nfc标签
 59             Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
 60             
 61             //封装uri并把它写到nfc标签 第2步,构造NdefMessage,其中有NdefRecord,NdefRecord中有封装的uri
 62             NdefMessage ndefMessage = new NdefMessage(
 63                     new NdefRecord[] { createUriRecord(mUri) });
 64             
 65             //封装uri并把它写到nfc标签 第3步,封装uri并写入
 66             if (writeTag(ndefMessage, tag)) {
 67                 mUri = null;
 68                 mSelectUri.setText("");
 69             }
 70         }
 71     }
 72 
 73     /*
 74      * 封装uri格式数据 
 75      * 现部分组成: 第一个字节是uri协议映射值
 76      * uri协议映射值,如:0x01 表示uri以 http://www.开头.
 77      * uri的内容 如:www.g.cn
 78      */
 79     public NdefRecord createUriRecord(String uriStr) {
 80         /*
 81          * 封装uri格式数据 第1步, 根据uriStr中的值找到构造第一个字节的内容:uri协议映射值
 82          */
 83         byte prefix = 0;
 84         for (Byte b : UriRecord.URI_PREFIX_MAP.keySet()) {
 85             String prefixStr = UriRecord.URI_PREFIX_MAP.get(b).toLowerCase();
 86             if ("".equals(prefixStr))
 87                 continue;
 88             if (uriStr.toLowerCase().startsWith(prefixStr)) {
 89                 prefix = b;
 90                 uriStr = uriStr.substring(prefixStr.length());
 91                 break;
 92             }
 93 
 94         }
 95         /*
 96          * 封装uri格式数据 第2步, uri的内容就是本函数的参数 uriStr
 97          */
 98         /*
 99          * 封装uri格式数据 第3步, 申请分配空间
100          */
101         byte[] data = new byte[1 + uriStr.length()];
102         
103         /*
104          * 封装uri格式数据 第4步, 把uri头的映射值和uri内容写到刚申请的空间中
105          */
106         data[0] = prefix;
107         System.arraycopy(uriStr.getBytes(), 0, data, 1, uriStr.length());
108 
109         /*
110          * 封装uri格式数据 第5步, 根据uri构造一个NdefRecord
111          */
112         NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
113                 NdefRecord.RTD_URI, new byte[0], data);
114         return record;
115     }
116 
117     /*
118      * 将封装好uri格式的NdefMessage写入到nfc标签中.
119      */
120     boolean writeTag(NdefMessage message, Tag tag) {
121         int size = message.toByteArray().length;
122         try {
123             Ndef ndef = Ndef.get(tag);
124             if (ndef != null) {
125                 ndef.connect();
126                 if (!ndef.isWritable()) {
127                     return false;
128                 }
129                 if (ndef.getMaxSize() < size) {
130                     return false;
131                 }
132                 ndef.writeNdefMessage(message);
133                 Toast.makeText(this, "ok", Toast.LENGTH_LONG).show();
134                 return true;
135             }
136         } catch (Exception e) {
137             e.printStackTrace();
138         }
139         return false;
140     }
141 }

UriRecord.java

  1 import java.nio.charset.Charset;
  2 import java.util.Arrays;
  3 import java.util.HashMap;
  4 import java.util.Map;
  5 import android.net.Uri;
  6 import android.nfc.NdefRecord;
  7 
  8 public class UriRecord {
  9 
 10     private final Uri mUri;// 存uri
 11 
 12     /*
 13      * uri 格式数据中 第一个字节 存uri的头值映射表
 14      * 如 0x01 表示uri以 http://www.开头,
 15      * 存uri的头值是为了省空间.
 16      */
 17     public static final Map<Byte, String> URI_PREFIX_MAP = new HashMap<Byte, String>();
 18 
 19     static {
 20         URI_PREFIX_MAP.put((byte) 0x00, "");
 21         URI_PREFIX_MAP.put((byte) 0x01, "http://www.");
 22         URI_PREFIX_MAP.put((byte) 0x02, "https://www.");
 23         URI_PREFIX_MAP.put((byte) 0x03, "http://");
 24         URI_PREFIX_MAP.put((byte) 0x04, "https://");
 25         URI_PREFIX_MAP.put((byte) 0x05, "tel:");
 26         URI_PREFIX_MAP.put((byte) 0x06, "mailto:");
 27         URI_PREFIX_MAP.put((byte) 0x07, "ftp://anonymous:anonymous@");
 28         URI_PREFIX_MAP.put((byte) 0x08, "ftp://ftp.");
 29         URI_PREFIX_MAP.put((byte) 0x09, "ftps://");
 30         URI_PREFIX_MAP.put((byte) 0x0A, "sftp://");
 31         URI_PREFIX_MAP.put((byte) 0x0B, "smb://");
 32         URI_PREFIX_MAP.put((byte) 0x0C, "nfs://");
 33         URI_PREFIX_MAP.put((byte) 0x0D, "ftp://");
 34         URI_PREFIX_MAP.put((byte) 0x0E, "dav://");
 35         URI_PREFIX_MAP.put((byte) 0x0F, "news:");
 36         URI_PREFIX_MAP.put((byte) 0x10, "telnet://");
 37         URI_PREFIX_MAP.put((byte) 0x11, "imap:");
 38         URI_PREFIX_MAP.put((byte) 0x12, "rtsp://");
 39         URI_PREFIX_MAP.put((byte) 0x13, "urn:");
 40         URI_PREFIX_MAP.put((byte) 0x14, "pop:");
 41         URI_PREFIX_MAP.put((byte) 0x15, "sip:");
 42         URI_PREFIX_MAP.put((byte) 0x16, "sips:");
 43         URI_PREFIX_MAP.put((byte) 0x17, "tftp:");
 44         URI_PREFIX_MAP.put((byte) 0x18, "btspp://");
 45         URI_PREFIX_MAP.put((byte) 0x19, "btl2cap://");
 46         URI_PREFIX_MAP.put((byte) 0x1A, "btgoep://");
 47         URI_PREFIX_MAP.put((byte) 0x1B, "tcpobex://");
 48         URI_PREFIX_MAP.put((byte) 0x1C, "irdaobex://");
 49         URI_PREFIX_MAP.put((byte) 0x1D, "file://");
 50         URI_PREFIX_MAP.put((byte) 0x1E, "urn:epc:id:");
 51         URI_PREFIX_MAP.put((byte) 0x1F, "urn:epc:tag:");
 52         URI_PREFIX_MAP.put((byte) 0x20, "urn:epc:pat:");
 53         URI_PREFIX_MAP.put((byte) 0x21, "urn:epc:raw:");
 54         URI_PREFIX_MAP.put((byte) 0x22, "urn:epc:");
 55         URI_PREFIX_MAP.put((byte) 0x23, "urn:nfc:");
 56     }
 57 
 58     private UriRecord(Uri uri) {
 59         this.mUri = uri;
 60     }
 61 
 62     public Uri getUri() {
 63         return mUri;
 64     }
 65 
 66     /*
 67      * 这时,uri数据里没有uri头值,整个uri数据就是一个uri
 68      */
 69     private static UriRecord parseAbsolute(NdefRecord ndefRecord) {
 70         //1,取得数据流
 71         byte[] payload = ndefRecord.getPayload();
 72         //2,解析出一个uri
 73         String uriStr = new String(payload, Charset.forName("UTF-8"));
 74         Uri uri = Uri.parse(uriStr);
 75         return new UriRecord(uri);
 76 
 77     }
 78     /*
 79      * 解析nfc uri格式的数据
 80      * 
 81      */
 82     private static UriRecord parseWellKnown(NdefRecord ndefRecord) {
 83         //解析uri第1步,判断record中是否是 uri
 84         if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_URI))
 85             return null;
 86         //解析uri第2步,获取字节数据.
 87         byte[] payload = ndefRecord.getPayload();
 88         
 89         //解析uri第3步,解析出uri头,如https://
 90         String prefix = URI_PREFIX_MAP.get(payload[0]);
 91         //解析uri第4步,解析出uri的内容,如:www.g.cn
 92         byte[] prefixBytes = prefix.getBytes(Charset.forName("UTF-8"));
 93         
 94         //解析uri第5步,合并uri头各内容.
 95         byte[] fullUri = new byte[prefixBytes.length + payload.length - 1];
 96         System.arraycopy(prefixBytes, 0, fullUri, 0, prefixBytes.length);
 97         System.arraycopy(payload, 1, fullUri, prefixBytes.length,payload.length - 1);
 98         //解析uri第6步,构造Uri
 99         String fullUriStr = new String(fullUri, Charset.forName("UTF-8"));
100         Uri uri = Uri.parse(fullUriStr);
101         //解析uri第7步,
102         return new UriRecord(uri);
103 
104     }
105     /*
106      * 解析uri格式数据.
107      */
108     public static UriRecord parse(NdefRecord record) {
109         short tnf = record.getTnf();
110         if (tnf == NdefRecord.TNF_WELL_KNOWN) {
111             return parseWellKnown(record);
112         } else if (tnf == NdefRecord.TNF_ABSOLUTE_URI) {
113             return parseAbsolute(record);
114         }
115         throw new IllegalArgumentException("Unknown TNF " + tnf);
116     }
117 }

 

posted @ 2015-09-05 14:52  f9q  阅读(1812)  评论(0编辑  收藏  举报