译者:陈广 日期: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 事件类型,一共有三种类型:
我们使用 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系列芯片开发了 Android 下的使用库,请到ST官网搜索ST25SDK
进行下载。
我写这篇文章时,SDK 为 1.6 版本。整个开发包有很多的文件,包含文档、示例等等。我们需要找到以下三个文件:
tag
对象(由Android定义),并实例化由 ST25 SDK 定义的tag
对象。 此文件可以直接放在【MainActivity.java】文件中。将【st25sdk-1.6.0.jar】文件拷贝到...\ST25\app\libs
文件夹下,在 Android Studio 中,展开【ST25】➤【libs】,可以看到我们刚才拷贝的【st25sdk-1.6.0.jar】文件,其上单击右键,在弹出菜单中选中【Add As Libray...】项安装 SDK。
将【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】按钮。
在【Import Modulee frome Library】窗口的【File name】编辑框中选择刚才的【st25.android.reader.interface.aar】文件,点击【Finish】按钮结束安装。它将直接在您的项目窗口中创建一个【st25.android.reader.interface.aar】项,此模块有自己的 gradle 文件。
由于 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。
效果如下图所示:
将 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 文件查看第一句代码。
所有包安装完成后,效果如下图所示:
总算把这个开发包安装完了,真麻烦!接下来使用这个开发包来发现标签。
打开【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); //将之前的代码替换为这句
}
}
运行程序,现在可以显示卡片类型了,如: