对NFC(BUG)的初步认识

对NFC(BUG)的初步认识

多年未曾更新的帖子,今天再记录一下,上家公司用到的新技术 NFC点对点通信 。一个让人“疯狂”的技术。

概念

根据官方解释,其是近距离无线通信 (NFC) 是一组近距离无线技术,通常只有在距离不超过 4 厘米时才能启动连接。借助 NFC,可以在 NFC 标签与 Android 设备之间或者两台 Android 设备之间共享小型负载。
支持 NFC 的 Android 设备同时支持以下三种主要操作模式:

  1. 读取器/写入器模式 ,支持 NFC 设备读取和/或写入被动 NFC 标签和贴纸;
  2. 点对点模式 ,支持 NFC 设备与其他 NFC 对等设备交换数据;Android Beam 使用的就是此操作模式;
  3. 卡模拟模式 ,支持 NFC 设备本身充当 NFC 卡。然后,可以通过外部 NFC 读取器(例如 NFC 销售终端)访问模拟 NFC 卡。

本文章主要讲的是 点对点模式,根据实际项目的使用,对此做过简单记录。

首先还是常规操作,获取权限:

    <uses-permission android:name="android.permission.NFC" />  
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

接下来就是对NFC的具体操作,需要跟你的兄弟部门去沟通,这个NFC支持哪些标签,以及项目中需要使用什么标签来进行通信。具体的标签内容,可以查看 官方文档,我项目中使用的是IsoDep。

初始化NFC

NFC的初始化就像蓝牙一样,获取其的NfcAdapter即可:

mNfcAdapter = NfcAdapter.getDefaultAdapter(context);

接着,我们得判断你的设备是否支持,且是否打开了NFC功能:

   public NFCState ifNFCUse() {
        if (this.mNfcAdapter == null) {
            return NFCState.STATE_UNSUPPORTED;
        } else {
            return !this.mNfcAdapter.isEnabled() ? NFCState.STATE_CLOSE : NFCState.STATE_OPEN;
        }
    }

获取NFC标签

获取通信标签有两种方式:
1.通过在Activity页面实现onNewIntent()方法;

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        ...
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            Parcelable[] rawMessages =
                intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        ...
        }
    }

2.通过BroadcastReceiver实现;

	public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (tag != null && tag.getTechList() != null) {
            Log.d("find_nfc_iso", "nfc iso : " + Arrays.toString(tag.getTechList()));
            //这里我做了一次重置,因为NFC有个特性,每次进行连接,必须断开上一次的连接操作,才能继续连接
            DeviceService.resetNfc();
            //这里做个例子通过遍历标签集合,来判断获取是否有你需要的标签
            for (String tech :
                    tag.getTechList()) {
                if (tech.equals("android.nfc.tech.IsoDep")) {
                    NfcStateReceiver.tag = tag;
                    NfcStateReceiver.isoDep = IsoDep.get(tag);
                    break;
                }
            }
        }
        if (null == action || action.isEmpty()) {
            return;
        }
        //定义了一个接口,根据获取到的action类型,来及时的更新连接状态
        if (action.equals(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED)) {
            int state = intent.getIntExtra("android.nfc.extra.ADAPTER_STATE", DEFAULT_VALUE_NFC);
            switch (state) {
                case 1:
                    this.onNfcStateListener.onStateOff();
                    DeviceService.resetNfc();
                    break;
                case 2:
                    this.onNfcStateListener.onStateTurningOn();
                    break;
                case 3:
                    this.onNfcStateListener.onStateOn();
                    break;
                case 4:
                    this.onNfcStateListener.onStateTurningOff();
            }
        }
    }

连接

通过上面我们已经获取到了nfc,以及通信标签,接下来就是连接的操作,如下所示:

    public Print
    Nfc(IsoDep iso, Tag nfcTag) {
        this.iso = iso;
        try {
            if (this.iso == null) {
                Log.d(TAG, "not find iso,nfc connected failed");
                return;
            }
            //因NFC特殊性,连接前判断是否已连接
            if (this.iso.isConnected()) {
                //释放连接状态
                this.iso.close();
            }
            //连接
            this.iso.connect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.nfcTag = nfcTag;
        //这里是个心跳,为了保证跟另外一台设备通信正常,我设置的是500毫秒发送一次
        createDownTimer();
    }

发送数据

NFC的数据发送跟蓝牙以及WIFI的发送方式完全不同,BLE蓝牙通过gatt发送,BT蓝牙或者WIFI可以通过socket发送,而NFC是通过标签进行发送的,拿我们获取的IsoDep,调用 transceive(byte[] data) 方法来进行发送,如下:

iso.transceive(ICommand.HEART_BEAT);

注意 :如果你的数据长度在24个字节以内,你是可以直接发送的。如果超出24个byte(这个长度数我不确定是不是每个厂家都不一样),那就得分段发送。

接收数据

发送完成了,接下来就是我们的接收数据的环节,如下:

receipt = iso.transceive(ICommand.HEART_BEAT);

是的,你没看错,NFC的接收也是通过transceive(byte[] data) 方法来进行的,他有一个byte[]的回参。能拿到这个回参,恭喜你通信成功。

最紧要的—BUG

1.在你做iso.connect() 的操作时,一定要确保当前是未连接的状态,否则你会报错,提示你 “无法连接,让你先释放上一个”
2.在你发送数据的时候,即调用 iso.transceive() 的时候,如果你是第一次使用NFC功能,你会发现一个问题,他会给你一个异常 “tag was lost” 。不管你检如何查自己的代码,你都发现没有问题,这就是我说的NFC通信特殊的原因。具体原因你可以理解为,假设另外一放未单片机,单片机需要一直给NFC的中控发送信息,如果单片机发送慢了,那就会导致这个异常产生。是的,不光你的APP跟单片机有个心跳机制,单片机跟NFC模块之间也有一个类似心跳机制的东西存在。

OVER

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值