from collections import namedtuple
from rpcclient.exceptions import RpcFailedLaunchingAppError
ScreenLockStatus = namedtuple('ScreenLockStatus', ['lock', 'passcode'])
[docs]
class SpringBoard:
def __init__(self, client):
self._client = client
[docs]
def get_spring_board_server_port(self) -> int:
return self._client.symbols.SBSSpringBoardServerPort()
[docs]
def launch_application(self, bundle_identifier: str) -> None:
""" launch application using SpringBoardServices """
err = self._client.symbols.SBSLaunchApplicationWithIdentifier(self._client.cf(bundle_identifier), 0)
if err != 0:
raise RpcFailedLaunchingAppError(
f'SBSLaunchApplicationWithIdentifier failed with: error code {err} - '
f'{self._client.symbols.SBSApplicationLaunchingErrorString(err).py()}')
[docs]
def get_screen_lock_status(self) -> ScreenLockStatus:
""" get lockscreen and passcode status using SpringBoardServices """
server_port = self.get_spring_board_server_port()
with self._client.safe_malloc(8) as p_is_lock:
with self._client.safe_malloc(8) as p_is_passcode:
p_is_lock[0] = 0
p_is_passcode[0] = 0
self._client.symbols.SBGetScreenLockStatus(server_port, p_is_lock, p_is_passcode)
return ScreenLockStatus(p_is_lock[0] == 1, p_is_passcode[0] == 1)
[docs]
def open_sensitive_url_and_unlock(self, url: str, unlock: bool = True) -> None:
""" open default application according to url scheme """
screen_lock_status = self.get_screen_lock_status()
if not unlock and screen_lock_status.lock:
if screen_lock_status.passcode:
raise RpcFailedLaunchingAppError(
'cannot open url while screen is locked with passcode. you must unlock device first')
raise RpcFailedLaunchingAppError('cannot open url while screen is locked, use unlock=True parameter')
cf_url_ref = self._client.objc_get_class('NSURL').URLWithString_(self._client.cf(url))
if not self._client.symbols.SBSOpenSensitiveURLAndUnlock(cf_url_ref, unlock):
raise RpcFailedLaunchingAppError('SBSOpenSensitiveURLAndUnlock failed')