一、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读写相关推荐

  1. Android NFC 读写示例

    自己新浪博客转移 在Android NFC 应用中,Android手机通常是作为通信中的发起者,也就是作为各种NFC卡的读写器.Android对NFC的支持主要在 android.nfc 和andro ...

  2. android NFC 读写

    我也是初学者,在百度看了一天NFC技术文档才做出来的.具体怎么做的我还不是很清楚. 源码共享给大家一起学习. 下载地址:http://download.csdn.net/detail/u0130911 ...

  3. c语言读写nfc,Android NFC M1卡读写芯片卡读写(CPU卡读写)(RFID读写)

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/sgn5200/article/deta ...

  4. Android nfc模块读写MifareClassic卡50

     http://3y.uu456.com/bp_8mhvy4gizz721et5ih0i_1.html 一般来说,基于MifareClassic的射频卡:1K:16个分区(sector),每个分区 ...

  5. Android NFC 标签读写Demo与历史漏洞概述

    文章目录 前言 NFC基础 1.1 RFID区别 1.2 工作模式 1.3 日常应用 NFC标签 2.1 标签应用 2.2 应用实践 2.3 标签预览 2.4 前台调度 NFC开发 3.1 NDEF数 ...

  6. android NFC的读写

    一.NFC知识 1.NFC是什么? NFC,即Near Field Communication,近距离无线通讯技术,是一种短距离的(通常<=4cm或更短)高频(13.56M Hz)无线通信技术, ...

  7. Android NFC 使用MifareUltralight读写数据

    一.概述: Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本.小容量的卡片.低成本,是指它是目前市场中价格最低的遵守ISO14443 ...

  8. Android之NFC读写操作

    上次记录NFC知识时,还处在研究状态,现在项目的第一阶段开发已经完成.上篇Android之NFC开发,简单介绍了一些知识,也是对未知信息的研究,总要了解一点来龙去脉,省的心发慌.这篇文章总结自己的项目 ...

  9. Android中NFC读写

    参考网址:https://blog.csdn.net/sky2016_w/article/details/79026596 https://www.jianshu.com/p/61f90708bb02 ...

  10. Android开发NFC读写数据

    1.权限<uses-permission android:name="android.permission.NFC"/><uses-feature android ...

最新文章

  1. SQL Server数据类型
  2. 一周AI回顾 | 特斯拉AI负责人说神经网络正在改变编程,机器学习大神Bengio新论文专注RNN优化
  3. Python初识面向对象
  4. JSON 基础解释.
  5. .NET Core 3.0之创建基于Consul的Configuration扩展组件
  6. 【C++入门】C++类和对象
  7. java传文件到kafka_Java将CSV的数据发送到kafka的示例
  8. MAC代码下统计代码行数工具
  9. 文件后缀名怎么修改?文件不显示后缀名怎么办
  10. 毕业设计/酒店管理系统
  11. 用php打竖的文字_手写php函数处理 竖排文字
  12. 2021谷歌年度AI技术总结 | Jeff Dean执笔万字展望人工智能的5大未来趋势!
  13. 工业触摸一体机的触摸屏原理和维护
  14. 硬派健身——健身先健脑
  15. 冲激响应(impulse response)
  16. 第14.4节 使用IE浏览器获取网站访问的http信息
  17. 老调重弹:JDBC系列 之 JDBC层次结构和基本构成
  18. SQL Server 2016 [修改数据库名称]及[添加次文件和日志文件]
  19. 黑马程序员--Foundation框架之--NSObject类
  20. go二维map_go map详细使用方法

热门文章

  1. echarts 自定义 tooltip
  2. 零基础可入门的Python,为什么有些人自学几天就放弃了?
  3. 三宝小精灵机器人_三宝小精灵机器人
  4. 小米6通话音量补丁_手机通话声音小?只需打开这个开关,音量既大又清晰
  5. webgis期末考试试题_WebGIS考试参考试题
  6. java 读取pdf表格_在Java中使用tabula提取PDF中的表格数据
  7. 沟通CTBS金融行业远程接入解决方案
  8. Matlab fftshift and ifftshift and some confusions
  9. GL3520 USB3.0集线器USB HUB电路AD设计硬件原理图+PCB+集成库
  10. 两波形相位差的计算值_变压器损耗计算公式