HarmonyOS学习路之开发篇—网络与连接(NFC开发 二)

简介: 设备可以模拟卡片,替代卡片完成对应操作,如模拟门禁卡、公交卡等。应用或者其他模块可以通过接口完成以下功能

卡模拟功能

场景介绍

设备可以模拟卡片,替代卡片完成对应操作,如模拟门禁卡、公交卡等。应用或者其他模块可以通过接口完成以下功能:


查询是否支持指定安全单元的卡模拟功能,安全单元包括HCE(Host Card Emulation)、ESE(Embedded Secure Element)和SIM(Subscriber Identity Module)卡。

打开或关闭指定技术类型的卡模拟,并查询卡模拟状态。

获取NFC信息,包括当前激活的安全单元、Hisee上电状态、是否支持RSSI(Received Signal Strength Indication)查询等。

根据NFC服务的类型获取刷卡时选择服务的方式,包括支付(Payment)类型和非支付(Other)类型。

动态设置和注销前台优先应用。

NFC应用的AID(Application Identifier,应用标识)相关操作,包括注册和删除应用的AID、查询应用是否是指定AID的默认应用、获取应用的AID等。

定义Host和OffHost服务的抽象类,应用可以通过继承抽象类来实现NFC卡模拟功能。

接口说明

NFC卡模拟功能的主要接口说明如下,在使用对应的接口前,需要申请ohos.permission.NFC_CARD_EMULATION权限。


表1 NFC卡模拟功能的主要接口


image.png

image.png

image.png

查询是否支持卡模拟功能

1.调用NfcController类的getInstance(Context context)接口,获取NfcController实例。

2.调用CardEmulation类的getInstance(NfcController controller)接口,获取CardEmulation实例,去管理本机卡模拟模块操作。

3.调用isSupported(int feature)接口去查询是否支持HCE、UICC、ESE卡模拟。

// 获取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);

开关卡模拟及查询卡模拟状态

1.调用NfcController类的getInstance(Context context)接口,获取NfcController实例。

2.调用CardEmulation类的getInstance(NfcController controller)接口,获取CardEmulation实例,去管理本机卡模拟模块操作。

3.调用setListenMode(int mode)接口去打开或者关闭卡模拟。

4.调用isListenModeEnabled()接口去查询卡模拟是否打开。

// 获取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信息

1.调用NfcController类的getInstance(Context context)接口,获取NfcController实例。

2.调用CardEmulation类的getInstance(NfcController controller)接口,获取CardEmulation实例,去管理本机卡模拟模块操作。

3.调用getNfcInfo(String key)接口去获取NFC信息。

// 获取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服务的类型获取刷卡时选择服务的方式

1.调用NfcController类的getInstance(Context context)接口,获取NfcController实例。

2.调用CardEmulation类的getInstance(NfcController controller)接口,获取CardEmulation实例,去管理本机卡模拟模块操作。

3.调用getSelectionType(Sring category)接口去获取选择服务的方式。

// 获取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

动态设置和注销前台优先应用

1.调用NfcController类的getInstance(Context context)接口,获取NfcController实例。

2.调用CardEmulation类的getInstance(NfcController controller)接口,获取CardEmulation实例,去管理本机卡模拟模块操作。

3.调用registerForegroundPreferred(Ability appAbility, ElementName appName)接口去动态设置前台优先应用。

4.调用unregisterForegroundPreferred(Ability appAbility)接口去取消设置前台优先应用。

// 获取NFC控制对象
NfcController nfcController = NfcController.getInstance(context);
// 获取卡模拟控制对象
CardEmulation cardEmulation = CardEmulation.getInstance(nfcController);
// 动态设置前台优先应用
Ability ability = new Ability();
cardEmulation.registerForegroundPreferred(ability, new ElementName());
// 注销前台优先应用
cardEmulation.unregisterForegroundPreferred(ability);

NFC应用的AID相关操作

静态注册AID

在配置文件config.json注册HCE服务,具体可参考Ability。

在配置文件的module中,添加metaData对象,并配置customizeData。

使用paymentAid字段静态注册支付类型的AID,多个支付类型的AID使用‘|’符号隔开。

使用otherAid字段静态注册其他类型的AID,多个其他类型的AID使用‘|’符号隔开。

示例代码如下:

"metaData": {
  "customizeData": [
    {
      "name": "paymentAid",
      "value": "325041592E5359532E4444463031"    
    },
    {
      "name": "otherAid",
      "value": "0123456789|535558494E2E4D46|1234567890"
     }  
  ]
}

动态注册AID

1.调用NfcController类的getInstance(Context context)接口,获取NfcController实例。

2.调用CardEmulation类的getInstance(NfcController controller)接口,获取CardEmulation实例,去管理本机卡模拟模块操作。

3.调用registerAids(ElementName appName, String type, List<String> aids)接口去给应用注册指定类型的AID。

4.调用removeAids(ElementName appName, String type)接口去删除应用的指定类型的AID。

// 获取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);


AID查询

调用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");
}

Host服务的抽象类

应用的服务继承HostService,实现HCE卡模拟功能。

应用自定义实现抽象方法handleRemoteCommand(byte[] cmd, IntentParams params)和disabledCallback()。

应用自定义功能。

// 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消息通知

场景介绍

NFC消息通知是HarmonyOS内部或者与应用之间跨进程通讯的机制,注册者在注册消息通知后,一旦符合条件的消息被发出,注册者即可接收到该消息。


接口说明

表1 NFC消息通知的相关广播介绍

image.png

注册并获取NFC状态改变消息

  1. 1.构建消息通知接收者NfcStateEventSubscriber。
  2. 2.注册NFC状态改变消息。
  3. 3.NfcStateEventSubscriber接收并处理NFC状态改变消息。
// 构建消息接收者/注册者
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());
}

注册并获取NFC场强消息

  1. 1.构建消息通知接收者NfcFieldOnAndOffEventSubscriber。
  2. 2.注册NFC场强消息。
  3. 3.NfcFieldOnAndOffEventSubscriber接收并处理NFC场强消息。
// 构建消息接收者/注册者
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());
}
相关文章
|
2天前
|
UED 开发者
鸿蒙next版开发:ArkTS组件通用属性(运动模糊)
在HarmonyOS 5.0中,ArkTS引入了运动模糊功能,允许开发者为组件添加动态模糊效果,增强视觉表现。本文详细解读了运动模糊的属性和使用方法,并提供了示例代码。运动模糊可增强视觉效果、提升用户体验和实现动态效果,适用于多种场景。
78 2
|
2天前
|
开发者 UED 容器
鸿蒙next版开发:ArkTS组件通用属性(图像效果)
在HarmonyOS 5.0中,ArkTS提供了丰富的图像效果属性,如阴影、灰度、高光、饱和度、对比度、图像反转、叠色、色相旋转等,极大丰富了用户界面的表现力。本文详细介绍这些属性并提供示例代码。
57 2
|
2天前
|
UED
鸿蒙next版开发:ArkTS组件通用属性(前景色设置)
在HarmonyOS 5.0中,ArkTS提供了丰富的组件样式设置能力,包括前景色设置。本文详细解读了ArkTS中前景色设置的通用属性,并通过示例代码展示了如何使用foregroundColor属性设置组件的前景色,从而提升界面美观性和用户体验。
59 1
|
2天前
|
JavaScript 开发者 索引
鸿蒙next版开发:ArkTS组件通用属性(复用标识)
在HarmonyOS 5.0中,ArkTS的复用标识(Reused Identifier)是关键机制,用于标识和引用组件,特别是在列表渲染和组件复用中。本文详细解读了复用标识的通用属性和作用,并提供了示例代码,帮助开发者提高应用性能和效率。
55 1
|
2天前
|
UED 开发者
鸿蒙next版开发:ArkTS组件通用属性(多态样式)
在HarmonyOS 5.0中,ArkTS的多态样式(stateStyles)功能允许开发者根据不同状态(如正常、按压、禁用、聚焦、选中等)为组件设置不同的样式,从而提供更丰富的用户体验。通过stateStyles属性,可以动态改变组件样式,提升用户交互的直观性和界面美观性。示例代码展示了如何为文本组件设置正常和按压状态的样式。
55 1
|
2天前
|
开发者
鸿蒙next版开发:ArkTS组件通用属性(组件标识)
在HarmonyOS 5.0中,ArkTS的组件标识(ID)为每个组件提供唯一标识符,方便开发者引用和操作组件。本文详细解读了id和key属性的使用方法,并提供了示例代码,展示了如何通过组件标识获取属性、发送事件及动态操作组件。
56 1
|
2天前
|
开发者 UED
鸿蒙next版开发:ArkTS组件通用属性(悬浮态效果)
在HarmonyOS 5.0中,ArkTS引入了悬浮态效果的控制属性,使开发者能为组件添加鼠标悬浮时的视觉反馈,增强用户体验。本文详解了hoverEffect属性及其常见效果(Auto、Scale、Highlight、None),并提供了示例代码,展示了如何为按钮设置悬浮效果。通过这些属性,开发者可以实现更生动和互动的界面。
57 1
|
2天前
|
API 开发者 UED
鸿蒙next版开发:ArkTS组件通用属性(焦点控制)
在HarmonyOS 5.0中,ArkTS提供了完善的焦点控制属性,如focusable、defaultFocus、onFocus和onBlur,帮助开发者管理和响应用户界面中的焦点变化。本文详细介绍这些属性,并通过示例代码展示如何使用FocusController类进行焦点管理,提升应用的交互性和无障碍支持。
56 1
|
2天前
|
开发者
鸿蒙next版开发:ArkTS组件通用属性(菜单控制)
在HarmonyOS 5.0中,ArkTS引入了灵活的菜单控制属性,支持通过长按、点击或鼠标右键触发弹出式菜单,增强用户交互体验。本文详细介绍了bindMenu和bindContextMenu方法,以及MenuItem的配置属性,并提供了示例代码,帮助开发者更好地理解和使用这些功能。
57 1
|
2天前
|
开发者
鸿蒙next版开发:ArkTS组件通用属性(Popup控制)
在HarmonyOS 5.0中,ArkTS提供了灵活的Popup控制属性,允许开发者创建和管理弹出窗口,用于显示额外信息、提示、表单等,增强用户交互体验。本文详解了Popup控制的通用属性,并提供了示例代码。通过bindPopup方法,可以将弹出窗口绑定到组件上,支持多种用途,如显示额外信息、表单提交和交互反馈。
57 1