카드 에뮬레이션 기능
장면 소개
이 장치는 카드를 시뮬레이션하여 카드를 교체하여 액세스 제어 카드, 버스 카드 등 시뮬레이션과 같은 해당 작업을 완료할 수 있습니다. 애플리케이션 또는 기타 모듈은 인터페이스를 통해 다음 기능을 완료할 수 있습니다.
- 지정된 보안 장치의 카드 에뮬레이션 기능 지원 여부를 쿼리합니다. 보안 장치에는 HCE(Host Card Emulation), ESE(Embedded Secure Element) 및 SIM(Subscriber Identity Module) 카드가 포함됩니다.
- 지정된 기술 유형의 카드 에뮬레이션을 켜거나 끄고 카드 에뮬레이션 상태를 쿼리합니다.
- 현재 활성화된 보안 장치, Hisee 전원 켜짐 상태, RSSI(Received Signal Strength Indication) 쿼리 지원 여부 등 NFC 정보를 얻습니다.
- NFC 서비스의 종류에 따라 결제(Payment) 유형과 미결제(Other) 유형으로 카드를 스와이프할 때 서비스를 선택하는 방법을 얻습니다.
- 전경 우선 앱을 동적으로 설정하고 로그아웃합니다.
- 애플리케이션 AID 등록 및 삭제, 애플리케이션이 지정된 AID의 기본 애플리케이션인지 여부 조회, 애플리케이션의 AID 획득 등 NFC 애플리케이션의 AID(Application Identifier, 애플리케이션 식별) 관련 작업
- Host 및 OffHost 서비스의 추상 클래스를 정의하고 응용 프로그램은 추상 클래스를 상속하여 NFC 카드 시뮬레이션 기능을 구현할 수 있습니다.
인터페이스 설명
NFC 카드 에뮬레이션 기능의 주요 인터페이스를 설명하면 해당 인터페이스를 사용하기 전에 ohos.permission.NFC_CARD_EMULATION 권한을 신청해야 합니다.
클래스 이름 |
인터페이스 이름 |
기능 설명 |
---|---|---|
카드에뮬레이션 |
getInstance(NfcController 컨트롤러) |
카드 시뮬레이션 클래스의 인스턴스를 만듭니다. |
isSupported(정수 기능) |
카드 에뮬레이션 기능이 지원되는지 쿼리합니다. |
|
setListenMode(정수 모드) |
카드 에뮬레이션 모드를 설정합니다. |
|
isListenModeEnabled() |
카드 에뮬레이션 기능이 활성화되어 있는지 쿼리합니다. |
|
getNfcInfo(문자열 키) |
NFC 정보를 가져옵니다. |
|
getSelectionType(문자열 카테고리) |
NFC 서비스의 종류에 따라 카드를 스와이프할 때 서비스를 선택하는 방법을 습득합니다. |
|
registerForegroundPreferred(능력 appAbility, ElementName appName) |
포그라운드 우선순위 애플리케이션을 동적으로 설정합니다. |
|
unregisterForegroundPreferred(능력 appAbility) |
포그라운드 우선 앱을 설정 해제합니다. |
|
isDefaultForAid(ElementName appName, String aid) |
애플리케이션이 지정된 AID에 대한 기본 처리 애플리케이션인지 여부를 판별하십시오. |
|
registerAids(ElementName appName, String type, List<String> aids) |
애플리케이션에 지정된 유형의 AID를 등록합니다. |
|
removeAids(ElementName appName, 문자열 유형) |
애플리케이션에서 지정된 유형의 AID를 삭제합니다. |
|
getAids(ElementName appName, 문자열 유형) |
애플리케이션에서 지정된 유형의 AID 목록을 가져옵니다. |
|
호스트 서비스 |
sendResponse(바이트[] 응답) |
피어 장치에 응답 데이터를 보냅니다. |
handleRemoteCommand(byte[] cmd, IntentParams params) |
피어 장치에서 보낸 명령을 처리합니다. |
|
disabledCallback(int errCode) |
연결 예외에 대한 콜백. |
카드 에뮬레이션 기능 지원 여부 쿼리
- NfcController 인스턴스를 얻기 위해 NfcController 클래스의 getInstance(Context context) 인터페이스를 호출합니다.
- CardEmulation 클래스의 getInstance(NfcController 컨트롤러) 인터페이스를 호출하여 로컬 카드 시뮬레이션 모듈의 작업을 관리하기 위한 CardEmulation 인스턴스를 가져옵니다.
- 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);
스위치 카드 시뮬레이션 및 쿼리 카드 시뮬레이션 상태
- NfcController 인스턴스를 얻기 위해 NfcController 클래스의 getInstance(Context context) 인터페이스를 호출합니다.
- CardEmulation 클래스의 getInstance(NfcController 컨트롤러) 인터페이스를 호출하여 로컬 카드 시뮬레이션 모듈의 작업을 관리하기 위한 CardEmulation 인스턴스를 가져옵니다.
- setListenMode(int mode) 인터페이스를 호출하여 카드 에뮬레이션을 활성화 또는 비활성화합니다.
- 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 정보 얻기
- NfcController 인스턴스를 얻기 위해 NfcController 클래스의 getInstance(Context context) 인터페이스를 호출합니다.
- CardEmulation 클래스의 getInstance(NfcController 컨트롤러) 인터페이스를 호출하여 로컬 카드 시뮬레이션 모듈의 작업을 관리하기 위한 CardEmulation 인스턴스를 가져옵니다.
- 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 서비스의 종류에 따라 카드를 스와이프할 때 서비스를 선택하는 방법을 얻습니다.
- NfcController 인스턴스를 얻기 위해 NfcController 클래스의 getInstance(Context context) 인터페이스를 호출합니다.
- CardEmulation 클래스의 getInstance(NfcController 컨트롤러) 인터페이스를 호출하여 로컬 카드 시뮬레이션 모듈의 작업을 관리하기 위한 CardEmulation 인스턴스를 가져옵니다.
- getSelectionType(문자열 범주) 인터페이스를 호출하여 선택 서비스 메서드를 가져옵니다.
// 获取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
포그라운드 우선 애플리케이션에서 동적으로 설정 및 로그아웃
- NfcController 인스턴스를 얻기 위해 NfcController 클래스의 getInstance(Context context) 인터페이스를 호출합니다.
- CardEmulation 클래스의 getInstance(NfcController 컨트롤러) 인터페이스를 호출하여 로컬 카드 시뮬레이션 모듈의 작업을 관리하기 위한 CardEmulation 인스턴스를 가져옵니다.
- 전경 우선 애플리케이션을 동적으로 설정하려면 registerForegroundPreferred(Ability appAbility, ElementName appName) 인터페이스를 호출합니다.
- 포그라운드 선호 애플리케이션 설정을 취소하려면 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 서비스를 등록합니다. 자세한 내용은 능력을 참조하십시오 .
- 구성 파일의 모듈에서 metaData 개체를 추가하고 customizeData를 구성합니다.
- paymentAid 필드를 사용하여 지불 유형의 AID를 정적으로 등록하고 '|' 기호를 사용하여 지불 유형의 여러 AID를 구분하십시오.
- otherAid 필드를 사용하여 다른 유형의 AID를 정적으로 등록하고 '|' 기호를 사용하여 다른 여러 유형의 AID를 구분하십시오.
샘플 코드는 다음과 같습니다.
"metaData": {
"customizeData": [
{
"name": "paymentAid",
"value": "325041592E5359532E4444463031"
},
{
"name": "otherAid",
"value": "0123456789|535558494E2E4D46|1234567890"
}
]
}
동적으로 AID 등록
- NfcController 인스턴스를 얻기 위해 NfcController 클래스의 getInstance(Context context) 인터페이스를 호출합니다.
- CardEmulation 클래스의 getInstance(NfcController 컨트롤러) 인터페이스를 호출하여 로컬 카드 시뮬레이션 모듈의 작업을 관리하기 위한 CardEmulation 인스턴스를 가져옵니다.
- registerAids(ElementName appName, String type, List<String> aids) 인터페이스를 호출하여 애플리케이션에 지정된 유형의 AID를 등록합니다.
- 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");
}
호스트 서비스의 추상 클래스
- 애플리케이션 서비스는 HCE 카드 시뮬레이션 기능을 구현하기 위해 HostService를 상속합니다.
- 추상 메서드 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 내에서 또는 애플리케이션과의 프로세스 간 통신을 위한 메커니즘입니다 등록자가 메시지 알림에 등록한 후 인증된 메시지가 전송되면 등록자는 메시지를 받을 수 있습니다.
인터페이스 설명
설명하다 |
알림 이름 |
추가 매개변수 |
---|---|---|
NFC 상태 |
보통.event.nfc.action.ADAPTER_STATE_CHANGED |
extra_nfc_state |
참가 소식 |
보통.event.nfc.action.RF_FIELD_ON_DETECTED |
extra_nfc_transaction |
출발 메시지 |
보통.event.nfc.action.RF_FIELD_OFF_DETECTED |
- |
등록하고 NFC 상태 변경 메시지 받기
- 메시지 알림 수신자 NfcStateEventSubscriber를 빌드합니다.
- NFC 상태 변경 메시지를 등록합니다.
- 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 전계 강도 소식 받기
- 메시지 알림 수신자 NfcFieldOnAndOffEventSubscriber를 빌드합니다.
- NFC 전계 강도 메시지에 등록하십시오.
- 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());
}