您的位置:首页 > 其它

NFC技术的基础应用

2016-01-18 16:00 357 查看
      There are two major uses cases when working with NDEF data and Android:

        1、Reading NDEF data from an NFC tag

       2、Beaming NDEF messages from one device to another with Android Beam™。

     在安卓系统的应用中,最主要的有两种应用场景,第一个就是读取NEC标签里面的NDEF格式的数据,第二个就是不同设备间的NDEF信息数据的操作。接下来就主要学习一下这两块的实际应用。

    首先学习一下基础知识:

    一、权限的声明:

<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
    二、检查设备是否支持NFC
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent;
private IntentFilter[] filters;
private String[][] techLists=null;
private void checkNdef() {
nfcAdapter=NfcAdapter.getDefaultAdapter(this);
pendingIntent=PendingIntent.getActivity(MainActivity.this, 500, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_S         INGLE_TOP), 0);
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
filter.addDataType("*/*");
filters=new IntentFilter[]{filter};
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
if (nfcAdapter==null){
Toast.makeText(this,"不支持NFC功能",Toast.LENGTH_SHORT).show();
}else{
if (nfcAdapter.isEnabled()){
Toast.makeText(this,"NFC功能已打开",Toast.LENGTH_SHORT).show();
nfcAdapter.setNdefPushMessageCallback(this,this);
}else{
Intent intent= new Intent(Settings.ACTION_NFC_SETTINGS);
startActivity(intent);
}
}
}
    三、NFC调度方式:前台调度和标签调度
     所谓前台调度就是指我们直接在一个当前运行程序的Activity中显式的应用NFC;而标签调度就是指我们在我们的应用程序中配置好相关的Intent-filter,当设备接触到NFC标签的时候会调用有该配置的应用程序。

    前台调度方式:(Manifest文件下的配置不做任何调整,只是声明一个普通的Activity即可)

public class MainActivity extends AppCompatActivity implements NfcAdapter.CreateNdefMessageCallback{
private NfcAdapter nfcAdapter;
private PendingIntent pendingIntent;
private IntentFilter[] filters;
private String[][] techLists=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkNdef();
}

private void checkNdef() {
nfcAdapter=NfcAdapter.getDefaultAdapter(this);
pendingIntent=PendingIntent.getActivity(MainActivity.this, 500, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
filter.addDataType("*/*");
filters=new IntentFilter[]{filter};
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
if (nfcAdapter==null){
Toast.makeText(this,"不支持NFC功能",Toast.LENGTH_SHORT).show();
}else{
if (nfcAdapter.isEnabled()){
Toast.makeText(this,"NFC功能已打开",Toast.LENGTH_SHORT).show();
nfcAdapter.setNdefPushMessageCallback(this,this);
}else{
Intent intent= new Intent(Settings.ACTION_NFC_SETTINGS);
startActivity(intent);
}
}
}

@Override
protected void onResume() {
super.onResume();
//前台调度系统
nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,filters,techLists);
}

@Override
protected void onPause() {
super.onPause();
nfcAdapter.disableForegroundDispatch(MainActivity.this);
}
}    标签的调度系统:(此方式需要Manifest文件配置三种Intent过滤器,ACTION_NDEF_DISCOVERED、ACTION_TECH_SDISCOVERED、ACTION_TAG_DISCOVERED
<!--NEDF_DISCOVERED-->
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<data android:mimeType="text/plain"></data>
</intent-filter>
<!--TECH_DISCOVERED-->
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"></action>
</intent-filter>
<!--Define in the xml of resource-->
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/tech_list"></meta-data>
<!--TAG_DISCOVERED-->
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"></action>
</intent-filter>     tech_list.xml:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>                                                        
                                                                             
 读写模式

  NFC标签的读操作:

     基本步骤:

            第一:从intent里面获取到NDEFMessage;

            第二:解析数据

   文本的读操作:

String action=intent.getAction();
Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)){
//第一步:获取NDEFMEssage
NdefMessage[] messages=null;
Parcelable[] rawMsgs=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs !=null){
messages = new NdefMessage[rawMsgs.length];
for (int i = 0; i <messages.length ; i++) {
messages[i]= (NdefMessage) rawMsgs[i];
}
}else{
byte[]empty=new byte[]{};
NdefRecord ndefRecord=new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,empty,empty);
NdefMessage ndefMessage=new NdefMessage(new NdefRecord[]{ndefRecord});
messages = new NdefMessage[]{ndefMessage};
}
//第二步:解析文本数据
if (messages !=null &&messages.length>0){
for (int i = 0; i < messages.length; i++) {
int length=messages[i].getRecords().length;
NdefRecord[] records=messages[i].getRecords();
for (int j=0;j<length;j++){
for (NdefRecord ndefRecoder:records) {
//解析文本
if (isText){
//检查
Preconditions.checkArgument(Arrays.equals(ndefRecoder.getType(),NdefRecord.RTD_TEXT));
//获取payload内容
byte[] textPayload=ndefRecoder.getPayload();
//解析payload的第一个字节(包含编码格式,最高位为0的话,则为UTF-8;为1的话则为UTF-16)
Byte statuByte=ndefRecoder.getPayload()[0];
String textEncode;
if ((statuByte & 0x880)==0){
textEncode="UTF-8";
}else{
textEncode="UTF-16";
}
//获取language code,(通过第一个字节低五位,获取其长度)
int langLenth=statuByte&0x3F;
String langCode=new String(textPayload,1,langLenth,Charset.forName("UTF-8"));
try {
//获取真实文本的数据
String payloadText=new String(textPayload,langLenth+1,textPayload.length-langLenth-1,textEncode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}       Absolute_uri格式:
String action=intent.getAction();
Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)){
//第一步:获取NDEFMEssage
NdefMessage[] messages=null;
Parcelable[] rawMsgs=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs !=null){
messages = new NdefMessage[rawMsgs.length];
for (int i = 0; i <messages.length ; i++) {
messages[i]= (NdefMessage) rawMsgs[i];
}
}else{
byte[]empty=new byte[]{};
NdefRecord ndefRecord=new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,empty,empty);
NdefMessage ndefMessage=new NdefMessage(new NdefRecord[]{ndefRecord});
messages = new NdefMessage[]{ndefMessage};
}
//第二步:解析数据
if (messages !=null &&messages.length>0){
for (int i = 0; i < messages.length; i++) {
int length=messages[i].getRecords().length;
NdefRecord[] records=messages[i].getRecords();
for (int j=0;j<length;j++){
for (NdefRecord ndefRecoder:records) {
byte[] abPayload=ndefRecoder.getPayload();
Uri uri=Uri.parse(new String(abPayload,Charset.forName("UTF-8")));
}
}
}
}   Well_know_Uri:
String action=intent.getAction();
Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)){
//第一步:获取NDEFMEssage
NdefMessage[] messages=null;
Parcelable[] rawMsgs=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs !=null){
messages = new NdefMessage[rawMsgs.length];
for (int i = 0; i <messages.length ; i++) {
messages[i]= (NdefMessage) rawMsgs[i];
}
}else{
byte[]empty=new byte[]{};
NdefRecord ndefRecord=new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,empty,empty);
NdefMessage ndefMessage=new NdefMessage(new NdefRecord[]{ndefRecord});
messages = new NdefMessage[]{ndefMessage};
}
//第二步:解析数据
if (messages !=null &&messages.length>0){
for (int i = 0; i < messages.length; i++) {
int length=messages[i].getRecords().length;
NdefRecord[] records=messages[i].getRecords();
for (int j=0;j<length;j++){
for (NdefRecord ndefRecoder:records) {
Preconditions.checkArgument(Arrays.equals(ndefRecoder.getType(),NdefRecord.RTD_URI));
byte[] payload=ndefRecoder.getPayload();
String prefix=URI_PREFIX_MAP.get(payload[0]);
byte[] fullUri= Bytes.concat(prefix.getBytes(Charset.forName("UTF-8")), Arrays.copyOfRange(payload, 1, payload.length));
Uri uri=Uri.parse(new String(fullUri));
}
}
}
}
     写操作:


  TNF_WELL_KNOWN with RTD_TEXT

   
<span style="color:rgba(0, 0, 0, 0.870588235294118);">  </span><span style="color:#333333;">public static NdefMessage writeText(String payload, 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 = payload.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);
NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], data);
return new NdefMessage(new NdefRecord[]{record});
}</span>


   TNF_ABSOLUTE_URI

public static NdefMessage writeAbsoluteUri(String uri){
NdefRecord uriRecord = new NdefRecord(
NdefRecord.TNF_ABSOLUTE_URI ,
uri.getBytes(Charset.forName("US-ASCII")),
new byte[0], new byte[0]);
return new NdefMessage(new NdefRecord[]{uriRecord});
}


   TNF_WELL_KNOWN with RTD_URI

public static NdefMessage writeWellKnowUri(String uri){
byte[] uriField = uri.getBytes(Charset.forName("US-ASCII"));
byte[] payload = new byte[uriField.length + 1];              //add 1 for the URI Prefix
payload[0] = 0x01;                                      //prefixes http://www. to the URI
System.arraycopy(uriField, 0, payload, 1, uriField.length);  //appends URI to payload
NdefRecord rtdUriRecord = new NdefRecord( NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
return new NdefMessage(new NdefRecord[]{<span style="font-family: Roboto, sans-serif;">rtdUriRecord </span>});
}<span style="font-size:18px;font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><strong>      </strong>         </span><span style="font-size:14px;font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">            </span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Nfc 读写模式