JeffLIrion / adb_shell

A Python implementation of ADB with shell and FileSync functionality.
Apache License 2.0
530 stars 60 forks source link

Some Features Implementation #187

Closed enty8080 closed 3 years ago

enty8080 commented 3 years ago

Hello adb_shell developers,

I would like to ask about adding interactive shell to adb_shell project. I think it will be good for people who does not want to send commands manually through device.shell().

device.interact()

result:

android@localhost # pwd
/sdcard
android@localhost #
device.install('/path/to/apk')
# device.uninstall('bundle identifier')
device.reboot()

Regards, Ivan Nikolsky (@enty8080)

P.S. I am using your python package and it is very good :), so it will be good to see this features.

JeffLIrion commented 3 years ago
  1. Wouldn't that just be a wrapper around shell() calls?
    while True:
       command = input("adb # ")
       if command == "exit":
           break
       resp = device.shell(command)
       if resp:
           print(resp)
  2. Those are just shell commands. The install command is (link): pm install -r /sdcard/Download/something.apk
  3. I think that's just device.shell("reboot").
enty8080 commented 3 years ago

1. Okay, but interactive shell is not just a wrapper, its a wrapper, but with some extra functions:

https://github.com/google/python-adb/blob/f4e597fe55900651a8a91fccc1e09061fd96b5e9/adb/adb_protocol.py#L443

2. Okay, I read about it.

3. No, reboot is not a shell command:

https://github.com/google/python-adb/blob/f4e597fe55900651a8a91fccc1e09061fd96b5e9/adb/adb_commands.py#L345

JeffLIrion commented 3 years ago

This should accomplish reboot:

device._open(b'reboot:', transport_timeout_s, read_timeout_s, timeout_s)

Can you please confirm that it works.

enty8080 commented 3 years ago

@JeffLIrion Sorry for late response. Yes, it works fine for me, thank you.

JeffLIrion commented 3 years ago

OK, I'll merge the corresponding pull request.

I don't intend to implement items 1 and 2, as the scope of this package is to implement the ADB protocol, not to provide utilities and helper functions. I don't want to clutter the AdbDevice and AdbDeviceAsync classes. That said, I think the following approach would be reasonable, if you'd like to contribute it.

  1. Implement an AdbDeviceUtils class that looks like:

    class AdbDeviceUtils:
       def __init__(self, adb_device):
           self._adb_device = adb_device
    
       def install(self, apk, ...):
           self._adb_device.shell("<install command>", ...)
  2. Add a property to the AdbDevice class:
    @property
    def utils(self):
       return AdbDeviceUtils(self)

Then you could do device.utils.install(...).

And do the same for the AdbDeviceAsync class.