设备可以模拟卡片,替代卡片完成对应操作,如模拟门禁卡、公交卡等。应用或者其他模块可以通过接口完成以下功能:
NFC卡模拟功能的主要接口说明如下,在使用对应的接口前,需要申请ohos.permission.NFC_CARD_EMULATION权限。
类名 | 接口名 | 功能描述 |
---|---|---|
CardEmulation | getInstance(NfcController controller) | 创建一个卡模拟类的实例。 |
isSupported(int feature) | 查询是否支持卡模拟功能。 | |
setListenMode(int mode) | 设置卡模拟模式。 | |
isListenModeEnabled() | 查询卡模拟功能是否打开。 | |
getNfcInfo(String key) | 获取NFC的信息。 | |
getSelectionType(String category) | 根据NFC服务的类型获取刷卡时选择服务的方式。 | |
registerForegroundPreferred(Ability appAbility, ElementName appName) | 动态设置前台优先应用。 | |
unregisterForegroundPreferred(Ability appAbility) | 取消设置前台优先应用。 | |
isDefaultForAid(ElementName appName, String aid) | 判断应用是否是指定AID的默认处理应用。 | |
registerAids(ElementName appName, String type, List<String> aids) | 给应用注册指定类型的AID。 | |
removeAids(ElementName appName, String type) | 删除应用的指定类型的AID。 | |
getAids(ElementName appName, String type) | 获取应用中指定类型的AID列表。 | |
HostService | sendResponse(byte[] response) | 发送响应的数据到对端设备。 |
handleRemoteCommand(byte[] cmd, IntentParams params) | 处理对端设备发送的命令。 | |
disabledCallback(int errCode) | 连接异常的回调。 |
// 获取NFC控制对象
NfcController nfcController = NfcController.getInstance(context);
// 获取卡模拟控制对象
CardEmulation cardEmulation = CardEmulation.getInstance(nfcController);
// 查询是否支持HCE、UICC、ESE卡模拟,返回值表示是否支持对应安全单元的卡模拟
boolean isSupportedHce = cardEmulation.isSupported(CardEmulation.FEATURE_HCE);
boolean isSupportedUicc = cardEmulation.isSupported(CardEmulation.FEATURE_UICC);
boolean isSupportedEse = cardEmulation.isSupported(CardEmulation.FEATURE_ESE);
// 获取NFC控制对象
NfcController nfcController = NfcController.getInstance(context);
// 获取卡模拟控制对象
CardEmulation cardEmulation = CardEmulation.getInstance(nfcController);
// 打开卡模拟
cardEmulation.setListenMode(CardEmulation.ENABLE_MODE_ALL);
// 调用查询卡模拟开关状态的接口,返回值为卡模拟是否是打开的状态
boolean isEnabled = cardEmulation.isListenModeEnabled();
// 关闭卡模拟
cardEmulation.setListenMode(CardEmulation.DISABLE_MODE_A_B);
// 调用查询卡模拟开关状态的接口,返回值为卡模拟是否是打开的状态
isEnabled = cardEmulation.isListenModeEnabled();
// 获取NFC控制对象
NfcController nfcController = NfcController.getInstance(context);
// 获取卡模拟控制对象
CardEmulation cardEmulation = CardEmulation.getInstance(nfcController);
// 查询本机当前使能的安全单元类型
String seType = cardEmulation.getNfcInfo(CardEmulation.KEY_ENABLED_SE_TYPE); // ENABLED_SE_TYPE_ESE
// 查询Hisee上电状态
String hiseeState = cardEmulation.getNfcInfo(CardEmulation.KEY_HISEE_READY);
// 查询是否支持RSSI的查询
String rssiAbility = cardEmulation.getNfcInfo(CardEmulation.KEY_RSSI_SUPPORTED);
// 获取NFC控制对象
NfcController nfcController = NfcController.getInstance(context);
// 获取卡模拟控制对象
CardEmulation cardEmulation = CardEmulation.getInstance(nfcController);
// 获取选择服务的方式
int result = cardEmulation.getSelectionType(CardEmulation.CATEGORY_PAYMENT); // SELECTION_TYPE_PREFER_DEFAULT
result = cardEmulation.getSelectionType(CardEmulation.CATEGORY_OTHER); // SELECTION_TYPE_ASK_IF_CONFLICT
// 获取NFC控制对象
NfcController nfcController = NfcController.getInstance(context);
// 获取卡模拟控制对象
CardEmulation cardEmulation = CardEmulation.getInstance(nfcController);
// 动态设置前台优先应用
Ability ability = new Ability();
cardEmulation.registerForegroundPreferred(ability, new ElementName());
// 注销前台优先应用
cardEmulation.unregisterForegroundPreferred(ability);
示例代码如下:
"metaData": {
"customizeData": [
{
"name": "paymentAid",
"value": "325041592E5359532E4444463031"
},
{
"name": "otherAid",
"value": "0123456789|535558494E2E4D46|1234567890"
}
]
}
// 获取NFC控制对象
NfcController nfcController = NfcController.getInstance(context);
// 获取卡模拟控制对象
CardEmulation cardEmulation = CardEmulation.getInstance(nfcController);
// 给应用注册指定类型的AID
List<String> aids = new ArrayList<String>();
aids.add(0, "A0028321901280");
aids.add(1, "A0028321901281");
Element element = new ElementName();
try {
cardEmulation.registerAids(element, CardEmulation.CATEGORY_PAYMENT, aids);
} catch (IllegalArgumentException e) {
HiLog.error(TAG, "IllegalArgumentException when registerAids");
}
// 删除应用的指定类型的AID
cardEmulation.removeAids(element, CardEmulation.CATEGORY_PAYMENT);
cardEmulation.removeAids(element, CardEmulation.CATEGORY_OTHER);
调用isDefaultForAid(ElementName appName, String aid)接口,可判断应用是否是指定AID的默认处理应用:
// 判断应用是否是指定AID的默认处理应用
String aid = "A0028321901280";
cardEmulation.isDefaultForAid(element, aid);
调用getAids(ElementName appName, String type)接口去获取应用中指定类型的AID列表:
// 获取应用中指定类型的AID列表
try {
cardEmulation.getAids(element, CardEmulation.CATEGORY_PAYMENT);
} catch (IllegalArgumentException e) {
HiLog.error(TAG, "IllegalArgumentException when getAids");
}
// HCE应用的服务继承HostService,实现HCE卡模拟功能
public class AppService extends HostService {
@Override
public byte[] handleRemoteCommand(byte[] cmd, IntentParams params) {
HiLog.info(TAG, "handleRemoteCommand" );
if (Arrays.equals(SELECT_PPSE, cmd)) {
HiLog.info(TAG, "Matched PPSE select" );
return PPSE_RESP;
} else if (Arrays.equals(SELECT_MASTERCARD, cmd)) {
HiLog.info(TAG, "Matched Mastercard select" );
return SELECT_MASTERCARD_RESP;
} else if (Arrays.equals(GET_PROC_OPT, cmd)) {
HiLog.info(TAG, "Matched get processing options" );
return GET_PROC_OPT_RESP;
} else if (Arrays.equals(READ_REC, cmd)) {
HiLog.info(TAG, "Matched read rec" );
return READ_REC_RESP;
} else if (cmd.length >= 5 && cmd[0] == (byte)0x80 && cmd[1] == (byte)0x2a
&& cmd[2] == (byte)0x8e && cmd[3] == (byte)0x80 && cmd[4] == 0x0f) {
return COMPUTE_CHECKSUM_RESP;
} else {
return new byte[] {(byte)0x90, 0x00};
}
}
@Override
public void disabledCallback(int errCode) {
// 应用自定义接口实现。
}
// 应用自定义功能
}
NFC消息通知是HarmonyOS内部或者与应用之间跨进程通讯的机制,注册者在注册消息通知后,一旦符合条件的消息被发出,注册者即可接收到该消息。
描述 | 通知名 | 附加参数 |
---|---|---|
NFC状态 | usual.event.nfc.action.ADAPTER_STATE_CHANGED | extra_nfc_state |
进场消息 | usual.event.nfc.action.RF_FIELD_ON_DETECTED | extra_nfc_transaction |
离场消息 | usual.event.nfc.action.RF_FIELD_OFF_DETECTED | - |
// 构建消息接收者/注册者
class NfcStateEventSubscriber extends CommonEventSubscriber {
NfcStateEventSubscriber (CommonEventSubscribeInfo info) {
super(info);
}
@Override
public void onReceiveEvent(CommonEventData commonEventData) {
if (commonEventData == null || commonEventData.getIntent() == null) {
return;
}
if (NfcController.STATE_CHANGED.equals(commonEventData.getIntent().getAction())) {
IntentParams params = commonEventData.getIntent().getParams();
int currState = commonEventData.getIntent().getIntParam(NfcController.EXTRA_NFC_STATE, NfcController.STATE_OFF);
}
}
}
// 注册消息
MatchingSkills matchingSkills = new MatchingSkills();
// 增加获取NFC状态改变消息
matchingSkills.addEvent(NfcController.STATE_CHANGED);
matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_NFC_ACTION_ADAPTER_STATE_CHANGED);
CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
NfcStateEventSubscriber subscriber = new NfcStateEventSubscriber(subscribeInfo);
try {
CommonEventManager.subscribeCommonEvent(subscriber);
} catch (RemoteException e) {
HiLog.error(TAG, "doSubscribe occur exception: %{public}s" ,e.toString());
}
// 构建消息接收者/注册者
class NfcFieldOnAndOffEventSubscriber extends CommonEventSubscriber {
NfcFieldOnAndOffEventSubscriber (CommonEventSubscribeInfo info) {
super(info);
}
@Override
public void onReceiveEvent(CommonEventData commonEventData) {
if (commonEventData == null || commonEventData.getIntent() == null) {
return;
}
if (NfcController.FIELD_ON_DETECTED.equals(commonEventData.getIntent().getAction())) {
IntentParams params = commonEventData.getIntent().getParams();
if (params == null) {
HiLog.info(TAG, "Pure FIELD_ON_DETECTED");
} else {
HiLog.info(TAG, "Transaction FIELD_ON_DETECTED");
Intent transactionIntent = (Intent) params.getParam("transactionIntent");
}
} else if (NfcController.FIELD_OFF_DETECTED.equals(commonEventData.getIntent().getAction())) {
HiLog.info(TAG, "FIELD_OFF_DETECTED");
}
HiLog.info(TAG, "NfcFieldOnAndOffEventSubscriber onReceiveEvent: %{public}s", commonEventData.getIntent().getAction());
}
}
// 注册消息
MatchingSkills matchingSkills = new MatchingSkills();
// 增加获取NFC状态改变消息
matchingSkills.addEvent(NfcController.FIELD_ON_DETECTED);
matchingSkills.addEvent(NfcController.FIELD_OFF_DETECTED);
CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
HiLog.info(TAG, "subscribeInfo permission: %{public}s", subscribeInfo.getPermission());
NfcFieldOnAndOffEventSubscriber subscriber = new NfcFieldOnAndOffEventSubscriber(subscribeInfo);
try {
CommonEventManager.subscribeCommonEvent(subscriber);
} catch (RemoteException e) {
HiLog.error(TAG, "doSubscribe occur exception: %{public}s", e.toString());
}