Android中的NFC操纵

锦通  金牌会员 | 2024-8-27 03:38:30 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 554|帖子 554|积分 1662

目次
1.申请权限
2.设置意图过滤器
3.判断NFC功能是否可用(NfcAdapter)
4.NFC感应(NfcAdapter)启用与禁用
5.NFC数据解码
6.案例代码一览

NFC的全称是“Near Field Communication”,意思是近场通信、与邻近的地区通信。该功能由NfcAdapter(NFC适配器)控制。
1.申请权限

  1. <!-- NFC权限,无需动态申请 -->
  2. <uses-permission android:name="android.permission.NFC" />
复制代码
2.设置意图过滤器

在清单文件(AndroidManifests)中为Activity设置意图过滤器(IntentFilter);在程序检测到NFC操纵时将跳转至该界面。
本部分操纵用于从外部直接打开指定Activity。


  • android.nfc.action.NDEF_DISCOVERED:指定了当应用程序收到包罗NDEF(NFC Data Exchange Format)数据的NFC标签时应该触发的动作。NDEF是一种用于在NFC设备之间交换信息的尺度格式。
  • android.nfc.action.TAG_DISCOVERED:界说了当检测到NFC标签时应该触发的动作。这个动作用于处置惩罚未包罗NDEF数据的NFC标签。
  • android.nfc.action.TECH_DISCOVERED:指定了当检测到支持的NFC技术时应该触发的动作。这允许应用程序处置惩罚特定的NFC技术。其中具体的NFC技术由meta-data标签指定源文件。
  1. <!--AndroidManifests-->
  2. <activity
  3.     android:name=".NFCActivity"
  4.     android:exported="true" >
  5.     <intent-filter>
  6.         <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
  7.         <category android:name="android.intent.category.DEFAULT"/>
  8.     </intent-filter>
  9.     <intent-filter>
  10.         <action android:name="android.nfc.action.TAG_DISCOVERED"/>
  11.         <category android:name="android.intent.category.DEFAULT"/>
  12.     </intent-filter>
  13.     <intent-filter>
  14.         <action android:name="android.nfc.action.TECH_DISCOVERED"/>
  15.         <category android:name="android.intent.category.DEFAULT"/>
  16.     </intent-filter>
  17.     <!--定义了android.nfc.action.TECH_DISCOVERED的具体NFC技术-->
  18.     <!--资源文件位于xml/nfc_tech_filter.xml中-->
  19.     <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
  20.         android:resource="@xml/nfc_tech_filter"/>
  21. </activity>
复制代码
  1. <!--xml/nfc_tech_filter.xml文件内容如下-->
  2. <!--该文件为Android所有能支持的NFC类型-->
  3. <resource>
  4.     <tech-list>
  5.         <tech>android.nfc.tech.NfcA</tech>
  6.         <tech>android.nfc.tech.NfcB</tech>
  7.         <tech>android.nfc.tech.NfcF</tech>
  8.         <tech>android.nfc.tech.NfcV</tech>
  9.         <tech>android.nfc.tech.IsoDep</tech>
  10.         <tech>android.nfc.tech.Ndef</tech>
  11.         <tech>android.nfc.tech.NdefFormatable</tech>
  12.         <tech>android.nfc.tech.MifareClassic</tech>
  13.         <tech>android.nfc.tech.MifareUltralight</tech>
  14.     </tech-list>
  15. </resource>
复制代码
3.判断NFC功能是否可用(NfcAdapter)

可利用NfcAdapter(NFC适配器)举行判断,未开启时跳转至NFC设置界面;NfcAdapter常用方法如下:


  • getDefaultAdapter(静态方法):获取NFC适配器对象;设备无NFC功能时返回null。
  • isEnabled:判断NFC功能是否可用(即是否开启)。
  • enableForegroundDispatch:用于启用NFC感应;第一个参数为上下文环境,第三参数为用于触发的待定意图,第三个参数为过滤器(会触发待定意图的NFC事件类型),第四个参数为指定NFC技术类型的二维数组。
  • disableForegroundDispatch:用于禁用NFC感应。
  1. //获取NFC适配器
  2. NfcAdapter nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this);
  3. //判断设备是否有NFC功能
  4. if(nfcAdapter==null){
  5.     textView.setText("设备无NFC功能");
  6. }
  7. //判断设备是否开启NFC功能
  8. else if (!nfcAdapter.isEnabled()) {
  9.     textView.setText("设备未开启NFC功能");
  10.     //跳转至设置NFC界面
  11.     Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS);
  12.     startActivity(intent);
  13. }
  14. else {
  15.     textView.setText("设备已开启NFC功能");
  16. }
复制代码
4.NFC感应(NfcAdapter)启用与禁用

建议在页面暂停时禁用NFC感应,在页面运行时启用NFC感应
用于触发的待定意图(PendingIntent)为读取NFC信息通常为跳转至当前界面(即会触发onNewIntent方法请注意需将Activity设置为仅有一个,可在清单文件将launchMode设置为singleTop,或为Intent利用.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
  1. //准备NFC感应启动参数
  2. //用于触发的待定意图
  3. Intent intent=new Intent(MainActivity.this,MainActivity.class);
  4. //intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
  5. PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);
  6. //过滤器数组(会触发待定意图的NFC事件类型)
  7. IntentFilter[] intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};
  8. //指定NFC技术类型的二维数组
  9. String[][] techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}};
  10. protected void onResume() {
  11.     super.onResume();
  12.     if(nfcAdapter!=null&&nfcAdapter.isEnabled()){
  13.         //启用NFC感应
  14.         nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList);
  15.     }
  16. }
  17. protected void onPause() {
  18.     super.onPause();
  19.     if(nfcAdapter!=null&&nfcAdapter.isEnabled()){
  20.         //禁用NFC感应
  21.         nfcAdapter.disableForegroundDispatch(MainActivity.this);
  22.     }
  23. }
复制代码
5.NFC数据解码

用于触发的待定意图(PendingIntent)为读取NFC信息通常为跳转至当前界面(即会触发onNewIntent方法请注意需将Activity设置为仅有一个
可以通过重写onNewIntent方法,获取NFC数据并解码:

  • 利用Intent获取action并判断是否为NFC操纵触发;action返回效果可能为null;可无此步
  • 利用Intent获取其中包罗的Tag型数据;可利用Tag数据获取卡序列号( getId()方法 )tag返回效果可能为null
  • 利用Tag数据获取MifareClassic对象
  • MifareClassic对象连接到NFC卡
  • 根据MifareClassic对象获取卡中数据
  • 关闭MifareClassic与卡的连接,无论是否出现异常
MifareClassic类常用方法


  • get(静态方法):从Tag对象中获取卡片对象的信息。
  • connet:连接卡片数据。
  • close:释放卡片数据。
  • getType:获取卡片类型。TYPE_CLASSIC表示传统型,TYPE_PLUS表示加强型,TYPE_PRO表示专业型。
  • getSectorCount:获取扇形地区。
  • getBlockCount:获取分块个数。
  • getSize:获取存储大小,单位字节。
  1. protected void onNewIntent(Intent intent) {
  2.         super.onNewIntent(intent);
  3.         //读取NFC信息
  4.         Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
  5.         if(tag!=null){
  6.             //获取序列号
  7.             byte[] id_bytes=tag.getId();
  8.             String id="";
  9.             for(int i=0;i<id_bytes.length;i++){
  10.                 id=id+id_bytes[i];
  11.             }
  12.             //创建MifareClassic对象
  13.             MifareClassic classic=MifareClassic.get(tag);
  14.             try {
  15.                 //连接卡片
  16.                 classic.connect();
  17.                 //获取类型
  18.                 int typeI=classic.getType();
  19.                 String type=null;
  20.                 if(typeI==MifareClassic.TYPE_CLASSIC){
  21.                     type="传统类型";
  22.                 }
  23.                 else if(typeI==MifareClassic.TYPE_PLUS) {
  24.                     type="增强类型";
  25.                 }
  26.                 else if (typeI==MifareClassic.TYPE_PRO) {
  27.                     type="专业类型";
  28.                 }
  29.                 else {
  30.                     type="未知类型";
  31.                 }
  32.                 //获取其他数据
  33.                 int i1=classic.getSectorCount();//扇形区域
  34.                 int i2=classic.getBlockCount();//分块个数
  35.                 int i3=classic.getSize();//内存大小
  36.             } catch (IOException e) {
  37.                 throw new RuntimeException(e);
  38.             }finally {
  39.                 try {
  40.                     //无论是否发生异常都要释放卡片数据(关闭连接)
  41.                     classic.close();
  42.                 } catch (IOException e) {
  43.                     throw new RuntimeException(e);
  44.                 }
  45.             }
  46.         }
  47.     }
复制代码
6.案例代码一览

以下为MainActivity(界面只有一个TextView)的全部代码,请在清单文件声明(静态申请)NFC权限后利用。
  1. public class MainActivity extends AppCompatActivity {
  2.     private NfcAdapter nfcAdapter=null;
  3.     private PendingIntent pendingIntent=null;
  4.     private IntentFilter[] intentFilter=null;
  5.     private String[][] techList=null;
  6.     private TextView textView=null;
  7.     @SuppressLint("MissingInflatedId")
  8.     protected void onCreate(Bundle savedInstanceState) {
  9.         super.onCreate(savedInstanceState);
  10.         setContentView(R.layout.activity_main);
  11.         //获取控件
  12.         textView=findViewById(R.id.textView);
  13.         //获取NFC适配器
  14.         nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this);
  15.         //判断设备是否有NFC功能
  16.         if(nfcAdapter==null){
  17.             textView.setText("设备无NFC功能");
  18.         }
  19.         //判断设备是否开启NFC功能
  20.         else if (!nfcAdapter.isEnabled()) {
  21.             textView.setText("设备未开启NFC功能");
  22.             //跳转至NFC设置界面
  23.             Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS);
  24.             startActivity(intent);
  25.         }
  26.         else {
  27.             textView.setText("设备已开启NFC功能");
  28.         }
  29.         //准备NFC感应启动参数
  30.         //用于触发的待定意图
  31.         Intent intent=new Intent(MainActivity.this,MainActivity.class);
  32.         //intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
  33.         pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);
  34.         //过滤器(会触发待定意图的NFC事件类型)
  35.         intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};
  36.         //指定NFC技术类型
  37.         techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}};
  38.     }
  39.     protected void onResume() {
  40.         super.onResume();
  41.         if(nfcAdapter!=null&&nfcAdapter.isEnabled()){
  42.             //启用NFC感应
  43.             nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList);
  44.         }
  45.     }
  46.     protected void onPause() {
  47.         super.onPause();
  48.         if(nfcAdapter!=null&&nfcAdapter.isEnabled()){
  49.             //禁用NFC感应
  50.             nfcAdapter.disableForegroundDispatch(MainActivity.this);
  51.         }
  52.     }
  53.     //该界面触发NFC自动调用该方法
  54.     protected void onNewIntent(Intent intent) {
  55.         super.onNewIntent(intent);
  56.         String outString="NFC卡无数据";
  57.         //读取NFC信息
  58.         Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
  59.         if(tag!=null){
  60.             //获取序列号
  61.             byte[] id_bytes=tag.getId();
  62.             String id="";
  63.             for(int i=0;i<id_bytes.length;i++){
  64.                 id=id+id_bytes[i];
  65.             }
  66.             outString="序列号为:"+id+"\n";
  67.             //创建MifareClassic对象
  68.             MifareClassic classic=MifareClassic.get(tag);
  69.             try {
  70.                 //连接卡片
  71.                 classic.connect();
  72.                 //获取类型
  73.                 int typeI=classic.getType();
  74.                 String type=null;
  75.                 if(typeI==MifareClassic.TYPE_CLASSIC){
  76.                     type="传统类型";
  77.                 }
  78.                 else if(typeI==MifareClassic.TYPE_PLUS) {
  79.                     type="增强类型";
  80.                 }
  81.                 else if (typeI==MifareClassic.TYPE_PRO) {
  82.                     type="专业类型";
  83.                 }
  84.                 else {
  85.                     type="未知类型";
  86.                 }
  87.                 //获取其他数据
  88.                 int i1=classic.getSectorCount();//扇形区域
  89.                 int i2=classic.getBlockCount();//分块个数
  90.                 int i3=classic.getSize();//内存大小
  91.                 outString=outString+type+"\n"+"扇形区域:"+i1+"\n分块个数:"+i2+"\n内存大小:"+i3;
  92.             } catch (IOException e) {
  93.                 throw new RuntimeException(e);
  94.             }finally {
  95.                 try {
  96.                     //无论是否发生异常都要关闭连接
  97.                     classic.close();
  98.                 } catch (IOException e) {
  99.                     throw new RuntimeException(e);
  100.                 }
  101.             }
  102.         }
  103.         textView.setText(outString);
  104.         if(outString.equals("NFC卡无数据")){
  105.             Handler handler=new Handler(new Handler.Callback() {
  106.                 public boolean handleMessage(@NonNull Message message) {
  107.                     textView.setText("设备已开启NFC功能");
  108.                     return true;
  109.                 }
  110.             });
  111.             new Thread(new Runnable() {
  112.                 public void run() {
  113.                     try {
  114.                         Thread.sleep(3000);
  115.                     } catch (InterruptedException e) {
  116.                         throw new RuntimeException(e);
  117.                     }
  118.                     handler.sendEmptyMessage(123);
  119.                 }
  120.             }).start();
  121.         }
  122.     }
  123. }
复制代码
tag:NFC,nfc,芯片,磁卡,近距通信

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

锦通

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表