Android--NFC读写
一、NFC API
API地址:https://www.android-doc.com/guide/topics/connectivity/nfc/nfc.html
二、简介
NFC的三种模式
读卡器模式(Reader/writer mode)、仿真卡模式(Card Emulation Mode)、点对点模式(P2P mode)。
(1)读卡器模式
数据在NFC芯片中,可以简单理解成“刷标签”。本质上就是通过支持NFC的手机或其它电子设备从带有NFC芯片的标签、贴纸、名片等媒介中读写信息。通常NFC标签是不需要外部供电的。当支持NFC的外设向NFC读写数据时,它会发送某种磁场,而这个磁场会自动的向NFC标签供电。
(2)仿真卡模式
数据在支持NFC的手机或其它电子设备中,可以简单理解成“刷手机”。本质上就是将支持NFC的手机或其它电子设备当成借记卡、公交卡、门禁卡等IC卡使用。基本原理是将相应IC卡中的信息凭证封装成数据包存储在支持NFC的外设中 。
在使用时还需要一个NFC射频器(相当于刷卡器)。将手机靠近NFC射频器,手机就会接收到NFC射频器发过来的信号,在通过一系列复杂的验证后,将IC卡的相应信息传入NFC射频器,最后这些IC卡数据会传入NFC射频器连接的电脑,并进行相应的处理(如电子转帐、开门等操作)。
(3)点对点模式
该模式与蓝牙、红外差不多,用于不同NFC设备之间进行数据交换,不过这个模式已经没有有“刷”的感觉了。其有效距离一般不能超过4厘米,但传输建立速度要比红外和蓝牙技术快很多,传输速度比红外块得多,如过双方都使用Android4.2,NFC会直接利用蓝牙传输。这种技术被称为Android Beam。所以使用Android Beam传输数据的两部设备不再限于4厘米之内。
点对点模式的典型应用是两部支持NFC的手机或平板电脑实现数据的点对点传输,例如,交换图片或同步设备联系人。因此,通过NFC,多个设备如数字相机,计算机,手机之间,都可以快速连接,并交换资料或者服务。
二、NDEF,TECH,TAG 解析顺序
在使用之前,我们要先去了解下NFC 的tag分发系统
如果想让android设备感应到NFC标签,你要保证两点
1:屏幕没有锁住
2:NFC功能已经在设置中打开
当系统检测到一个NFC标签的时候,他会自动去寻找最合适的activity去处理这个intent.
他所发出的这个Intent将会有三种action:
ACTION_NDEF_DISCOVERED:当系统检测到tag中含有NDEF格式的数据时,且系统中有activity声明可以接受包含NDEF数据的Intent的时候,系统会优先发出这个action的intent。
ACTION_TECH_DISCOVERED:当没有任何一个activity声明自己可以响应ACTION_NDEF_DISCOVERED时,系统会尝试发出TECH的intent.即便你的tag中所包含的数据是NDEF的,但是如果这个数据的MIME type或URI不能和任何一个activity所声明的想吻合,系统也一样会尝试发出tech格式的intent,而不是NDEF.
ACTION_TAG_DISCOVERED:当系统发现前两个intent在系统中无人会接受的时候,就只好发这个默认的TAG类型的
3:NFC标签过滤
在activity的intent过滤xml声明中,你可以同时声明过滤这三种action.但是由之前所说,你应该知道系统在发送intent的时候是有优先级的,所以你最好清楚自己最想处理哪个。
1、过滤ACTION_TAG_DISCOVERED:
<intent-filter><action android:name="android.nfc.action.TAG_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
2、过滤ACTION_NDEF_DISCOVERED:
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED"/><category android:name="android.intent.category.DEFAULT"/><data android:mimeType="text/plain" />
</intent-filter>
data的mimeType类型了,这个定义的越准确,intent指向你这个activity的成功率就越高,否则系统可能不会发出你想要的NDEF intent了。
3、过滤ACTION_TECH_DISCOVERED:
你首先需要在你的<project-path>/res/xml下面创建一个过滤规则文件。名字任取,比如可以叫做nfc_tech_filter.xml。这个里面定义的是nfc实现的各种标准,每一个nfc卡都会符合多个不同的标准,个人理解为这些标准有些相互之间也是兼容的。你可以在检测到nfc标签后使用getTechList()方法来查看你所检测的tag到底支持哪些nfc标准。
一个nfc_tech_filter.xml中可以定义多个<tech-list>结构组。每一组代表我声明我只接受同时满足这些标准的nfc标签。比如A组表示,只有同时满足IsoDep,NfcA,NfcB,NfcF这四个标准的nfc标签的intent才能进入。A与B组之间的关系就是只要满足其中一个就可以了。换句话说,你的nfc标签技术,满足A的声明也可以,满足B的声明也可以。
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><tech-list> --------------------------------A组<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-list><tech-list>-----------------------------------------B组<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>
过滤器过滤
<intent-filter><action android:name="android.nfc.action.TECH_DISCOVERED"/></intent-filter><meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" />
4、
nfc标签前台分发系统
之所以把他也归类在nfc的过滤里面,主要是因为他跟解析nfc标签到不是那么的紧密,他解决的是接受哪些nfc标准的标签问题。所以更接近nfc的过滤。
什么叫nfc的前台发布系统?就是说当我们已经打开我们的应用的时候,那么通过这个前台发布系统的设置,我们可以让我们已经启动的activity拥有更高的优先级来依据我们在代码中定义的标准来过滤和处理intent,而不是让别的声明了intent filter的activity来干扰,甚至连自己声明在androidManifest中的intent filter都不会来干扰。也就是说foreground Dispatch的优先级大于intent filter。
第一种情况:当你的activity没有启动的时候,去扫描tag,那么系统中所有的intent filter都将一起参与过滤。
第二种情况:当你的actiity启动了,去扫描tag时,那么将直接使用你在foreground dispatch中代码写入的过滤标准。如果这个标准没有命中任何intent,那么系统将使用所有activity声明的intent filter xml来过滤。
三、NFC有关的常见的ISO标准有:
标准 | 说明 |
---|---|
ISO 14443 | RFID卡标准(非接触IC卡),该标准又有很多子标准 |
ISO 7816 | 接触式IC卡标准 |
ISO 15693 | 某种射频卡标准吧,这个没查到资料 |
ISO 18092 | NFC标准 |
四、使用
1、加权限
<uses-permission android:name="android.permission.NFC" />
2、加上文提到的过滤,将activity启动模式android:launchMode="singleInstance"或者android:launchMode="singleTop"
3、封装工具类
/*** Created by Administrator on 2019/7/26* <p>* desc:*/
public class nfcUtils {public static NfcAdapter mNfcAdapter;public static IntentFilter[] mIntentFilter = null;public static PendingIntent mPendingIntent = null;public static String[][] mTechList = null;/*** 构造函数,用于初始化nfc*/public nfcUtils(Activity activity) {mNfcAdapter = isNfcEnable(activity);NfcInit(activity);}/*** 判断手机是否具备NFC功能** @param context {@link Context}* @return {@code true}: 具备 {@code false}: 不具备*/public static boolean isNfcExits(Context context) {NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context);return nfcAdapter != null;}/*** 判断手机NFC是否开启* <p>* OPPO A37m 发现必须同时开启NFC以及Android Beam才可以使用* 20180108 发现OPPO单独打开NFC即可读取标签,不清楚是否是系统更新* </p>** @param context {@link Context}* @return {@code true}: 已开启 {@code false}: 未开启*/public static boolean isNfcEnable(Context context) {NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context);
// if (Build.MANUFACTURER.toUpperCase().contains("OPPO")) {
// return nfcAdapter.isEnabled() && isAndroidBeamEnable(context);
// }return nfcAdapter != null && nfcAdapter.isEnabled();}/*** 判断手机NFC的Android Beam是否开启,在API 16之后才有** @param context {@link Context}* @return {@code true}: 已开启 {@code false}: 未开启*/public static boolean isAndroidBeamEnable(Context context) {NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context);return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && nfcAdapter != null && nfcAdapter.isNdefPushEnabled();}/*** 判断手机是否具备Android Beam** @param context {@link Context}* @return {@code true}:具备 {@code false}:不具备*/public static boolean isAndroidBeamExits(Context context) {return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && isNfcExits(context);}/*** 跳转至系统NFC设置界面.** @param context {@link Context}* @return {@code true} 跳转成功 <br> {@code false} 跳转失败*/public static boolean intentToNfcSetting(Context context) {if (isNfcExits(context)) {if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {return toIntent(context, Settings.ACTION_NFC_SETTINGS);}}return false;}/*** 跳转至系统NFC Android Beam设置界面,同页面基本都有NFC开关.** @param context {@link Context}* @return {@code true} 跳转成功 <br> {@code false} 跳转失败*/public static boolean intentToNfcShare(Context context) {if (isAndroidBeamExits(context)) {return toIntent(context, Settings.ACTION_NFCSHARING_SETTINGS);}return false;}/*** 跳转方法.* @param context {@link Context}* @param action 意图* @return 是否跳转成功 {@code true } 成功<br>{@code false}失败*/private static boolean toIntent(Context context, String action) {try {Intent intent = new Intent(action);context.startActivity(intent);} catch (Exception ex) {ex.printStackTrace();return false;}return true;}/*** 初始化nfc设置*/public static void NfcInit(Activity activity) {方法一:Intent intent = new Intent(activity, activity.getClass());intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);mPendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);//做一个IntentFilter过滤你想要的action 这里过滤的是ndefIntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);//如果你对action的定义有更高的要求,比如data的要求,你可以使用如下的代码来定义intentFilter// IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);// try {// filter.addDataType("*/*");// } catch (IntentFilter.MalformedMimeTypeException e) {// e.printStackTrace();// }// mIntentFilter = new IntentFilter[]{filter, filter2};// mTechList = null;try {filter.addDataType("*/*");} catch (IntentFilter.MalformedMimeTypeException e) {e.printStackTrace();}mTechList = new String[][]{{MifareClassic.class.getName()},{NfcA.class.getName()}};//生成intentFiltermIntentFilter = new IntentFilter[]{filter};方法二:mPendingIntent = PendingIntent.getActivity(activity, 0, new Intent(activity, activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);try {filter.addDataType("*/*");} catch (IntentFilter.MalformedMimeTypeException e) {e.printStackTrace();}mIntentFilter = new IntentFilter[]{filter, filter2};mTechList = null;}/*** 读取NFC的数据*/public static String readNFCFromTag(Intent intent) throws UnsupportedEncodingException {Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);if (rawArray != null) {NdefMessage mNdefMsg = (NdefMessage) rawArray[0];NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];if (mNdefRecord != null) {String readResult = new String(mNdefRecord.getPayload(), "UTF-8");return readResult;}}return "";}/*** 往nfc写入数据*/public static void writeNFCToTag(String data, Intent intent) throws IOException, FormatException {Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);Ndef ndef = Ndef.get(tag);ndef.connect();NdefRecord ndefRecord = null;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {ndefRecord = NdefRecord.createTextRecord(null, data);}NdefRecord[] records = {ndefRecord};NdefMessage ndefMessage = new NdefMessage(records);ndef.writeNdefMessage(ndefMessage);}/*** 读取nfcID*/public static String readNFCId(Intent intent) throws UnsupportedEncodingException {Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);String id = ByteArrayToHexString(tag.getId());return id;}/*** 将字节数组转换为字符串*/private static String ByteArrayToHexString(byte[] inarray) {int i, j, in;String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};String out = "";for (j = 0; j < inarray.length; ++j) {in = (int) inarray[j] & 0xff;i = (in >> 4) & 0x0f;out += hex[i];i = in & 0x0f;out += hex[i];}return out;}
}
4、弹框提示
private void showDialog(String title, String content, View.OnClickListener listener) {dismissDialog();AlertDialog.Builder builder = new AlertDialog.Builder(this);LayoutInflater inflater = LayoutInflater.from(this);View view = inflater.inflate(R.layout.dialog_tag_lost, null);TextView tvTitle = (TextView) view.findViewById(R.id.dialog_title);TextView tvContent = (TextView) view.findViewById(R.id.dialog_content);tvTitle.setText(title);tvContent.setText(content);Button btnCancel = (Button) view.findViewById(R.id.btn_cancel);Button btnOk = (Button) view.findViewById(R.id.btn_confirm);btnCancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dismissDialog();}});btnOk.setOnClickListener(listener);builder.setView(view);mDialog = builder.create();mDialog.setCancelable(false);mDialog.setCanceledOnTouchOutside(false);mDialog.show();}private void dismissDialog() {if (mDialog != null && mDialog.isShowing()) {mDialog.dismiss();mDialog = null;}}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/dialog_title"android:layout_width="match_parent"android:layout_height="40dp"android:textSize="18sp"android:gravity="center"android:textColor="#76C36E"/><TextViewandroid:id="@+id/dialog_content"android:layout_width="match_parent"android:layout_height="70dp"android:textSize="16sp"android:gravity="center"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_cancel"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="取消"android:textStyle="bold"android:textColor="#76C36E"android:background="@null"/><Buttonandroid:id="@+id/btn_confirm"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="确定"android:textStyle="bold"android:textColor="#76C36E"android:background="@null"/></LinearLayout>
</LinearLayout>
5、生命周期
@Overrideprotected void onDestroy() {super.onDestroy();dismissDialog();}@Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);processIntent(intent);}public void onResume(){super.onResume();nfcUtils.mNfcAdapter.enableForegroundDispatch(this, nfcUtils.mPendingIntent, nfcUtils.mIntentFilter, nfcUtils.mTechList);}public void onPause(){super.onPause();if (nfcUtils.isNfcEnable(this)){nfcUtils.mNfcAdapter.disableForegroundDispatch(this);}}
6、在onCreate()中 nfcUtils nfc = new NFC(this);
Android--NFC读写相关推荐
- Android NFC 读写示例
自己新浪博客转移 在Android NFC 应用中,Android手机通常是作为通信中的发起者,也就是作为各种NFC卡的读写器.Android对NFC的支持主要在 android.nfc 和andro ...
- android NFC 读写
我也是初学者,在百度看了一天NFC技术文档才做出来的.具体怎么做的我还不是很清楚. 源码共享给大家一起学习. 下载地址:http://download.csdn.net/detail/u0130911 ...
- c语言读写nfc,Android NFC M1卡读写芯片卡读写(CPU卡读写)(RFID读写)
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/sgn5200/article/deta ...
- Android nfc模块读写MifareClassic卡50
http://3y.uu456.com/bp_8mhvy4gizz721et5ih0i_1.html 一般来说,基于MifareClassic的射频卡:1K:16个分区(sector),每个分区 ...
- Android NFC 标签读写Demo与历史漏洞概述
文章目录 前言 NFC基础 1.1 RFID区别 1.2 工作模式 1.3 日常应用 NFC标签 2.1 标签应用 2.2 应用实践 2.3 标签预览 2.4 前台调度 NFC开发 3.1 NDEF数 ...
- android NFC的读写
一.NFC知识 1.NFC是什么? NFC,即Near Field Communication,近距离无线通讯技术,是一种短距离的(通常<=4cm或更短)高频(13.56M Hz)无线通信技术, ...
- Android NFC 使用MifareUltralight读写数据
一.概述: Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本.小容量的卡片.低成本,是指它是目前市场中价格最低的遵守ISO14443 ...
- Android之NFC读写操作
上次记录NFC知识时,还处在研究状态,现在项目的第一阶段开发已经完成.上篇Android之NFC开发,简单介绍了一些知识,也是对未知信息的研究,总要了解一点来龙去脉,省的心发慌.这篇文章总结自己的项目 ...
- Android中NFC读写
参考网址:https://blog.csdn.net/sky2016_w/article/details/79026596 https://www.jianshu.com/p/61f90708bb02 ...
- Android开发NFC读写数据
1.权限<uses-permission android:name="android.permission.NFC"/><uses-feature android ...
最新文章
- SQL Server数据类型
- 一周AI回顾 | 特斯拉AI负责人说神经网络正在改变编程,机器学习大神Bengio新论文专注RNN优化
- Python初识面向对象
- JSON 基础解释.
- .NET Core 3.0之创建基于Consul的Configuration扩展组件
- 【C++入门】C++类和对象
- java传文件到kafka_Java将CSV的数据发送到kafka的示例
- MAC代码下统计代码行数工具
- 文件后缀名怎么修改?文件不显示后缀名怎么办
- 毕业设计/酒店管理系统
- 用php打竖的文字_手写php函数处理 竖排文字
- 2021谷歌年度AI技术总结 | Jeff Dean执笔万字展望人工智能的5大未来趋势!
- 工业触摸一体机的触摸屏原理和维护
- 硬派健身——健身先健脑
- 冲激响应(impulse response)
- 第14.4节 使用IE浏览器获取网站访问的http信息
- 老调重弹:JDBC系列 之 JDBC层次结构和基本构成
- SQL Server 2016 [修改数据库名称]及[添加次文件和日志文件]
- 黑马程序员--Foundation框架之--NSObject类
- go二维map_go map详细使用方法
热门文章
- echarts 自定义 tooltip
- 零基础可入门的Python,为什么有些人自学几天就放弃了?
- 三宝小精灵机器人_三宝小精灵机器人
- 小米6通话音量补丁_手机通话声音小?只需打开这个开关,音量既大又清晰
- webgis期末考试试题_WebGIS考试参考试题
- java 读取pdf表格_在Java中使用tabula提取PDF中的表格数据
- 沟通CTBS金融行业远程接入解决方案
- Matlab fftshift and ifftshift and some confusions
- GL3520 USB3.0集线器USB HUB电路AD设计硬件原理图+PCB+集成库
- 两波形相位差的计算值_变压器损耗计算公式