当前位置:   article > 正文

Android中的NFC操作_android nfc

android nfc

目录

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数据并解码:

  1. 使用Intent获取action并判断是否为NFC操作触发;action返回结果可能为null;可无此步
  2. 使用Intent获取其中包含的Tag型数据;可使用Tag数据获取卡序列号( getId()方法 )tag返回结果可能为null
  3. 使用Tag数据获取MifareClassic对象
  4. MifareClassic对象连接到NFC卡
  5. 根据MifareClassic对象获取卡中数据
  6. 关闭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,芯片,磁卡,近距通信

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/873448
推荐阅读
相关标签
  

闽ICP备14008679号