只有遵守NDEF uri 格式规范的数据才能写到nfc标签上.
NDEF uri 格式规范
uri 只有两部分:
第1个字节是uri协议映射值,如:0x01 表示uri以 http://www.开头.
然后是uri的内容 ,如 www.g.cn
uri协议映射值表
示例
ReadWriteUriActivity.java
import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast; /*
* 本apk主activity,拦截nfc标签事件
* 把读到的内容传给ShowNFCTagContentActivity
* 把封装好的uri写到临近的nfc标签.
*/
public class ReadWriteUriMainActivity extends Activity {
private TextView mSelectUri;
private String mUri; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_read_write_uri_main);
mSelectUri = (TextView) findViewById(R.id.textview_uri); } public void onClick_SelectUri(View view) {
Intent intent = new Intent(this, UriListActivity.class);
startActivityForResult(intent, ); } @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == && resultCode == ) {
mUri = data.getStringExtra("uri");
mSelectUri.setText(mUri);
}
} /*
* 如果本aty中的mUri空,就读nfc标签内容存到mUri中,
* 不空就封装uri并把它写到nfc标签中
*/
@Override
public void onNewIntent(Intent intent) {
if (mUri == null) {//读nfc标签内容存到mUri中,并显示
//把读到的内容传给ShowNFCTagContentActivity
Intent myIntent = new Intent(this, ShowNFCTagContentActivity.class);
myIntent.putExtras(intent);
myIntent.setAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
startActivity(myIntent);
} else {// 封装uri并把它写到nfc标签中 //封装uri并把它写到nfc标签 第1步,取nfc标签
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); //封装uri并把它写到nfc标签 第2步,构造NdefMessage,其中有NdefRecord,NdefRecord中有封装的uri
NdefMessage ndefMessage = new NdefMessage(
new NdefRecord[] { createUriRecord(mUri) }); //封装uri并把它写到nfc标签 第3步,封装uri并写入
if (writeTag(ndefMessage, tag)) {
mUri = null;
mSelectUri.setText("");
}
}
} /*
* 封装uri格式数据
* 现部分组成: 第一个字节是uri协议映射值
* uri协议映射值,如:0x01 表示uri以 http://www.开头.
* uri的内容 如:www.g.cn
*/
public NdefRecord createUriRecord(String uriStr) {
/*
* 封装uri格式数据 第1步, 根据uriStr中的值找到构造第一个字节的内容:uri协议映射值
*/
byte prefix = ;
for (Byte b : UriRecord.URI_PREFIX_MAP.keySet()) {
String prefixStr = UriRecord.URI_PREFIX_MAP.get(b).toLowerCase();
if ("".equals(prefixStr))
continue;
if (uriStr.toLowerCase().startsWith(prefixStr)) {
prefix = b;
uriStr = uriStr.substring(prefixStr.length());
break;
} }
/*
* 封装uri格式数据 第2步, uri的内容就是本函数的参数 uriStr
*/
/*
* 封装uri格式数据 第3步, 申请分配空间
*/
byte[] data = new byte[ + uriStr.length()]; /*
* 封装uri格式数据 第4步, 把uri头的映射值和uri内容写到刚申请的空间中
*/
data[] = prefix;
System.arraycopy(uriStr.getBytes(), , data, , uriStr.length()); /*
* 封装uri格式数据 第5步, 根据uri构造一个NdefRecord
*/
NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_URI, new byte[], data);
return record;
} /*
* 将封装好uri格式的NdefMessage写入到nfc标签中.
*/
boolean writeTag(NdefMessage message, Tag tag) {
int size = message.toByteArray().length;
try {
Ndef ndef = Ndef.get(tag);
if (ndef != null) {
ndef.connect();
if (!ndef.isWritable()) {
return false;
}
if (ndef.getMaxSize() < size) {
return false;
}
ndef.writeNdefMessage(message);
Toast.makeText(this, "ok", Toast.LENGTH_LONG).show();
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
UriRecord.java
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import android.net.Uri;
import android.nfc.NdefRecord; public class UriRecord { private final Uri mUri;// 存uri /*
* uri 格式数据中 第一个字节 存uri的头值映射表
* 如 0x01 表示uri以 http://www.开头,
* 存uri的头值是为了省空间.
*/
public static final Map<Byte, String> URI_PREFIX_MAP = new HashMap<Byte, String>(); static {
URI_PREFIX_MAP.put((byte) 0x00, "");
URI_PREFIX_MAP.put((byte) 0x01, "http://www.");
URI_PREFIX_MAP.put((byte) 0x02, "https://www.");
URI_PREFIX_MAP.put((byte) 0x03, "http://");
URI_PREFIX_MAP.put((byte) 0x04, "https://");
URI_PREFIX_MAP.put((byte) 0x05, "tel:");
URI_PREFIX_MAP.put((byte) 0x06, "mailto:");
URI_PREFIX_MAP.put((byte) 0x07, "ftp://anonymous:anonymous@");
URI_PREFIX_MAP.put((byte) 0x08, "ftp://ftp.");
URI_PREFIX_MAP.put((byte) 0x09, "ftps://");
URI_PREFIX_MAP.put((byte) 0x0A, "sftp://");
URI_PREFIX_MAP.put((byte) 0x0B, "smb://");
URI_PREFIX_MAP.put((byte) 0x0C, "nfs://");
URI_PREFIX_MAP.put((byte) 0x0D, "ftp://");
URI_PREFIX_MAP.put((byte) 0x0E, "dav://");
URI_PREFIX_MAP.put((byte) 0x0F, "news:");
URI_PREFIX_MAP.put((byte) 0x10, "telnet://");
URI_PREFIX_MAP.put((byte) 0x11, "imap:");
URI_PREFIX_MAP.put((byte) 0x12, "rtsp://");
URI_PREFIX_MAP.put((byte) 0x13, "urn:");
URI_PREFIX_MAP.put((byte) 0x14, "pop:");
URI_PREFIX_MAP.put((byte) 0x15, "sip:");
URI_PREFIX_MAP.put((byte) 0x16, "sips:");
URI_PREFIX_MAP.put((byte) 0x17, "tftp:");
URI_PREFIX_MAP.put((byte) 0x18, "btspp://");
URI_PREFIX_MAP.put((byte) 0x19, "btl2cap://");
URI_PREFIX_MAP.put((byte) 0x1A, "btgoep://");
URI_PREFIX_MAP.put((byte) 0x1B, "tcpobex://");
URI_PREFIX_MAP.put((byte) 0x1C, "irdaobex://");
URI_PREFIX_MAP.put((byte) 0x1D, "file://");
URI_PREFIX_MAP.put((byte) 0x1E, "urn:epc:id:");
URI_PREFIX_MAP.put((byte) 0x1F, "urn:epc:tag:");
URI_PREFIX_MAP.put((byte) 0x20, "urn:epc:pat:");
URI_PREFIX_MAP.put((byte) 0x21, "urn:epc:raw:");
URI_PREFIX_MAP.put((byte) 0x22, "urn:epc:");
URI_PREFIX_MAP.put((byte) 0x23, "urn:nfc:");
} private UriRecord(Uri uri) {
this.mUri = uri;
} public Uri getUri() {
return mUri;
} /*
* 这时,uri数据里没有uri头值,整个uri数据就是一个uri
*/
private static UriRecord parseAbsolute(NdefRecord ndefRecord) {
//1,取得数据流
byte[] payload = ndefRecord.getPayload();
//2,解析出一个uri
String uriStr = new String(payload, Charset.forName("UTF-8"));
Uri uri = Uri.parse(uriStr);
return new UriRecord(uri); }
/*
* 解析nfc uri格式的数据
*
*/
private static UriRecord parseWellKnown(NdefRecord ndefRecord) {
//解析uri第1步,判断record中是否是 uri
if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_URI))
return null;
//解析uri第2步,获取字节数据.
byte[] payload = ndefRecord.getPayload(); //解析uri第3步,解析出uri头,如https://等
String prefix = URI_PREFIX_MAP.get(payload[]);
//解析uri第4步,解析出uri的内容,如:www.g.cn
byte[] prefixBytes = prefix.getBytes(Charset.forName("UTF-8")); //解析uri第5步,合并uri头各内容.
byte[] fullUri = new byte[prefixBytes.length + payload.length - ];
System.arraycopy(prefixBytes, , fullUri, , prefixBytes.length);
System.arraycopy(payload, , fullUri, prefixBytes.length,payload.length - );
//解析uri第6步,构造Uri
String fullUriStr = new String(fullUri, Charset.forName("UTF-8"));
Uri uri = Uri.parse(fullUriStr);
//解析uri第7步,
return new UriRecord(uri); }
/*
* 解析uri格式数据.
*/
public static UriRecord parse(NdefRecord record) {
short tnf = record.getTnf();
if (tnf == NdefRecord.TNF_WELL_KNOWN) {
return parseWellKnown(record);
} else if (tnf == NdefRecord.TNF_ABSOLUTE_URI) {
return parseAbsolute(record);
}
throw new IllegalArgumentException("Unknown TNF " + tnf);
}
}