引言
鸿蒙平台提供 AirTouch服务,支持元服务、原生鸿蒙应用、快应用等实现 NFC标签触达功能。
典型场景,例如:
-
餐饮:用户手机碰Tag标签 -> Portal页 -> 快速点餐。
-
出行:用户手机碰Tag标签 -> Portal页 -> 解锁共享单车。
本文,小编将业务中实现的能力NFC碰一碰唤起我方应用
中的‘技术要点’及‘实现步骤’进行整理归纳。
一、创建 AirTouch 服务
- 登录AppGallery Connect网站,点击“我的项目”。
- 选择需要创建 AirTouch 服务的项目,进入项目设置页面
- 在“项目设置”页签,左侧导航选择“构建 > AirTouch”。
- 点击“申请AirTouch服务”。
- 设置AirTouch服务基本信息。
- 点击“保存”,创建完成后,返回AirTouch服务创建首页,可对所创建的服务进行详情查看、修改与直达服务的创建。
- 在AirTouch服务首页列表项中,点击“申请直达服务”按钮,进入直达服务创建首页。
- 点击“新建商家直达服务”,请填写服务信息。点击“下一步”。
- HarmonyOS NEXT版本请选择HMACSHA256签名算法。
- 选择
关联MimeType的PayLoad作为查询参数
,下文我会举例如何在NFC唤起应用时获取携带数据
- 点击“下一步”,设置AirTouch卡片样式。
右侧为NFC碰一碰后提示用户将拉起的应用弹窗效果图
需要注意的是跳转地址如何填写?例如:在元服务跳转地址栏目填写跳转链接:
以我的demo应用为例,填写的跳转链接内容为:
{
"bundleName": "com.atomicservice.5765880207854372291",
"abilityName": "EntryAbility",
"moduleName": "entry"
}
- 点击“下一步”,完成商家直达服务的配置,此时该服务状态为待审核,审核通过后,可下载对应的直达标签内容(写入标签时需要用到)。
二、NFC 标签需要写入哪些数据
标签需要写入一条URI记录,一条AirTouch格式记录,两条AAR(Android Application Record)记录,和一条MIME格式记录,需要按顺序写入。
标签格式(包含五部分):
- Uri Record:AirTouch服务申请时配置的默认跳转链接。
- AirTouch格式记录(参见AirTouch格式说明)。
- AAR Record:com.huawei.hwid。
- AAR Record:com.huawei.hms。
- MIMIE Record:AirTouch服务申请时配置的跳转链接参数。
标签写入参考以下代码样例:
String airTouchContent = "下载的标签内容,审核通过后即可下载";
// 默认的跳转链接,也就是新建商家服务直达里填写的内容
String airTouchDefaultLink = "https:/default.airtouch.huawei.com/blankcodelabdev";
// 若选择"标签中关联MimeType的PayLoad作为查询参数",需要以下两个变量
// 跳转链接参数,例如创建时填写的 paramId
String airTouchJumpParamKey = "paramId";
String airTouchJumpParamValue = "跳转链接参数值";
byte[] TYPE_HW = {0x68, 0x77};
NdefMessage ndefMessage = new NdefMessage(
new NdefRecord[] {
NdefRecord.createUri(airTouchDefaultLink),
new NdefRecord(NdefRecord.TNF_MIME_MEDIA, TYPE_HW, new byte[0], Base64.decode(airTouchContent, Base64.NO_WRAP)),
NdefRecord.createApplicationRecord("com.huawei.hwid"),
NdefRecord.createApplicationRecord("com.huawei.hms"),
// 若选择"标签中关联MimeType的PayLoad作为查询参数",需要加入以下NdefRecord
new NdefRecord(NdefRecord.TNF_MIME_MEDIA, airTouchJumpParamKey, new byte[0], airTouchJumpParamValue),
}
);
.......
Tag tag = intent.getParcelbleExtra(NfcAdapter.EXTRA_TAG);
Ndef ndef = Ndef.get(tag);
......
ndef.writeNdefMessage(ndefMessage);
使用Flutter开发的NFC写入代码示例
import 'dart:typed_data';
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
import 'package:ndef/ndef.dart' as ndef;
import 'dart:convert';
import 'dart:developer' as dev;
abstract class NfcWriteTool {
static const url = '默认的跳转链接';
static const tagContent = '下载的标签内容';
static final content = ndef.NDEFRecord(
tnf: ndef.TypeNameFormat.media,
type: Uint8List.fromList(utf8.encode('hw')),
payload: base64Url.decode(tagContent),
);
// 搜索是否有可写入设备
static Future<bool> findNfcTag({
int timeout = 20,
bool checkWritable = true,
}) async {
try {
final nfcTag = await FlutterNfcKit.poll(
timeout: Duration(seconds: timeout),
);
if (checkWritable) {
return nfcTag.ndefWritable ?? false;
} else {
return true;
}
} catch (e) {
return false;
}
}
// 将数据写入NFC设备
static Future<bool> writeNDEFRecords({required String paramId}) async {
final param = ndef.NDEFRecord(
tnf: ndef.TypeNameFormat.media,
type: Uint8List.fromList(utf8.encode('paramId')),
payload: Uint8List.fromList(utf8.encode(paramId)),
);
try {
await FlutterNfcKit.writeNDEFRecords([
ndef.UriRecord.fromString(url),
content,
ndef.AARRecord(packageName: 'com.huawei.hwid'),
ndef.AARRecord(packageName: 'com.huawei.hms'),
param
]);
await FlutterNfcKit.finish();
return true;
} catch (e) {
return false;
}
}
}
三、如何获取 NFC 携带的参数
在入口文件EntryAbility
中做以下处理,接收入参
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
this.receiveWantParams(want, false)
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)
}
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
this.receiveWantParams(want, true)
}
}
receiveWantParams(want: Want, isRelaunch: boolean): void {
const wantAction = want.action ?? ''
if (want.parameters) {
if (wantAction === LaunchChannel.NFC) {
const paramId = (want.parameters['tagParam'] as string) ?? ''
// 这个 paramId 就是NFC交互时携带的数据,可自行处理,例如存入`appStorage 或 static`,然后在主页面根据数据响应逻辑(跳转,弹窗)等
}
}
}
运行效果图
由于示例项目申请的服务还没过审,直接展示项目效果如下: