您当前的位置: 首页 > 

xiangzhihong8

暂无认证

  • 1浏览

    0关注

    1324博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

nfc近场通信

xiangzhihong8 发布时间:2015-12-07 17:46:39 ,浏览量:1

NFC简介:

Near Field Communication 近场通信,是一种数据传输技术。

与wifi、蓝牙、红外线等数据传输技术的一个主要差异就是有效距离一般不能超过4cm。

NFC支持3种工作模式:

1.读卡器模式;

2.仿真卡模式;

3.点对点模式;

1.读卡器模式:

通过NFC设备(支持NFC的Android手机)从带有NFC芯片的标签、贴纸、报纸、明信片等媒介读取信息,或将数据写到这些媒介中。

2.仿真卡模式:

是将支持NFC的手机或其他电子设备当成借记卡、信用卡、公交卡、门禁卡等IC卡使用;基本原理是将相应的IC卡中的信息(支付凭证)封装成数据包存储在支持NFC的手机中,在使用时还需要一个NFC射频器(相当于刷传统IC卡时使用的刷卡器),将手机靠近NFC射频器,手机就会收到NFC射频器发过来的信号,在通过一系列复杂的验证后,将IC卡的相应信息传入NFC射频器,最后这些IC卡数据会传入NFC射频器连接的计算机,并进行相应的处理(如电子转账、开门等操作)。

3.点对点模式:

与蓝牙、红外差不多,可以用于不同的NFC设备之间进行数据交换,只是NFC的点对点模式有效距离更短,不能超过4cm;但是如果两个设备使用的都是Android4.2及以上版本,NFC会直接利用蓝牙传输,这种技术被称为Android Beam,所以Android Beam传输数据的两部设备不局限于4cm之内。

基础知识:

1.Android SDK API主要支持NFC论坛标准(Forum Standard),这种标准被称为NDEF(NFC Data Exchange Format,NFC数据交换格式);

2.Android SDK API支持如下三种NDEF数据的操作:

a.从NFC标签读取NDEF格式的数据;

b.向NFC标签写入NDEF格式的数据;

c.通过Android Beam技术将NDEF数据发送到另一部NFC设备;

3.在一个NFC设备读取NFC标签或另一个NFC设备中的数据之前会在0.1秒的时间之内建立NFC连接,然后数据会自动从被读取一端流向读取数据的一端;数据接收端会根据具体的数据格式和标签类型调用相应的Activity(这种行为也称为Tag Dispatch),这些Activity都需要定义Intent Filter,这些Intent Filter中就会指定不同的过滤机制,分为三个级别,也称为NFC的三重过滤机制。

4.NDEF_DISCOVERED:

只过滤固定格式的NDEF数据。例如:纯文本、指定协议(http、ftp、smb等)的URI等;

  TECH_DISCOVERED:

当ACTION_NDEF_DISCOVERED指定的过滤机制无法匹配Tag时,就会使用这种过滤机制进行匹配,这种过滤机制并不是通过Tag中的数据格式进行匹配的,而是根据Tag支持的数据存储格式进行匹配,因此这种过滤机制的范围更广;

  TAG_DISCOVERED:

如果将NFC过滤机制看成if...else if...else语句的话,那么这种过滤机制就相当于else部分,当前面两种过滤机制都匹配失败后,系统就会利用这种过滤机制来处理,这种过滤机制用来处理未识别的Tag(数据格式不对,而且Tag支持的格式也不匹配)。

5.Android系统会依次匹配NDEF_DISCOVERED、TECH_DISCOVERED和TAG_DISCOVERED;如果通过三重过滤机制仍然无法匹配Tag,则什么都不做;通常在成功匹配Tag后,Android设备会发出比较清脆的声音,而未成功匹配Tag,就会发出比较沉闷的声音。

此过程的处理流程如下图所示:

6.在manifest文件中需要设置的部分有:

设置权限:

限制Android版本:

android:minSdkVersion="14"

限制安装的设备:

设置Activity的Intent Filter,比如设置为三种过滤机制的一种:

    

接下来,我们来第一个例子,这个例子是属于读卡器模式,从NFC芯片中读取和写入数据。

它的manifest文件内容如下:

[html]  view plain copy
  1.   
  2.   
  3.   
  4.       
  5.       
  6.       
  7.   
  8.       
  9.   
  10.       
  11.   
  12.           
  13.               
  14.                   
  15.   
  16.                   
  17.               
  18.               
  19.               
  20.                   
  21.               
  22.               
  23.               
  24.           
  25.       
  26.   
  27.   

它的Activity的内容如下,包括读取、写入、删除三大功能:(其中删除功能是通过写入空值来实现的)

[java]  view plain copy
  1. import java.io.IOException;  
  2. import java.io.UnsupportedEncodingException;  
  3. import java.nio.charset.Charset;  
  4.   
  5. import android.media.AudioManager;  
  6. import android.media.MediaPlayer;  
  7. import android.media.RingtoneManager;  
  8. import android.net.Uri;  
  9. import android.nfc.FormatException;  
  10. import android.nfc.NdefMessage;  
  11. import android.nfc.NdefRecord;  
  12. import android.nfc.NfcAdapter;  
  13. import android.nfc.Tag;  
  14. import android.nfc.tech.MifareUltralight;  
  15. import android.nfc.tech.Ndef;  
  16. import android.nfc.tech.NfcA;  
  17. import android.os.Bundle;  
  18. import android.app.Activity;  
  19. import android.app.PendingIntent;  
  20. import android.content.Context;  
  21. import android.content.Intent;  
  22. import android.content.IntentFilter;  
  23. import android.graphics.Color;  
  24. import android.util.Log;  
  25. import android.view.Menu;  
  26. import android.view.View;  
  27. import android.view.View.OnClickListener;  
  28. import android.widget.Button;  
  29. import android.widget.TextView;  
  30. import android.widget.Toast;  
  31.   
  32. public class NfcDemoActivity extends Activity implements OnClickListener {  
  33.   
  34.     // NFC适配器  
  35.     private NfcAdapter nfcAdapter = null;  
  36.     // 传达意图  
  37.     private PendingIntent pi = null;  
  38.     // 滤掉组件无法响应和处理的Intent  
  39.     private IntentFilter tagDetected = null;  
  40.     // 文本控件  
  41.     private TextView promt = null;  
  42.     // 是否支持NFC功能的标签  
  43.     private boolean isNFC_support = false;  
  44.     // 读、写、删按钮控件  
  45.     private Button readBtn, writeBtn, deleteBtn;  
  46.   
  47.     @Override  
  48.     protected void onCreate(Bundle savedInstanceState) {  
  49.         super.onCreate(savedInstanceState);  
  50.         setContentView(R.layout.activity_nfc_demo);  
  51.         setupViews();  
  52.         initNFCData();  
  53.     }  
  54.   
  55.     @Override  
  56.     protected void onResume() {  
  57.         super.onResume();  
  58.         if (isNFC_support == false) {  
  59.             // 如果设备不支持NFC或者NFC功能没开启,就return掉  
  60.             return;  
  61.         }  
  62.         // 开始监听NFC设备是否连接  
  63.         startNFC_Listener();  
  64.   
  65.         if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(this.getIntent()  
  66.                 .getAction())) {  
  67.             // 注意这个if中的代码几乎不会进来,因为刚刚在上一行代码开启了监听NFC连接,下一行代码马上就收到了NFC连接的intent,这种几率很小  
  68.             // 处理该intent  
  69.             processIntent(this.getIntent());  
  70.         }  
  71.     }  
  72.   
  73.     @Override  
  74.     protected void onPause() {  
  75.         super.onPause();  
  76.         if (isNFC_support == true) {  
  77.             // 当前Activity如果不在手机的最前端,就停止NFC设备连接的监听  
  78.             stopNFC_Listener();  
  79.         }  
  80.     }  
  81.   
  82.     @Override  
  83.     protected void onNewIntent(Intent intent) {  
  84.         super.onNewIntent(intent);  
  85.         // 当前app正在前端界面运行,这个时候有intent发送过来,那么系统就会调用onNewIntent回调方法,将intent传送过来  
  86.         // 我们只需要在这里检验这个intent是否是NFC相关的intent,如果是,就调用处理方法  
  87.         if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {  
  88.             processIntent(intent);  
  89.         }  
  90.     }  
  91.   
  92.     @Override  
  93.     public void onClick(View v) {  
  94.   
  95.         // 点击读按钮后  
  96.         if (v.getId() == R.id.read_btn) {  
  97.             try {  
  98.                 String content = read(tagFromIntent);  
  99.                 if (content != null && !content.equals("")) {  
  100.                     promt.setText(promt.getText() + "nfc标签内容:\n" + content  
  101.                             + "\n");  
  102.                 } else {  
  103.                     promt.setText(promt.getText() + "nfc标签内容:\n" + "内容为空\n");  
  104.                 }  
  105.             } catch (IOException e) {  
  106.                 promt.setText(promt.getText() + "错误:" + e.getMessage() + "\n");  
  107.                 Log.e("myonclick", "读取nfc异常", e);  
  108.             } catch (FormatException e) {  
  109.                 promt.setText(promt.getText() + "错误:" + e.getMessage() + "\n");  
  110.                 Log.e("myonclick", "读取nfc异常", e);  
  111.             }  
  112.             // 点击写后写入  
  113.         } else if (v.getId() == R.id.write_btn) {  
  114.             try {  
  115.                 write(tagFromIntent);  
  116.             } catch (IOException e) {  
  117.                 promt.setText(promt.getText() + "错误:" + e.getMessage() + "\n");  
  118.                 Log.e("myonclick", "写nfc异常", e);  
  119.             } catch (FormatException e) {  
  120.                 promt.setText(promt.getText() + "错误:" + e.getMessage() + "\n");  
  121.                 Log.e("myonclick", "写nfc异常", e);  
  122.             }  
  123.         } else if (v.getId() == R.id.delete_btn) {  
  124.             try {  
  125.                 delete(tagFromIntent);  
  126.             } catch (IOException e) {  
  127.                 promt.setText(promt.getText() + "错误:" + e.getMessage() + "\n");  
  128.                 Log.e("myonclick", "删除nfc异常", e);  
  129.             } catch (FormatException e) {  
  130.                 promt.setText(promt.getText() + "错误:" + e.getMessage() + "\n");  
  131.                 Log.e("myonclick", "删除nfc异常", e);  
  132.             }  
  133.         }  
  134.     }  
  135.   
  136.     private void setupViews() {  
  137.         // 控件的绑定  
  138.         promt = (TextView) findViewById(R.id.promt);  
  139.         readBtn = (Button) findViewById(R.id.read_btn);  
  140.         writeBtn = (Button) findViewById(R.id.write_btn);  
  141.         deleteBtn = (Button) findViewById(R.id.delete_btn);  
  142.         // 给文本控件赋值初始文本  
  143.         promt.setText("等待RFID标签");  
  144.         // 监听读、写、删按钮控件  
  145.         readBtn.setOnClickListener(this);  
  146.         writeBtn.setOnClickListener(this);  
  147.         deleteBtn.setOnClickListener(this);  
  148.     }  
  149.   
  150.     private void initNFCData() {  
  151.         // 初始化设备支持NFC功能  
  152.         isNFC_support = true;  
  153.         // 得到默认nfc适配器  
  154.         nfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());  
  155.         // 提示信息定义  
  156.         String metaInfo = "";  
  157.         // 判定设备是否支持NFC或启动NFC  
  158.         if (nfcAdapter == null) {  
  159.             metaInfo = "设备不支持NFC!";  
  160.             Toast.makeText(this, metaInfo, Toast.LENGTH_SHORT).show();  
  161.             isNFC_support = false;  
  162.         }  
  163.         if (!nfcAdapter.isEnabled()) {  
  164.             metaInfo = "请在系统设置中先启用NFC功能!";  
  165.             Toast.makeText(this, metaInfo, Toast.LENGTH_SHORT).show();  
  166.             isNFC_support = false;  
  167.         }  
  168.   
  169.         if (isNFC_support == true) {  
  170.             init_NFC();  
  171.         } else {  
  172.             promt.setTextColor(Color.RED);  
  173.             promt.setText(metaInfo);  
  174.         }  
  175.     }  
  176.   
  177.     @Override  
  178.     public boolean onCreateOptionsMenu(Menu menu) {  
  179.         // Inflate the menu; this adds items to the action bar if it is present.  
  180.         getMenuInflater().inflate(R.menu.nfc_demo, menu);  
  181.         return true;  
  182.     }  
  183.   
  184.     // 字符序列转换为16进制字符串  
  185.     private String bytesToHexString(byte[] src) {  
  186.         return bytesToHexString(src, true);  
  187.     }  
  188.   
  189.     private String bytesToHexString(byte[] src, boolean isPrefix) {  
  190.         StringBuilder stringBuilder = new StringBuilder();  
  191.         if (isPrefix == true) {  
  192.             stringBuilder.append("0x");  
  193.         }  
  194.         if (src == null || src.length > 4) & 0x0F, 16));  
  195.             buffer[1] = Character.toUpperCase(Character.forDigit(src[i] & 0x0F,  
  196.                     16));  
  197.             System.out.println(buffer);  
  198.             stringBuilder.append(buffer);  
  199.         }  
  200.         return stringBuilder.toString();  
  201.     }  
  202.   
  203.     private Tag tagFromIntent;  
  204.   
  205.     /** 
  206.      * Parses the NDEF Message from the intent and prints to the TextView 
  207.      */  
  208.     public void processIntent(Intent intent) {  
  209.         if (isNFC_support == false)  
  210.             return;  
  211.   
  212.         // 取出封装在intent中的TAG  
  213.         tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
  214.   
  215.         promt.setTextColor(Color.BLUE);  
  216.         String metaInfo = "";  
  217.         metaInfo += "卡片ID:" + bytesToHexString(tagFromIntent.getId()) + "\n";  
  218.         Toast.makeText(this, "找到卡片", Toast.LENGTH_SHORT).show();  
  219.   
  220.         // Tech List  
  221.         String prefix = "android.nfc.tech.";  
  222.         String[] techList = tagFromIntent.getTechList();  
  223.   
  224.         //分析NFC卡的类型: Mifare Classic/UltraLight Info  
  225.         String CardType = "";  
  226.         for (int i = 0; i 
关注
打赏
1482932726
查看更多评论
立即登录/注册

微信扫码登录

0.0665s