doronz88 / pymobiledevice3

Pure python3 implementation for working with iDevices (iPhone, etc...).
https://discord.gg/52mZGC3JXJ
GNU General Public License v3.0
1.09k stars 149 forks source link

Cannot use the `set_icon_state` API #993

Closed mykola-mokhnach closed 2 weeks ago

mykola-mokhnach commented 2 weeks ago

Test environment

Describe the bug I am trying to change icons on the phone Home Screen. For that I call the get_icon_state first, modify the resulting array and then pass it back to the set_icon_state API. Unfortunately the latter does not work as expected and always throws an exception about plist parsing failure.

To Reproduce Run the following code

import pprint

from pymobiledevice3.services.springboard import SpringBoardServicesService
from pymobiledevice3.lockdown import create_using_usbmux

def main():
    with create_using_usbmux() as lockdown:
        with SpringBoardServicesService(lockdown=lockdown) as springboard:
            state = springboard.get_icon_state()
            pprint.pprint(state)

            new_state = do_icons_modifications(state)   

            pprint.pprint(new_state)
            springboard.set_icon_state(new_state)

if __name__ == '__main__':
    main()

Expected behavior Icons on the device's Home Screen are modified

Logs If applicable, add logs including backtraces for the given error that help explain your problem.

Additional context it would be nice to have at least some basic documentation on the newstate arg for the SpringBoardServicesService->set_icon_state API

For community

⬇️ Please click the 👍 reaction instead of leaving a +1 or 👍 comment

mykola-mokhnach commented 2 weeks ago

Exception details:

Traceback (most recent call last):
  File "/root/share/virtualenvs/icons-test-gJbEAhrd/lib/python3.9/site-packages/pymobiledevice3/service_connection.py", line 48, in parse_plist
    return plistlib.loads(payload)
  File "/opt/homebrew/Cellar/python@3.9/3.9.18/Frameworks/Python.framework/Versions/3.9/lib/python3.9/plistlib.py", line 883, in loads
    return load(fp, fmt=fmt, dict_type=dict_type)
  File "/opt/homebrew/Cellar/python@3.9/3.9.18/Frameworks/Python.framework/Versions/3.9/lib/python3.9/plistlib.py", line 869, in load
    raise InvalidFileException()
plistlib.InvalidFileException: Invalid file

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/root/code/icons-test/main.py", line 39, in <module>
    main()
  File "/root/code/icons-test/main.py", line 13, in main
    springboard.set_icon_state(state)
  File "/root/share/virtualenvs/icons-test-gJbEAhrd/lib/python3.9/site-packages/pymobiledevice3/services/springboard.py", line 39, in set_icon_state
    self.service.send_recv_plist(cmd)
  File "/root/share/virtualenvs/icons-test-gJbEAhrd/lib/python3.9/site-packages/pymobiledevice3/service_connection.py", line 126, in send_recv_plist
    return self.recv_plist(endianity=endianity)
  File "/root/share/virtualenvs/icons-test-gJbEAhrd/lib/python3.9/site-packages/pymobiledevice3/service_connection.py", line 169, in recv_plist
    return parse_plist(self.recv_prefixed(endianity=endianity))
  File "/root/share/virtualenvs/icons-test-gJbEAhrd/lib/python3.9/site-packages/pymobiledevice3/service_connection.py", line 50, in parse_plist
    raise PyMobileDevice3Exception(f'parse_plist invalid data: {payload[:100].hex()}')
pymobiledevice3.exceptions.PyMobileDevice3Exception: parse_plist invalid data: 
mykola-mokhnach commented 2 weeks ago

also tried to pass {} and [] as newstate, but got exactly the same exception as the above one

doronz88 commented 2 weeks ago

Thanks for the update. Just created a PR to fix that. In general you can just query the current icon state and reorder the icons as you wish. Feel free to submit a PR with documentation improvements

mykola-mokhnach commented 2 weeks ago

Thanks @doronz88

Maybe you know if this API also allows to delete/hide icons or if that would be possible in general using lockdown?

doronz88 commented 2 weeks ago

Haven't tried it myself, but my guess is not. Just play with it. I only wrapped the protocol messages as is