Android中的NFC操作

目录

1.申请权限

2.设置意图过滤器

3.判断NFC功能是否可用(NfcAdapter)

4.NFC感应(NfcAdapter)启用与禁用

5.NFC数据解码

6.案例代码一览


NFC的全称是“Near Field Communication”,意思是近场通信、与邻近的区域通信。

1.申请权限

<!-- NFC权限,无需动态申请 -->
<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标签指定源文件。
<!--AndroidManifests-->
<activityandroid:name=".NFCActivity"android:exported="true" ><intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/></intent-filter><intent-filter><action android:name="android.nfc.action.TAG_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/></intent-filter><intent-filter><action android:name="android.nfc.action.TECH_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/></intent-filter><!--定义了android.nfc.action.TECH_DISCOVERED的具体NFC技术--><!--资源文件位于xml/nfc_tech_filter.xml中--><meta-data android:name="android.nfc.action.TECH_DISCOVERED"android:resource="@xml/nfc_tech_filter"/></activity>
<!--xml/nfc_tech_filter.xml文件内容如下-->
<!--该文件为Android所有能支持的NFC类型-->
<resource><tech-list><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.IsoDep</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>
</resource>

3.判断NFC功能是否可用(NfcAdapter)

可使用NfcAdapter(NFC适配器)进行判断,NfcAdapter常用方法如下:

  • getDefaultAdapter(静态方法):获取NFC适配器对象;设备无NFC功能时返回null。
  • isEnabled:判断NFC功能是否可用(即是否开启)。
  • enableForegroundDispatch:用于启用NFC感应;第一个参数为上下文环境,第三参数为用于触发的待定意图,第三个参数为过滤器(会触发待定意图的NFC事件类型),第四个参数为指定NFC技术类型的二维数组。
  • disableForegroundDispatch:用于禁用NFC感应。
//获取NFC适配器
NfcAdapter nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this);
//判断设备是否有NFC功能
if(nfcAdapter==null){textView.setText("设备无NFC功能");
}
//判断设备是否开启NFC功能
else if (!nfcAdapter.isEnabled()) {textView.setText("设备未开启NFC功能");
}
else {textView.setText("设备已开启NFC功能");
}

4.NFC感应(NfcAdapter)启用与禁用

建议在页面暂停时禁用NFC感应,在页面运行时启用NFC感应

用于触发的待定意图(PendingIntent)为读取NFC信息通常为跳转至当前界面(即会触发onNewIntent方法请注意需将Activity设置为仅有一个,可在清单文件将launchMode设置为singleTop,或为Intent使用.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)

//准备NFC感应启动参数
//用于触发的待定意图
Intent intent=new Intent(MainActivity.this,MainActivity.class);
//intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);
//过滤器数组(会触发待定意图的NFC事件类型)
IntentFilter[] intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};
//指定NFC技术类型的二维数组
String[][] techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}};protected void onResume() {super.onResume();if(nfcAdapter!=null&&nfcAdapter.isEnabled()){//启用NFC感应nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList);}
}protected void onPause() {super.onPause();if(nfcAdapter!=null&&nfcAdapter.isEnabled()){//禁用NFC感应nfcAdapter.disableForegroundDispatch(MainActivity.this);}
}

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:获取存储大小,单位字节。

protected void onNewIntent(Intent intent) {super.onNewIntent(intent);//读取NFC信息Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);if(tag!=null){//获取序列号byte[] id_bytes=tag.getId();String id="";for(int i=0;i<id_bytes.length;i++){id=id+id_bytes[i];}//创建MifareClassic对象MifareClassic classic=MifareClassic.get(tag);try {//连接卡片classic.connect();//获取类型int typeI=classic.getType();String type=null;if(typeI==MifareClassic.TYPE_CLASSIC){type="传统类型";}else if(typeI==MifareClassic.TYPE_PLUS) {type="增强类型";}else if (typeI==MifareClassic.TYPE_PRO) {type="专业类型";}else {type="未知类型";}//获取其他数据int i1=classic.getSectorCount();//扇形区域int i2=classic.getBlockCount();//分块个数int i3=classic.getSize();//内存大小} catch (IOException e) {throw new RuntimeException(e);}finally {try {//无论是否发生异常都要释放卡片数据(关闭连接)classic.close();} catch (IOException e) {throw new RuntimeException(e);}}}}

6.案例代码一览

以下为MainActivity(界面只有一个TextView)的全部代码,请在清单文件声明(静态申请)NFC权限后使用。

public class MainActivity extends AppCompatActivity {private NfcAdapter nfcAdapter=null;private PendingIntent pendingIntent=null;private IntentFilter[] intentFilter=null;private String[][] techList=null;private TextView textView=null;@SuppressLint("MissingInflatedId")protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//获取控件textView=findViewById(R.id.textView);//获取NFC适配器nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this);//判断设备是否有NFC功能if(nfcAdapter==null){textView.setText("设备无NFC功能");}//判断设备是否开启NFC功能else if (!nfcAdapter.isEnabled()) {textView.setText("设备未开启NFC功能");}else {textView.setText("设备已开启NFC功能");}//准备NFC感应启动参数//用于触发的待定意图Intent intent=new Intent(MainActivity.this,MainActivity.class);//intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);//过滤器(会触发待定意图的NFC事件类型)intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};//指定NFC技术类型techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}};}protected void onResume() {super.onResume();if(nfcAdapter!=null&&nfcAdapter.isEnabled()){//启用NFC感应nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList);}}protected void onPause() {super.onPause();if(nfcAdapter!=null&&nfcAdapter.isEnabled()){//禁用NFC感应nfcAdapter.disableForegroundDispatch(MainActivity.this);}}//该界面触发NFC自动调用该方法protected void onNewIntent(Intent intent) {super.onNewIntent(intent);String outString="NFC卡无数据";//读取NFC信息Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);if(tag!=null){//获取序列号byte[] id_bytes=tag.getId();String id="";for(int i=0;i<id_bytes.length;i++){id=id+id_bytes[i];}outString="序列号为:"+id+"\n";//创建MifareClassic对象MifareClassic classic=MifareClassic.get(tag);try {//连接卡片classic.connect();//获取类型int typeI=classic.getType();String type=null;if(typeI==MifareClassic.TYPE_CLASSIC){type="传统类型";}else if(typeI==MifareClassic.TYPE_PLUS) {type="增强类型";}else if (typeI==MifareClassic.TYPE_PRO) {type="专业类型";}else {type="未知类型";}//获取其他数据int i1=classic.getSectorCount();//扇形区域int i2=classic.getBlockCount();//分块个数int i3=classic.getSize();//内存大小outString=outString+type+"\n"+"扇形区域:"+i1+"\n分块个数:"+i2+"\n内存大小:"+i3;} catch (IOException e) {throw new RuntimeException(e);}finally {try {//无论是否发生异常都要关闭连接classic.close();} catch (IOException e) {throw new RuntimeException(e);}}}textView.setText(outString);if(outString.equals("NFC卡无数据")){Handler handler=new Handler(new Handler.Callback() {public boolean handleMessage(@NonNull Message message) {textView.setText("设备已开启NFC功能");return true;}});new Thread(new Runnable() {public void run() {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}handler.sendEmptyMessage(123);}}).start();}}
}

tag:NFC,nfc,芯片,磁卡,近距通信

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/741693.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

效果图代渲多少钱一张?带你详细了解它的计费规则!

不知道有没有朋友遇到过渲着渲着就崩溃的情况发生&#xff0c;不然也不会去找代渲染的平台/某宝等渠道 也就是为了图能够顺利的跑出来&#xff0c;做了后期处理后&#xff0c;及时交付给客户。 我们以渲染100云渲染来举例&#xff0c;它成立2015年&#xff0c;是一家效果图代…

接口自动化测试框架:Pytest+Allure+Excel

1. Allure 简介 简介 Allure 框架是一个灵活的、轻量级的、支持多语言的测试报告工具&#xff0c;它不仅以 Web 的方式展示了简介的测试结果&#xff0c;而且允许参与开发过程的每个人可以从日常执行的测试中&#xff0c;最大限度地提取有用信息。 Allure 是由 Java 语言开发…

@Import注解作用

Import注解作用 理解springboot自动装配时&#xff0c;发现SpringBootApplication注解下的EnableAutoConfiguration注解头上有一个Import注解。 关于这个注解的作用&#xff0c;上网查找后发现理解的不是很明白&#xff0c;于是写了下面的Demo去理解。 两个pojo类&#xff1…

c++ stl 之 vector

#include <iostream> #include <vector>int main() {// 创建一个空的 vectorstd::vector<int> myVector;// 向 vector 中添加元素myVector.push_back(10);myVector.push_back(20);myVector.push_back(30);// 遍历 vector 并打印元素std::cout << "…

【InternLM 笔记】使用InternLM2-chat-1.8b制作时事问答知识库

环境版本 模型版本&#xff1a; InternLM2-chat-1.8b 准备环境 还是使用InternStudio进行操作 拉取环境 /root/share/install_conda_env_internlm_base.sh internlm开始实践 创建工作目录 cd ~ mkdir temp cd temp下载模型 import torch from modelscope import snapsh…

Unity DropDown 组件 详解

Unity版本 2022.3.13f1 Dropdown下拉菜单可以快速创建大量选项 一、 Dropwon属性详解 属性&#xff1a;功能&#xff1a;Interactable此组件是否接受输入&#xff1f;请参阅 Interactable。Transition确定控件以何种方式对用户操作进行可视化响应的属性。请参阅过渡选项。Nav…

MySQL 核心模块揭秘 | 09 期 | 二阶段提交 (3) flush、sync、commit 子阶段

1. 写在前面 经过上一篇文章的介绍&#xff0c;我们已经对 commit 阶段有了整体的认识。 这篇文章&#xff0c;我们一起进入各子阶段&#xff0c;看看它们都会干点什么&#xff0c;以及会怎么干。 为了方便理解&#xff0c;我们假设有 30 个事务&#xff0c;它们对应的用户线…

Titanic数据分析项目——Kaggle数据分析项目实战1

目前预测准确度达到77.511%, 会持续优化并且更新。 一、特征工程&#xff1a; 1、先对缺失值进行填充&#xff0c;先找到缺失值的位置&#xff0c;数值型数据填充众数&#xff0c;字符数据或者是离散型数据则填充出现最多的数据。 2、标准化数值型数据&#xff0c; 根据标准化…

Vue使用L2Dwidget

1、在根文件index.html中引入live2dw/lib/L2Dwidget.min.js 下载模型的文件&#xff0c;放在本地或者cdn 切换不同的模型 模型地址&#xff1a;https://github.com/xiazeyu/live2d-widget-models showLive2d(name: String) {var live2dWidget document.querySelector("…

大数据开发(Hive面试真题-卷三)

大数据开发&#xff08;Hive面试真题&#xff09; 1、Hive的文件存储格式都有哪些&#xff1f;2、Hive的count的用法&#xff1f;3、Hive得union和unionall的区别&#xff1f;4、Hive的join操作原理&#xff0c;left join、right join、inner join、outer join的异同&#xff1…

专升本 C语言笔记-01 printf 占位符 转义符

目录 一.printf()函数简介 1.1作用 将格式化后的字符串输出(打印东西) 1.2函数原型 1.3返回值 二.常见占位符 2.1.占位符的使用 2.2.格式修饰符 2.3.输出格式说明 三.转义字符 一.printf()函数简介 1.1作用 将格式化后的字符串输出(打印东西) printf…

Python数值方法在工程和科学问题解决中的应用

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 随着计算机技术的不断发展&#xff0c;Python作…

sqlserver语句中差集、并集、交集的用法

1、并集UNIONUNION 将两个查询的结果合并为一个结果集&#xff0c;并去除重复的行。 SELECT column1, column2 FROM Table1 UNION SELECT column1, column2 FROM Table2;2、交集INTERSECTINTERSECT 返回两个查询的结果中相同的行。 SELECT column1, column2 FROM Table1 IN…

C++之std::move

std::move 是C标准库中的一个函数模板&#xff0c;用于将其参数转换为右值引用。这通常用于移动语义&#xff0c;用于在避免不必要的复制的情况下&#xff0c;将资源&#xff08;例如内存、文件句柄等&#xff09;从一个对象转移到另一个对象。std::move 是C11引入的特性。 用…

【Python】新手入门学习:详细介绍开放封闭原则(OCP)及其作用、代码示例

【Python】新手入门学习&#xff1a;详细介绍开放封闭原则&#xff08;OCP&#xff09;及其作用、代码示例 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyT…

在Java中,Cloneable接口的作用,抛出CloneNotSupportedException的原因

文章目录 一、Cloneable接口的作用二、Cloneable接口的用法三、Cloneable的标记作用实现原理 一、Cloneable接口的作用 继承Cloneable接口并调用super.clone()是为了确保对象的克隆行为符合Java的规范。尽管Cloneable是一个空接口&#xff0c;没有定义任何方法&#xff0c;但如…

MQTT Topic通配符

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

如何不依赖Unity直接解压unitypackage的内容

使用场景 我们都知道unity的资源导出是导出成.unitypackage文件,如果要里面的内容,得打开Unity,将unitypackage导入进去才能看到里面的内容。 但是很多时候我们下了几十个unitypackage资源包,又不清楚好不好用,而且导入之后编译特别慢,unity又不提供批量解压的功能,所…

雷达图相关

1.中间显示数字 title: {text: 88,x: center,y: center,textStyle: {color: #333,fontWeight: bolder,fontSize: 64,} } 2.提示信息 tooltip: {trigger: item, // 当鼠标悬浮在某个数据项上时触发}, 3.修改中间颜色 默认&#xff1a; splitArea: {areaStyle: {color: [rgba(…

三分钟搞定普通函数和箭头函数的this指向问题

记住两个口诀&#xff1a; 普通函数的this是&#xff1a;谁调用这个函数&#xff0c;函数的this就指向谁 箭头函数的this是&#xff1a;箭头函数定义时的执行上下文的this是谁&#xff0c;箭头函数的this就指向谁 实例代码&#xff1a; var name222var b {name:111,fn:()>{…