""" Android NFC 组件 — NfcAdapter, NfcManager, Tag, NdefMessage 等 方法签名完全对齐 Android SDK """ import os import sys from typing import Any, Dict, List, Optional, Set, Tuple, Union from .._core import ( Stub, AndroidOnlyError, android_context, resolve_android_path, to_android_path, _sdcard_root, _app_data_dir, _package_name, ) # ═══════════════════════════════════════════════════════════════ # NdefRecord # ═══════════════════════════════════════════════════════════════ class NdefRecord(Stub): """NdefRecord — NDEF 记录""" TNF_ABSOLUTE_URI = 3 TNF_EMPTY = 0 TNF_EXTERNAL_TYPE = 4 TNF_MIME_MEDIA = 2 TNF_UNCHANGED = 6 TNF_UNKNOWN = 5 TNF_WELL_KNOWN = 1 RTD_URI = "U" RTD_TEXT = "T" RTD_SMART_POSTER = "Sp" RTD_ALTERNATIVE_CARRIER = "ac" RTD_HANDOVER_CARRIER = "Hc" RTD_HANDOVER_REQUEST = "Hr" RTD_HANDOVER_SELECT = "Hs" 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 @staticmethod def createUri(uri_spec: str) -> "NdefRecord": return NdefRecord(NdefRecord.TNF_ABSOLUTE_URI, type_=uri_spec.encode("utf-8"), payload=uri_spec.encode("utf-8")) @staticmethod def createMime(mime_type: str, data: bytes) -> "NdefRecord": return NdefRecord(NdefRecord.TNF_MIME_MEDIA, type_=mime_type.encode("utf-8"), payload=data) @staticmethod def createExternal(domain: str, type_: str, data: bytes) -> "NdefRecord": full_type = f"{domain}:{type_}" return NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, type_=full_type.encode("utf-8"), payload=data) @staticmethod def createApplicationRecord(package_name: str) -> "NdefRecord": return NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE, type_=package_name.encode("utf-8"), payload=package_name.encode("utf-8")) def getTnf(self) -> int: return self._tnf def getType(self) -> bytes: return self._type def getId(self) -> bytes: return self._id def getPayload(self) -> bytes: return self._payload def toByteArray(self) -> bytes: import struct tnf_byte = struct.pack("B", self._tnf & 0x07) type_len = len(self._type) id_len = len(self._id) payload_len = len(self._payload) header = struct.pack("BB", type_len, id_len) return tnf_byte + header + struct.pack(">I", payload_len) + \ self._type + self._id + self._payload def toString(self) -> str: return f"NdefRecord(tnf={self._tnf}, type={self._type})" # ═══════════════════════════════════════════════════════════════ # NdefMessage # ═══════════════════════════════════════════════════════════════ class NdefMessage(Stub): """NdefMessage — NDEF 消息""" def __init__(self, records: Union[List[NdefRecord], bytes, Any]): super().__init__() if isinstance(records, list): self._records = list(records) elif isinstance(records, bytes): self._records = [] else: self._records = [] def getRecords(self) -> List[NdefRecord]: return list(self._records) def getByteArrayLength(self) -> int: return sum(len(r.toByteArray()) for r in self._records) def toByteArray(self) -> bytes: data = b"" for r in self._records: data += r.toByteArray() return data # ═══════════════════════════════════════════════════════════════ # 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 [] def getId(self) -> bytes: return self._id def getTechList(self) -> List[str]: return list(self._tech_list) def getTechListParcelable(self) -> Any: return TechListParcelable(self._tech_list) def toString(self) -> str: return f"Tag(id={self._id.hex()}, techs={self._tech_list})" class TechListParcelable(Stub): """TechListParcelable — 技术列表包裹""" def __init__(self, tech_list: List[str]): super().__init__() self._tech_list = list(tech_list) def getTechList(self) -> List[str]: return list(self._tech_list) def toString(self) -> str: return f"TechListParcelable(techs={self._tech_list})" # ═══════════════════════════════════════════════════════════════ # NfcAdapter callback classes # ═══════════════════════════════════════════════════════════════ class NfcAdapterCreateBeamUrisCallback(Stub): def createBeamUris(self, event: "NfcEvent") -> List[Any]: return [] class NfcAdapterOnNdefPushCompleteCallback(Stub): def onNdefPushComplete(self, event: "NfcEvent"): pass class NdefMessageCallback(Stub): def createNdefMessage(self, event: "NfcEvent") -> Optional[NdefMessage]: return None # ═══════════════════════════════════════════════════════════════ # NfcEvent # ═══════════════════════════════════════════════════════════════ class NfcEvent(Stub): """NfcEvent — NFC 事件""" def __init__(self, nfc_adapter: Any = None): super().__init__() self.nfcAdapter = nfc_adapter def getNfcAdapter(self) -> Any: return self.nfcAdapter # ═══════════════════════════════════════════════════════════════ # NfcAntennaInfo / ApduServiceInfo / CardEmulation / NfcFCardEmulation # ═══════════════════════════════════════════════════════════════ class NfcAntennaInfo(Stub): """NfcAntennaInfo — NFC 天线信息""" def __init__(self, x: float = 0.0, y: float = 0.0): super().__init__() self._x = x self._y = y def getX(self) -> float: return self._x def getY(self) -> float: return self._y class ApduServiceInfo(Stub): """ApduServiceInfo — APDU 服务信息""" def __init__(self, description: str = ""): super().__init__() self._description = description def getDescription(self) -> str: return self._description class CardEmulation(Stub): """CardEmulation — 卡模拟""" CATEGORY_PAYMENT = "payment" CATEGORY_OTHER = "other" SELECTION_TYPE_ASK_IF_CONFLICT = 1 SELECTION_TYPE_PREFER_DEFAULT = 2 SELECTION_TYPE_USER_PROMPTED = 0 class NfcFCardEmulation(Stub): """NfcFCardEmulation — NFC-F 卡模拟""" EXTRA_NFC_F_CARD_EMULATION_PARAMS = "android.nfc.extra.EXTRA_NFC_F_CARD_EMULATION_PARAMS" @staticmethod def getInstance(nfc_adapter: Any) -> "NfcFCardEmulation": return NfcFCardEmulation() def enableService(self, activity: Any, service: Any) -> bool: return True def disableService(self, activity: Any, service: Any) -> bool: return True def setSystemCodeForService(self, activity: Any, service: Any, system_code: str) -> bool: return True # ═══════════════════════════════════════════════════════════════ # NfcManager # ═══════════════════════════════════════════════════════════════ class NfcManager(Stub): """NfcManager — NFC 管理器""" def __init__(self, context: Any = None): super().__init__() self._context = context self._default_adapter: Optional["NfcAdapter"] = None def getDefaultAdapter(self) -> Optional["NfcAdapter"]: if self._default_adapter is None: self._default_adapter = NfcAdapter() return self._default_adapter # ═══════════════════════════════════════════════════════════════ # 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" FLAG_READER_NFC_A = 1 FLAG_READER_NFC_B = 2 FLAG_READER_NFC_F = 4 FLAG_READER_NFC_V = 8 FLAG_READER_NFC_BARCODE = 16 FLAG_READER_SKIP_NDEF_CHECK = 128 FLAG_READER_NO_PLATFORM_SOUNDS = 256 FLAG_NDEF_PUSH_NO_CONFIRM = 1 _default_adapter: Optional["NfcAdapter"] = None def __init__(self): super().__init__() self._enabled = True self._ndef_push_message: Optional[NdefMessage] = None self._ndef_push_callback: Optional[NdefMessageCallback] = None self._push_complete_callback: Optional[NfcAdapterOnNdefPushCompleteCallback] = None self._beam_uri_callback: Optional[NfcAdapterCreateBeamUrisCallback] = None @staticmethod def getDefaultAdapter(context: Any = None) -> Optional["NfcAdapter"]: if NfcAdapter._default_adapter is None: NfcAdapter._default_adapter = NfcAdapter() return NfcAdapter._default_adapter def isEnabled(self) -> bool: return self._enabled def enable(self) -> bool: self._enabled = True return True def disable(self) -> bool: self._enabled = False return True def setNdefPushMessage(self, message: NdefMessage, activity: Any, vararg_activities: Any = None): self._ndef_push_message = message def setNdefPushMessageCallback(self, callback: NdefMessageCallback, activity: Any, vararg_activities: Any = None): self._ndef_push_callback = callback def setOnNdefPushCompleteCallback(self, callback: NfcAdapterOnNdefPushCompleteCallback, activity: Any, vararg_activities: Any = None): self._push_complete_callback = callback def setBeamUrisCallback(self, callback: NfcAdapterCreateBeamUrisCallback, activity: Any): self._beam_uri_callback = callback def enableForegroundDispatch(self, activity: Any, intent: Any, filters: Any, tech_lists: Any): pass def disableForegroundDispatch(self, activity: Any): pass def enableReaderMode(self, activity: Any, callback: Any, flags: int, extras: Any = None): pass def disableReaderMode(self, activity: Any): pass def invokeBeam(self, activity: Any) -> bool: return True def isSecureNfcSupported(self) -> bool: return False def isSecureNfcEnabled(self) -> bool: return False def enableSecureNfc(self, enable: bool) -> bool: return True def toString(self) -> str: return f"NfcAdapter(enabled={self._enabled})" # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "NfcAdapter", "NfcManager", "Tag", "NdefMessage", "NdefRecord", "NfcEvent", "NfcAdapterCreateBeamUrisCallback", "NfcAdapterOnNdefPushCompleteCallback", "NdefMessageCallback", "TechListParcelable", "NfcAntennaInfo", "ApduServiceInfo", "CardEmulation", "NfcFCardEmulation", ]