射频识别(RFID)技术

标签发现(Android)

译者:陈广 日期:2020-6-25


在上一篇文章中,我们已经配置好开发环境以及外围代码,本文讲解 ST25DV64K 的读写操作。首先我们要了解 ST25DV64K 存储器的结构。

上一篇文章,我们使用单片机通过 I2C 来控制 ST25DV64 芯片,今天我们使用手机作为读卡器来发现 ST25DV64。某种意义上来说,将 ST25DV64 芯片上的两个引脚连上一根绕了几圈的电线,就可以变成一张 NFC 电子标签,只不过这张电子标签确实有些贵。所以,今天的实验开发板不需要通电。

本来还想看几天 Android 入门视频,但发现之前学的并没有忘光,直接开工也是可以的。这得感谢 STM 有足够丰富的资料和 Demo 给你参考,省了不少事。不幸的是,做实验时,老是无法发现标签,最后把 ST25DV64K 拆下来换了一个上去解决,搞了一天,真是郁闷。想想好象前几天板子摔了一下,可能脱焊了,反正旧芯片是躺垃圾桶里了,有可能还是好的,十来块钱就这么浪费掉了。

标签发现

本文的程序和之前写的一篇《将手机化身为读卡器》的文章基本一样。那篇文章里的程序过于复杂,今天来个极简的。

创建项目

首先安装 Android 4.0,然后新建一个名为 ST25 的项目,使用【Empry Activity】模板。打开【AndroidManifest.xml】文件,添加 NFC 使用许可:

<uses-permission android:name="android.permission.NFC" />

接下来指定可触发通知的 NFC 事件类型,一共有三种类型:

  • NDEF_DISCOVERED:包含 NDEF 消息的 NFC 标签
  • TECH_DISCOVERED:已经在 Android 中注册的标签类型
  • TAG_DISCOVERED:只要是标签就可以

我们使用 TAG_DISCOVERED,这样就可以对所有标签有所反应。添加如下代码:

<intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>

最终,AndroidManifest.xml 代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.st25">

    <uses-permission android:name="android.permission.NFC" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

编写代码

接下来打开【MainActivity.java】更改代码如下:

package com.example.st25;

import androidx.appcompat.app.AppCompatActivity;

import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private NfcAdapter nfcAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    }

    @Override //页面失去焦点
    protected void onPause() {
        super.onPause();
        if (nfcAdapter != null) {
            nfcAdapter.disableForegroundDispatch(this);
        }
    }

    @Override //页面获取焦点
    protected void onResume() {
        super.onResume();

        if (nfcAdapter == null) {
            Toast.makeText(this, "对不起,您的设备不支持NFC功能!", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        if (!nfcAdapter.isEnabled()) {
            Toast.makeText(this, "请在系统设置中开启NFC功能!", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }

        PendingIntent pi = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        nfcAdapter.enableForegroundDispatch(this, pi, null, null);

        Intent intent = getIntent();
        String action = intent.getAction();
        Tag nfcTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (nfcTag != null) {
            Toast.makeText(this, "NFC Tag detected!", Toast.LENGTH_LONG).show();
        }
    }

    @Override //当前app正在前端界面运行,这个时候有intent发送过来,那么系统就会调用onNewIntent回调方法
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        setIntent(intent);
    }
}

运行程序,打开 App,注意这个 App 可不会自动弹出来。将各种类标签都贴到手机摄像头处试试。结果都是响一声并弹出消息框:

ST25 : NFC Tag detected!

将其贴到断电状态下的开发板天线处,查看是否有反应,没有反应就去检查电路吧。有反应就庆祝准备可以大展拳脚了。

安装 ST25 SDK

意法半导体专门为 ST25系列芯片开发了 Android 下的使用库,请到ST官网搜索ST25SDK进行下载。

我写这篇文章时,SDK 为 1.6 版本。整个开发包有很多的文件,包含文档、示例等等。我们需要找到以下三个文件:

  • 【st25sdk-1.6.0.jar】:ST25SDK 库。
  • 【st25_android_reader_interface-1.0.7-release.aar】:这是一个包含 Android 阅读器接口的 Android 文档。 这个阅读器接口被 SDK 用来与 Android 手机的 NFC API 通信。
  • 【TagDiscovery.java】:这是一个助手类,帮助发现 NFC 标签类型。 它使用tag对象(由Android定义),并实例化由 ST25 SDK 定义的tag对象。 此文件可以直接放在【MainActivity.java】文件中。

安装 ST25 SDK JAR

将【st25sdk-1.6.0.jar】文件拷贝到...\ST25\app\libs文件夹下,在 Android Studio 中,展开【ST25】➤【libs】,可以看到我们刚才拷贝的【st25sdk-1.6.0.jar】文件,其上单击右键,在弹出菜单中选中【Add As Libray...】项安装 SDK。

安装 Android 阅读器接口 AAR

将【st25_android_reader_interface-1.0.7-release.aar】文件拷贝至任一地方,改名为【st25.android.reader.interface.aar】。回到 Android Studio,单击菜单【File】➤【New Module】,打开【Select a Module Type】窗口,选中其中的【Import.JAR/.AAR Package】项,单击【Next】按钮。

图 1:添加 ARR

在【Import Modulee frome Library】窗口的【File name】编辑框中选择刚才的【st25.android.reader.interface.aar】文件,点击【Finish】按钮结束安装。它将直接在您的项目窗口中创建一个【st25.android.reader.interface.aar】项,此模块有自己的 gradle 文件。

引入 org.apache.commons:commons-lang3:3.5

由于 ST25 SDK 使用了org.apache.commons:commons-lang3:3.5库,所以需要引用。打开【apps/build.gradle】文件,添加如下代码:

implementation project(':st25.android.reader.interface')
implementation 'org.apache.commons:commons-lang3:3.5'

第一句是引入之前安装的阅读器接口 AAR。

效果如下图所示:

图 2:引用 org.apache.commons:commons-lang3:3.5

引入 TagDiscovery

将 TagDiscovery.java 拷贝至\ST25\app\src\main\java\com\example\st25文件夹下。在 Android Studio 中的 MainActivity 下方可以看到 TagDiscovery 项,打开它,将第一句代码的包名称更改为和 MainActivity 中的一样:

原代码:

package st.com.st25androiddemoapp;

更改为:

package com.example.st25;

注意,包名称可能不一样,自行打开 MainActivity.java 文件查看第一句代码。

所有包安装完成后,效果如下图所示:

图 3:安装后的效果

使用 ST25 SDK 发现标签

总算把这个开发包安装完了,真麻烦!接下来使用这个开发包来发现标签。

打开【MainActivity.java】文件,将MainActivity类声明为实现TagDiscovery的一个接口:

public class MainActivity extends AppCompatActivity implements TagDiscovery.onTagDiscoveryCompletedListener

可以按开发工具上的灯泡实现这个接口,也可以直接在MainActivity类中添加如下代码:

 @Override
public void onTagDiscoveryCompleted(NFCTag nfcTag, TagHelper.ProductID productId, STException e) {
    if (nfcTag != null) {
        String tagName = nfcTag.getName();
        Toast.makeText(this, "找到标签: " + tagName, Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(this, "标签发现失败", Toast.LENGTH_LONG).show();
    }
}

为不让 UI 阻塞,TagDiscovery中使用异步的方式来发现标签。当标签发现完成后,会自动执行onTagDiscoveryCompleted回调函数。

我们需要在OnResume方法中创建这个TagDiscovery,更改OnResume方法如下(只更改最后一句代码):

@Override //页面获取焦点
    protected void onResume() {
        super.onResume();

        if (nfcAdapter == null) {
            Toast.makeText(this, "对不起,您的设备不支持NFC功能!", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        if (!nfcAdapter.isEnabled()) {
            Toast.makeText(this, "请在系统设置中开启NFC功能!", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }

        PendingIntent pi = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        //将 NFC 事件发送至当前应用程序
        nfcAdapter.enableForegroundDispatch(this, pi, null, null);

        Intent intent = getIntent();
        String action = intent.getAction();
        Tag nfcTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (nfcTag != null) {
            new TagDiscovery(this).execute(nfcTag); //将之前的代码替换为这句
        }
    }

运行程序,现在可以显示卡片类型了,如:

  • 普通 15693 标签显示为:ISO15693/NFC Type 5 tag
  • 网上购买的 NFC 标签显示为:NFC Type2 tag
  • ST25DV64K 芯片显示为:ST25DV64K-J
  • 14443 标签,无法识别
;

© 2018 - IOT小分队文章发布系统 v0.3