""" Android nfc 扩展 — NfcAdapter, NdefMessage, NdefRecord, Tag, Tech, NfcA, NfcB, NfcF, NfcV, IsoDep, MifareClassic, MifareUltralight, NdefFormatable, CardEmulation, HostApduService, OffHostApduService 方法签名完全对齐 Android SDK """ from __future__ import annotations import sys from typing import Any, Dict, List, Optional, Tuple from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) __all__ = [ "NfcAdapter", "NdefMessage", "NdefRecord", "Tag", "Tech", "NfcA", "NfcB", "NfcF", "NfcV", "NfcBarcode", "IsoDep", "MifareClassic", "MifareUltralight", "NdefFormatable", "CardEmulation", "HostApduService", "OffHostApduService", ] # ═══════════════════════════════════════════════════════════════ # NdefRecord # ═══════════════════════════════════════════════════════════════ class NdefRecord(Stub): """NdefRecord — NDEF 记录""" TNF_EMPTY = 0x00 TNF_ABSOLUTE_URI = 0x03 TNF_MEDIA = 0x02 TNF_WELL_KNOWN = 0x01 TNF_UNCHANGED = 0x06 TNF_RESERVED = 0x07 TNF_EXTERNAL_TYPE = 0x04 RTD_TEXT = b"T" RTD_URI = b"U" RTD_SMART_POSTER = b"Sp" RTD_ALTERNATIVE_CARRIER = b"ac" RTD_HANDOVER_CARRIER = b"Hc" RTD_HANDOVER_REQUEST = b"Hr" RTD_HANDOVER_SELECT = b"Hr" def __init__(self, tnf: int = TNF_EMPTY, type_: bytes = b"", id_: bytes = b"", payload: bytes = b""): super().__init__() self._tnf = tnf self._type = type_ self._id = id_ self._payload = payload @property def tnf(self) -> int: return self._tnf @property def type(self) -> bytes: return self._type @property def id(self) -> bytes: return self._id @property def payload(self) -> bytes: return self._payload def getTnf(self) -> int: """获取 TNF""" return self._tnf def getType(self) -> bytes: """获取类型""" return self._type def getId(self) -> bytes: """获取 ID""" return self._id def getPayload(self) -> bytes: """获取载荷""" return self._payload def toByteArray(self) -> bytes: """转换为字节数组""" return self._tnf.to_bytes(1, 'big') + self._type + self._id + self._payload def toString(self) -> str: return f"NdefRecord(tnf={self._tnf}, type={self._type}, id={self._id}, payload={self._payload})" def equals(self, other: Any) -> bool: if not isinstance(other, NdefRecord): return False return (self._tnf == other._tnf and self._type == other._type and self._id == other._id and self._payload == other._payload) def hashCode(self) -> int: return hash((self._tnf, self._type, self._id, self._payload)) & 0x7FFFFFFF @staticmethod def createUri(uri: str) -> "NdefRecord": """创建 URI 记录""" return NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, b"U", b"", uri.encode()) @staticmethod def createMime(mime_type: str, data: bytes) -> "NdefRecord": """创建 MIME 记录""" return NdefRecord(NdefRecord.TNF_MEDIA, mime_type.encode(), b"", data) @staticmethod def createApplication(package_name: str) -> "NdefRecord": """创建应用记录""" return NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, b"android.com:pkg", b"", package_name.encode()) @staticmethod def createExternal(domain: str, type_: str, data: bytes) -> "NdefRecord": """创建外部类型记录""" return NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, f"{domain}:{type_}".encode(), b"", data) # ═══════════════════════════════════════════════════════════════ # NdefMessage # ═══════════════════════════════════════════════════════════════ class NdefMessage(Stub): """NdefMessage — NDEF 消息""" def __init__(self, records: Optional[List[NdefRecord]] = None): super().__init__() self._records = records or [] @staticmethod def fromBytes(data: bytes) -> "NdefMessage": """从字节数组创建消息""" return NdefMessage() def getRecords(self) -> List[NdefRecord]: """获取记录列表""" return self._records.copy() def getByteArray(self) -> bytes: """获取字节数组""" return b"".join(r.toByteArray() for r in self._records) def toByteArray(self) -> bytes: """转换为字节数组""" return self.getByteArray() def toString(self) -> str: return f"NdefMessage(records={len(self._records)})" # ═══════════════════════════════════════════════════════════════ # Tag # ═══════════════════════════════════════════════════════════════ class Tag(Stub): """Tag — NFC 标签 (桌面存根)""" def __init__(self, id_: bytes = b"", tech_list: Optional[List[str]] = None): super().__init__() self._id = id_ self._tech_list = tech_list or [] self._service_name = "" def getId(self) -> bytes: """获取标签 ID""" return self._id def getTechList(self) -> List[str]: """获取技术列表""" return self._tech_list.copy() def toString(self) -> str: return f"Tag(id={self._id.hex()}, techs={self._tech_list})" def hashCode(self) -> int: return hash(bytes(self._id)) & 0x7FFFFFFF def equals(self, other: Any) -> bool: if not isinstance(other, Tag): return False return self._id == other._id def getServiceName(self) -> str: """获取服务名称""" return self._service_name def getTagService(self) -> Optional[Any]: """获取标签服务""" return None # ═══════════════════════════════════════════════════════════════ # Tech # ═══════════════════════════════════════════════════════════════ class Tech(Stub): """Tech — NFC 技术基类 (桌面存根)""" PRESENCE_CHECK_DELAY = 125 def __init__(self, tag: Optional[Tag] = None): super().__init__() self._tag = tag self._connected = False self._timeout = 500 @staticmethod def get(tag: Tag, tech_class: Any) -> Optional["Tech"]: """获取技术实例""" return None def getTag(self) -> Optional[Tag]: """获取标签""" return self._tag def connect(self) -> None: """连接""" self._connected = True def reconnect(self) -> None: """重新连接""" pass def close(self) -> None: """关闭""" self._connected = False def getConnected(self) -> bool: """检查是否已连接""" return self._connected def isConnected(self) -> bool: """检查是否已连接""" return self._connected def getMaxTransceiveLength(self) -> int: """获取最大收发长度""" return 253 def setTimeout(self, timeout: int) -> None: """设置超时""" self._timeout = timeout def getTimeout(self) -> int: """获取超时""" return self._timeout def transceive(self, data: bytes) -> bytes: """收发数据""" return b"" # ═══════════════════════════════════════════════════════════════ # NfcA # ═══════════════════════════════════════════════════════════════ class NfcA(Tech): """NfcA — NFC-A 技术""" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) self._atqa = b"\x00\x00" self._sak = 0 def getAtqa(self) -> bytes: """获取 ATQA""" return self._atqa def getSak(self) -> int: """获取 SAK""" return self._sak def getMaxTransceiveLength(self) -> int: return 253 # ═══════════════════════════════════════════════════════════════ # NfcB # ═══════════════════════════════════════════════════════════════ class NfcB(Tech): """NfcB — NFC-B 技术""" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) self._application_data = b"" self._protocol_info = b"" def getApplicationData(self) -> bytes: """获取应用数据""" return self._application_data def getProtocolInfo(self) -> bytes: """获取协议信息""" return self._protocol_info def getMaxTransceiveLength(self) -> int: return 253 # ═══════════════════════════════════════════════════════════════ # NfcF # ═══════════════════════════════════════════════════════════════ class NfcF(Tech): """NfcF — NFC-F 技术""" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) self._manufacturer = 0 self._sc = 0 self._system_code = 0 self._pmm = b"" def getManufacturer(self) -> int: """获取制造商""" return self._manufacturer def getSC(self) -> int: """获取 SC""" return self._sc def getSystemCode(self) -> int: """获取系统代码""" return self._system_code def getPMm(self) -> bytes: """获取 PMm""" return self._pmm def getMaxTransceiveLength(self) -> int: return 253 # ═══════════════════════════════════════════════════════════════ # NfcV # ═══════════════════════════════════════════════════════════════ class NfcV(Tech): """NfcV — NFC-V 技术""" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) self._dsf_id = 0 self._response_flags = 0 self._identification = b"" def getDsfId(self) -> int: """获取 DSF ID""" return self._dsf_id def getResponseFlags(self) -> int: """获取响应标志""" return self._response_flags def getIdentification(self) -> bytes: """获取标识""" return self._identification # ═══════════════════════════════════════════════════════════════ # NfcBarcode # ═══════════════════════════════════════════════════════════════ class NfcBarcode(Tech): """NfcBarcode — NFC 条码技术""" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) # ═══════════════════════════════════════════════════════════════ # IsoDep # ═══════════════════════════════════════════════════════════════ class IsoDep(Tech): """IsoDep — ISO-DEP 技术""" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) self._hi_layer_response = b"" self._historical_bytes = b"" self._extended_length_supported = False def getHiLayerResponse(self) -> bytes: """获取高层响应""" return self._hi_layer_response def getHistoricalBytes(self) -> bytes: """获取历史字节""" return self._historical_bytes def setTimeout(self, timeout: int) -> None: self._timeout = timeout def getTimeout(self) -> int: return self._timeout def getMaxTransceiveLength(self) -> int: return 261 if self._extended_length_supported else 128 def isExtendedLengthApduSupported(self) -> bool: """检查是否支持扩展长度 APDU""" return self._extended_length_supported def transceive(self, data: bytes) -> bytes: return b"\x90\x00" # SW1=0x90, SW2=0x00 = success # ═══════════════════════════════════════════════════════════════ # MifareClassic # ═══════════════════════════════════════════════════════════════ class MifareClassic(Tech): """MifareClassic — MIFARE Classic 技术""" TYPE_CLASSIC = 0 TYPE_PLUS = 1 TYPE_PRO = 2 TYPE_UNKNOWN = -1 SIZE_1K = 1024 SIZE_2K = 2048 SIZE_4K = 4096 SIZE_MINI = 320 KEY_DEFAULT = b"\xFF\xFF\xFF\xFF\xFF\xFF" KEY_MIFARE_APPLICATION_DIRECTORY = b"\xA0\xA1\xA2\xA3\xA4\xA5" KEY_NFC_FORUM = b"\xD3\xF7\xD3\xF7\xD3\xF7" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) self._type = MifareClassic.TYPE_CLASSIC self._size = MifareClassic.SIZE_1K def authenticateSectorWithKeyA(self, sector_index: int, key: bytes) -> bool: """使用密钥 A 认证扇区""" return False def authenticateSectorWithKeyB(self, sector_index: int, key: bytes) -> bool: """使用密钥 B 认证扇区""" return False def readBlock(self, block_index: int) -> bytes: """读取块""" return b"\x00" * 16 def writeBlock(self, block_index: int, data: bytes) -> None: """写入块""" pass def readSector(self, sector_index: int) -> List[bytes]: """读取扇区""" return [b"\x00" * 16] * 4 def writeSector(self, sector_index: int, data: List[bytes]) -> None: """写入扇区""" pass @staticmethod def sectorToBlock(sector_index: int) -> int: """扇区索引转块索引""" if sector_index < 32: return sector_index * 4 return 32 * 4 + (sector_index - 32) * 16 @staticmethod def blockToSector(block_index: int) -> int: """块索引转扇区索引""" if block_index < 128: return block_index // 4 return 32 + (block_index - 128) // 16 @staticmethod def getBlockCountInSector(sector_index: int) -> int: """获取扇区中的块数量""" return 4 if sector_index < 32 else 16 def isEmulated(self) -> bool: """检查是否模拟""" return False def getMaxTransceiveLength(self) -> int: return 16 # ═══════════════════════════════════════════════════════════════ # MifareUltralight # ═══════════════════════════════════════════════════════════════ class MifareUltralight(Tech): """MifareUltralight — MIFARE Ultralight 技术""" TYPE_ULTRALIGHT = 1 TYPE_ULTRALIGHT_C = 2 TYPE_ULTRALIGHT_EV1 = 3 TYPE_NTAG_2xx = 4 TYPE_UNKNOWN = -1 def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) self._type = MifareUltralight.TYPE_ULTRALIGHT def readPages(self, page_offset: int) -> bytes: """读取页""" return b"\x00" * 16 def writePage(self, page_offset: int, data: bytes) -> None: """写入页""" pass def setTimeout(self, timeout: int) -> None: self._timeout = timeout def getTimeout(self) -> int: return self._timeout def getMaxTransceiveLength(self) -> int: return 16 # ═══════════════════════════════════════════════════════════════ # NdefFormatable # ═══════════════════════════════════════════════════════════════ class NdefFormatable(Tech): """NdefFormatable — NDEF 可格式化技术""" def __init__(self, tag: Optional[Tag] = None): super().__init__(tag) def format(self, first_message: NdefMessage) -> None: """格式化""" pass def formatReadOnly(self, first_message: NdefMessage) -> None: """格式化为只读""" pass # ═══════════════════════════════════════════════════════════════ # NfcAdapter # ═══════════════════════════════════════════════════════════════ class NfcAdapter(Stub): """NfcAdapter — NFC 适配器 (桌面存根)""" ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED" ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED" ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED" ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED" EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE" STATE_OFF = 1 STATE_TURNING_ON = 2 STATE_ON = 3 STATE_TURNING_OFF = 4 EXTRA_TAG = "android.nfc.extra.TAG" EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES" EXTRA_ID = "android.nfc.extra.ID" FLAG_READER_NFC_A = 0x01 FLAG_READER_NFC_B = 0x02 FLAG_READER_NFC_F = 0x04 FLAG_READER_NFC_V = 0x08 FLAG_READER_NFC_BARCODE = 0x10 FLAG_READER_SKIP_NDEF_CHECK = 0x20 FLAG_READER_NO_PLATFORM_SOUNDS = 0x40 FLAG_READER_LISTEN_MODE = 0x80 _instance: Optional["NfcAdapter"] = None def __init__(self, context: Any = None): super().__init__() self._context = context self._enabled = True self._ndef_push_enabled = False self._secure_nfc_enabled = False self._reader_mode_flags = 0 self._tech_list: List[str] = [] self._foreground_dispatch_active = False self._foreground_reader_active = False @staticmethod def getDefaultAdapter(context: Any) -> Optional["NfcAdapter"]: """获取默认适配器""" if NfcAdapter._instance is None: NfcAdapter._instance = NfcAdapter(context) return NfcAdapter._instance def isEnabled(self) -> bool: """检查 NFC 是否启用""" return self._enabled def enableForegroundDispatch(self, activity: Any, intent: Any, filters: List[Any], tech_lists: List[List[str]]) -> None: """启用前台分发""" self._foreground_dispatch_active = True def disableForegroundDispatch(self, activity: Any) -> None: """禁用前台分发""" self._foreground_dispatch_active = False def enableForegroundReader(self, activity: Any, flags: int, tech_lists: List[List[str]]) -> None: """启用前台读取器""" self._foreground_reader_active = True self._reader_mode_flags = flags def disableForegroundReader(self, activity: Any) -> None: """禁用前台读取器""" self._foreground_reader_active = False def enableReaderMode(self, activity: Any, callback: Any, flags: int, extras: Any = None) -> None: """启用读取器模式""" self._reader_mode_flags = flags def disableReaderMode(self, activity: Any) -> None: """禁用读取器模式""" self._reader_mode_flags = 0 def setNdefPushMessage(self, message: NdefMessage, activity: Any, *activities: Any) -> None: """设置 NDEF 推送消息""" pass def setNdefPushMessageCallback(self, callback: Any, activity: Any, *activities: Any) -> None: """设置 NDEF 推送消息回调""" pass def setOnNdefPushCompleteCallback(self, callback: Any, activity: Any, *activities: Any) -> None: """设置 NDEF 推送完成回调""" pass def enableNdefPush(self, activity: Any) -> None: """启用 NDEF 推送""" self._ndef_push_enabled = True def disableNdefPush(self, activity: Any) -> None: """禁用 NDEF 推送""" self._ndef_push_enabled = False def isNdefPushEnabled(self) -> bool: """检查 NDEF 推送是否启用""" return self._ndef_push_enabled def createNdefMessage(self, message: NdefMessage) -> None: """创建 NDEF 消息""" pass def getNfcAdapterExtrasInterface(self) -> Optional[Any]: """获取 NFC 适配器附加接口""" return None def isSecureNfcSupported(self) -> bool: """检查是否支持安全 NFC""" return True def isSecureNfcEnabled(self) -> bool: """检查安全 NFC 是否启用""" return self._secure_nfc_enabled def enableSecureNfc(self, enabled: bool) -> bool: """启用安全 NFC""" self._secure_nfc_enabled = enabled return True def disableSecureNfc(self) -> bool: """禁用安全 NFC""" self._secure_nfc_enabled = False return True def getMaxTransceiveLength(self, tech: str) -> int: """获取最大收发长度""" return 253 def getTechList(self) -> List[str]: """获取技术列表""" return self._tech_list.copy() def setTechList(self, tech_list: List[str]) -> None: """设置技术列表""" self._tech_list = tech_list # ═══════════════════════════════════════════════════════════════ # CardEmulation # ═══════════════════════════════════════════════════════════════ class CardEmulation(Stub): """CardEmulation — 卡模拟 (桌面存根)""" CATEGORY_PAYMENT = "payment" CATEGORY_OTHER = "other" SELECTION_MODE_PREFER_DEFAULT = 0 SELECTION_MODE_ALWAYS_ASK = 1 def __init__(self): super().__init__() self._aid_groups: Dict[str, List[Any]] = {} self._selection_modes: Dict[str, int] = {} def isDefaultServiceForCategory(self, service_component: Any, category: str) -> bool: """检查是否是类别的默认服务""" return False def setPreferredService(self, service_component: Any) -> None: """设置首选服务""" pass def unsetPreferredService(self) -> None: """取消设置首选服务""" pass def getSelectionModes(self, category: str) -> int: """获取选择模式""" return self._selection_modes.get(category, CardEmulation.SELECTION_MODE_PREFER_DEFAULT) def setSelectionModeForCategory(self, category: str, mode: int) -> None: """设置类别选择模式""" self._selection_modes[category] = mode def getCategory(self, service_component: Any) -> str: """获取类别""" return CardEmulation.CATEGORY_OTHER def registerAidGroup(self, service_component: Any, aid_group: Any) -> bool: """注册 AID 组""" return False def unregisterAidGroup(self, service_component: Any, aid_group: Any) -> bool: """注销 AID 组""" return False def setAidGroup(self, service_component: Any, aid_group: Any) -> None: """设置 AID 组""" pass def getAidGroup(self, service_component: Any, category: str) -> Optional[Any]: """获取 AID 组""" return None def addAidGroup(self, service_component: Any, aid_group: Any) -> None: """添加 AID 组""" pass def removeAidGroup(self, service_component: Any, aid_group: Any) -> None: """移除 AID 组""" pass # ═══════════════════════════════════════════════════════════════ # HostApduService # ═══════════════════════════════════════════════════════════════ class HostApduService(Stub): """HostApduService — 主机 APDU 服务 (桌面存根)""" SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE" SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service" DEACTIVATION_LINK_LOSS = 0 DEACTIVATION_DESELECTED = 1 def __init__(self): super().__init__() def processCommandApdu(self, command_apdu: bytes, extras: Any = None) -> bytes: """处理命令 APDU""" return b"\x90\x00" def onDeactivated(self, reason: int) -> None: """去激活回调""" pass def sendResponseApdu(self, response_apdu: bytes) -> None: """发送响应 APDU""" pass def notifyUnhandled(self) -> None: """通知未处理""" pass # ═══════════════════════════════════════════════════════════════ # OffHostApduService # ═══════════════════════════════════════════════════════════════ class OffHostApduService(Stub): """OffHostApduService — 脱机主机 APDU 服务 (桌面存根)""" SERVICE_INTERFACE = "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE" SERVICE_META_DATA = "android.nfc.cardemulation.off_host_apdu_service" def __init__(self): super().__init__()