""" Android SIP API — SipManager, SipProfile, SipSession, SipAudioCall (已废弃但存在于 SDK 中) 方法签名完全对齐 Android SDK """ import sys from typing import Any, Dict, List, Optional, Set, Tuple, Callable from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) __all__ = [ "SipManager", "SipProfile", "SipSession", "SipAudioCall", ] # ═══════════════════════════════════════════════════════════════ # SipManager # ═══════════════════════════════════════════════════════════════ class SipManager(Stub): """SipManager — SIP 会话管理器 (桌面存根, 已废弃)""" EXTRA_CALL_ID = "android.sip.extra.CALL_ID" EXTRA_OFFER_SD = "android.sip.extra.OFFER_SD" EXTRA_PEER_PROFILE = "android.sip.extra.PEER_PROFILE" def __init__(self, context: Any = None): super().__init__() self._context = context self._opened = False self._registered = False self._session: Optional["SipSession"] = None self._listener: Optional[Callable] = None @staticmethod def isSipWifiOnly(context: Any) -> bool: """检查 SIP 是否仅限 WiFi""" return False @staticmethod def isVoipSupported(context: Any) -> bool: """检查是否支持 VoIP""" return True @staticmethod def isApiSupported(context: Any) -> bool: """检查 SIP API 是否支持""" return True @staticmethod def newInstance(context: Any) -> "SipManager": """创建新实例""" return SipManager(context) def open(self, localProfile: "SipProfile") -> "SipSession": """打开 SIP 会话""" self._opened = True self._session = SipSession(localProfile) return self._session def setRegistrationListener( self, localProfileUri: str, listener: "SipSession.Listener" ): """设置注册监听器""" if self._session: self._session.setListener(listener) def close(self, localProfileUri: str): """关闭 SIP 会话""" self._opened = False self._registered = False self._session = None def getSessionFor(self, intent: Any) -> Optional["SipSession"]: """获取 Intent 对应的 SIP 会话""" return self._session def register( self, localProfile: "SipProfile", expiryTime: int, listener: "SipSession.Listener" ): """注册 SIP""" raise AndroidOnlyError("SipManager.register() 仅在 Android 设备上可用") def unregister( self, localProfile: "SipProfile", listener: "SipSession.Listener" ): """注销 SIP""" raise AndroidOnlyError("SipManager.unregister() 仅在 Android 设备上可用") def isOpened(self, localProfileUri: str) -> bool: """检查是否已打开""" return self._opened def isRegistered(self, localProfileUri: str) -> bool: """检查是否已注册""" return self._registered def createSipSessionIfNeeded(self, localProfile: "SipProfile") -> "SipSession": """如有必要则创建 SIP 会话""" if self._session is None: self._session = SipSession(localProfile) return self._session def createSipProfile(self, intent: Any) -> Optional["SipProfile"]: """从 Intent 创建 SIP 配置文件""" return None def toString(self) -> str: return f"SipManager(opened={self._opened}, registered={self._registered})" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════════ # SipProfile # ═══════════════════════════════════════════════════════════════ class SipProfile(Stub): """SipProfile — SIP 配置文件""" # --- Protocol constants --- PROTOCOL_UDP = "UDP" PROTOCOL_TCP = "TCP" PROTOCOL_TLS = "TLS" class Builder(Stub): """SipProfile.Builder — SIP 配置文件构建器""" def __init__(self, uri: str = ""): super().__init__() self._profile = SipProfile() self._profile._uri = uri def setProfileName(self, name: str) -> "SipProfile.Builder": self._profile._profile_name = name return self def setUserName(self, userName: str) -> "SipProfile.Builder": self._profile._user_name = userName return self def setDomain(self, domain: str) -> "SipProfile.Builder": self._profile._domain = domain return self def setPassword(self, password: str) -> "SipProfile.Builder": self._profile._password = password return self def setPort(self, port: int) -> "SipProfile.Builder": self._profile._port = port return self def setProtocol(self, protocol: str) -> "SipProfile.Builder": self._profile._protocol = protocol return self def setSendKeepAlive(self, enabled: bool) -> "SipProfile.Builder": self._profile._send_keep_alive = enabled return self def setAutoRegistration(self, enabled: bool) -> "SipProfile.Builder": self._profile._auto_registration = enabled return self def setDisplayName(self, displayName: str) -> "SipProfile.Builder": self._profile._display_name = displayName return self def setAuthUserName(self, authUserName: str) -> "SipProfile.Builder": self._profile._auth_user_name = authUserName return self def build(self) -> "SipProfile": return self._profile def toString(self) -> str: return f"SipProfile.Builder(name={self._profile._profile_name})" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF def __init__(self): super().__init__() self._uri = "" self._profile_name = "" self._user_name = "" self._domain = "" self._display_name = "" self._password = "" self._protocol = self.PROTOCOL_UDP self._port = 5060 self._send_keep_alive = False self._auto_registration = True self._auth_user_name = "" def getProfileName(self) -> str: return self._profile_name def getUserName(self) -> str: return self._user_name def getDomain(self) -> str: return self._domain def getDisplayName(self) -> str: return self._display_name def getPassword(self) -> str: return self._password def getProtocol(self) -> str: return self._protocol def getPort(self) -> int: return self._port def getSendKeepAlive(self) -> bool: return self._send_keep_alive def isAutoRegistration(self) -> bool: return self._auto_registration def getUri(self) -> str: return self._uri def toString(self) -> str: return (f"SipProfile(name={self._profile_name}, " f"user={self._user_name}@{self._domain})") def equals(self, other) -> bool: if not isinstance(other, SipProfile): return False return self._uri == other._uri def hashCode(self) -> int: return hash(self._uri) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════════ # SipSession # ═══════════════════════════════════════════════════════════════ class SipSession(Stub): """SipSession — SIP 会话""" # --- State constants --- STATE_READY_TO_CALL = 0 STATE_INCOMING_CALL = 1 STATE_INCOMING_CALL_ANSWERING = 2 STATE_IN_CALL = 3 STATE_OUTGOING_CALL = 4 STATE_OUTGOING_CALL_RINGING = 5 STATE_OUTGOING_CALL_CANCELING = 6 STATE_PINGING = 7 STATE_DEREGISTERING = 8 STATE_CLOSED = 9 def __init__(self, profile: "SipProfile" = None): super().__init__() self._profile = profile self._listener: Optional["SipSession.Listener"] = None self._state = self.STATE_CLOSED self._call_id = "" self._peer_profile: Optional[SipProfile] = None self._in_call = False def setListener(self, listener: "SipSession.Listener"): """设置会话监听器""" self._listener = listener def register(self, duration: int): """注册 SIP""" raise AndroidOnlyError("SipSession.register() 仅在 Android 设备上可用") def unregister(self): """注销 SIP""" raise AndroidOnlyError("SipSession.unregister() 仅在 Android 设备上可用") def makeAudioCall( self, localProfile: "SipProfile", peerProfile: "SipProfile" ): """发起音频呼叫""" raise AndroidOnlyError("SipSession.makeAudioCall() 仅在 Android 设备上可用") def answerCall(self, callId: str, sessionDescription: int): """接听呼叫""" raise AndroidOnlyError("SipSession.answerCall() 仅在 Android 设备上可用") def endCall(self): """结束呼叫""" raise AndroidOnlyError("SipSession.endCall() 仅在 Android 设备上可用") def changeCall(self, callId: str, sessionDescription: int): """更改呼叫""" raise AndroidOnlyError("SipSession.changeCall() 仅在 Android 设备上可用") def getCallId(self) -> str: return self._call_id def getPeerProfile(self) -> Optional["SipProfile"]: return self._peer_profile def getState(self) -> int: return self._state def isInCall(self) -> bool: return self._in_call def getLocalProfile(self) -> Optional["SipProfile"]: return self._profile # ═══════════════════════════════════════════════════════════ # Listener # ═══════════════════════════════════════════════════════════ class Listener(Stub): """SipSession.Listener — SIP 会话监听器""" def __init__(self): super().__init__() def onCalling(self, session: "SipSession"): """呼叫中回调""" pass def onRinging(self, session: "SipSession", caller: "SipProfile"): """响铃回调""" pass def onCallEstablished(self, session: "SipSession", sessionDescription: str): """呼叫建立回调""" pass def onCallEnded(self, session: "SipSession"): """呼叫结束回调""" pass def onCallBusy(self, session: "SipSession"): """呼叫忙碌回调""" pass def onError(self, session: "SipSession", errorCode: int, errorMessage: str): """错误回调""" pass def onCallChangeFailed(self, session: "SipSession", errorCode: int, errorMessage: str): """呼叫变更失败回调""" pass def onRegistrationDone(self, session: "SipSession", duration: int): """注册成功回调""" pass def onRegistrationFailed( self, session: "SipSession", errorCode: int, errorMessage: str ): """注册失败回调""" pass def onRegistrationTimeout(self, session: "SipSession"): """注册超时回调""" pass def toString(self) -> str: return f"SipSession.Listener@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF def toString(self) -> str: return f"SipSession(state={self._state})" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF # ═══════════════════════════════════════════════════════════════ # SipAudioCall # ═══════════════════════════════════════════════════════════════ class SipAudioCall(Stub): """SipAudioCall — SIP 音频呼叫""" def __init__(self, context: Any = None, localProfile: "SipProfile" = None): super().__init__() self._context = context self._local_profile = localProfile self._listener: Optional["SipAudioCall.Listener"] = None self._muted = False self._holding = False self._in_call = False def setListener(self, listener: "SipAudioCall.Listener"): """设置音频呼叫监听器""" self._listener = listener def startAudio(self): """开始音频""" raise AndroidOnlyError("SipAudioCall.startAudio() 仅在 Android 设备上可用") def stopAudio(self): """停止音频""" raise AndroidOnlyError("SipAudioCall.stopAudio() 仅在 Android 设备上可用") def close(self): """关闭音频呼叫""" self._in_call = False self._holding = False def isMuted(self) -> bool: return self._muted def toggleMute(self): """切换静音""" self._muted = not self._muted def hold(self, hold: int): """保持呼叫""" self._holding = (hold != 0) def continueCall(self, sessionDescription: int): """继续呼叫""" raise AndroidOnlyError("SipAudioCall.continueCall() 仅在 Android 设备上可用") def makeCall( self, localProfile: "SipProfile", peerProfile: "SipProfile", timeout: int ): """发起呼叫""" raise AndroidOnlyError("SipAudioCall.makeCall() 仅在 Android 设备上可用") def answerCall(self, sessionDescription: int): """接听呼叫""" raise AndroidOnlyError("SipAudioCall.answerCall() 仅在 Android 设备上可用") def sendDtmf(self, code: int): """发送 DTMF""" pass # ═══════════════════════════════════════════════════════════ # Listener # ═══════════════════════════════════════════════════════════ class Listener(Stub): """SipAudioCall.Listener — 音频呼叫监听器""" def __init__(self): super().__init__() def onReadyToCall(self, call: "SipAudioCall"): """准备呼叫回调""" pass def onCallEstablished(self, call: "SipAudioCall", sessionDescription: str): """呼叫建立回调""" pass def onCallEnded(self, call: "SipAudioCall"): """呼叫结束回调""" pass def onCallHeld(self, call: "SipAudioCall"): """呼叫保持回调""" pass def onCallChanged(self, call: "SipAudioCall"): """呼叫变更回调""" pass def onError(self, call: "SipAudioCall", errorCode: int, errorMessage: str): """错误回调""" pass def onRingingBack(self, call: "SipAudioCall"): """回铃回调""" pass def onRinging(self, call: "SipAudioCall", caller: "SipProfile"): """响铃回调""" pass def toString(self) -> str: return f"SipAudioCall.Listener@{hex(id(self))}" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF def toString(self) -> str: return f"SipAudioCall(inCall={self._in_call})" def equals(self, other) -> bool: return self is other def hashCode(self) -> int: return id(self) & 0x7FFFFFFF