Created
September 28, 2012 00:47
-
-
Save mrenouf/3797328 to your computer and use it in GitHub Desktop.
An adb convenience wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# Handles call to adb and prompts for device selection if | |
# necessary when more than once device is connected. | |
# | |
# by Mark Renouf <[email protected]> | |
# To install: | |
# 1. Place this script somewhere in your path, and make it executable. | |
# 2. Make sure 'adb' is also in your path. | |
# 3. Run 'adb-wrapper.py' as you would in place of 'adb'. | |
# 3. (Optional) Run 'adb-wrapper.py --wrap' to make 'adb' invoke this script. | |
import os; | |
import subprocess; | |
import re; | |
from stat import S_IXUSR, S_IXGRP, S_IXOTH; | |
import shutil; | |
import sys; | |
def get_devices(adb='adb.real'): | |
args = ['adb.real', 'devices'] | |
devices = subprocess.check_output(args) | |
lines = devices.strip().splitlines() | |
devices = {} | |
for line in lines[1:]: | |
(serial, type) = line.split('\t') | |
devices[serial] = type | |
return devices | |
def get_props(device_serial, adb='adb.real'): | |
args = ['adb.real', '-s', device_serial, 'shell', 'cat', '/system/build.prop'] | |
out = subprocess.check_output(args) | |
props = {} | |
for line in out.splitlines(): | |
line = line.strip() | |
if line.startswith("#") or line == "": continue | |
(key, value) = line.split("=", 1) | |
props[key] = value.strip() | |
return props | |
def device_label(props): | |
manufacturer_model = "%s %s" % ( | |
props['ro.product.manufacturer'].title(), | |
props['ro.product.model']) | |
return "%-25s [%s]" % (manufacturer_model[:25], props['ro.build.description']) | |
def prompt_number(prompt, min, max): | |
sys.stdout.write(prompt) | |
try: | |
choice = int(raw_input()) | |
if choice < min or choice > max: | |
return None | |
return choice | |
except (ValueError): | |
pass | |
except (KeyboardInterrupt): | |
pass | |
except (EOFError): | |
pass | |
return None | |
def prompt_yes_no(prompt): | |
sys.stdout.write(prompt) | |
try: | |
matched = re.match('^[Yy](es)?', raw_input()) | |
if matched is not None: | |
return True | |
except (ValueError): | |
pass | |
except (KeyboardInterrupt): | |
pass | |
except (EOFError): | |
pass | |
return False | |
def do_install(self_path, self_name): | |
adb_name = 'adb' | |
bin_name = 'adb.real' | |
target_path = subprocess.check_output(['which', adb_name]).strip() | |
target_dir = os.path.dirname(target_path) | |
self_target = os.path.join(target_dir, self_name) | |
target_real = os.path.join(target_dir, bin_name) | |
symlink_path = os.path.join(target_dir, adb_name) | |
print 'Installing as %s' % (target_path) | |
if prompt_yes_no('Continue? [y/N]?'): | |
print "renaming %s => %s" % (target_path, 'adb.real') | |
shutil.move(target_path, target_real) | |
print "copying %s => %s" % (self_path, self_target) | |
shutil.copyfile(self_path, self_target) | |
fstat = os.stat(self_target) | |
os.chmod(self_target, fstat.st_mode | S_IXUSR | S_IXGRP | S_IXOTH) | |
print "create symlink adb => %s" % (self_target) | |
os.symlink(self_name, symlink_path) | |
target_flags = { '-d', '-e', '-s', '-p'} | |
device_commands = {'connect', 'disconnect', 'push', 'pull', 'sync', | |
'shell', 'logcat', 'forward', 'jdwp', 'install', 'uninstall', | |
'bugreport', 'backup', 'restore', 'get-state', 'get-serialno', | |
'remount', 'reboot', 'reboot-bootloader', 'root', 'tcpip', 'ppp'} | |
def main(args): | |
self_path = os.path.normpath(args[0]) | |
self_name = os.path.basename(self_path) | |
self_dir = os.path.dirname(self_path) | |
if self_name != 'adb' and len(args) > 1 and args[1] == '--wrap': | |
do_install(self_path, self_name) | |
else: | |
if self_name == 'adb': | |
args[0] = os.path.join(self_dir, 'adb.real') | |
else: | |
args[0] = 'adb' | |
if len(args) > 1: | |
first_arg = args[1] | |
# see if the command would work without a serial number | |
# or if possibly a serial number was already supplied | |
if (first_arg not in target_flags) and first_arg in device_commands: | |
devices = get_devices() | |
if len(devices) > 1: | |
i = 1 | |
serials = devices.keys() | |
for device_serial in serials: | |
device_type = 'device' | |
if device_serial.startswith('emulator'): | |
device_type = 'emulator' | |
print "[%3d] [%8s] %s" % (i, device_type, device_label(get_props(device_serial, args[0]))) | |
i = i + 1 | |
selection = prompt_number("device? ", 1, len(serials)) | |
if selection is None: | |
print 'Cancelled!' | |
sys.exit(1) | |
device_serial = serials[selection - 1] | |
args.insert(1, '-s') | |
args.insert(2, device_serial) | |
try: | |
subprocess.call(args) | |
except: | |
pass | |
if __name__ == "__main__": | |
main(sys.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment