Quickly logs in on an Android device, via adb, using credentials from a CSV file.
Requirements: dialog (terminal) or zenity (GUI) for the UI
Configuration:
.user-passwords.csv
user1,password1
user2,password2
| #!/usr/bin/env python | |
| import csv | |
| import os | |
| import subprocess | |
| USER_PASSWORDS_FILE = '.user-passwords.csv' | |
| def list_connected_devices(): | |
| output = subprocess.check_output(['adb', 'devices']) | |
| for line in output.splitlines()[1:]: # First line is header | |
| if not line: | |
| continue | |
| data = line.split() | |
| yield data[0].decode() | |
| def list_credentials(): | |
| with open(USER_PASSWORDS_FILE, 'r') as fp: | |
| for line in csv.reader(fp): | |
| yield tuple(line) | |
| def _check_command(name): | |
| return subprocess.call( | |
| ['which', name], | |
| stderr=subprocess.DEVNULL, | |
| stdout=subprocess.DEVNULL) == 0 | |
| def _get_prompt_option(): | |
| PROMPT_OPTIONS = [ | |
| ('zenity', True, _prompt_selection_zenity), | |
| ('dialog', False, _prompt_selection_dialog), | |
| ] | |
| UI_AVAILABLE = bool(os.environ.get('DISPLAY')) | |
| for command, require_ui, function in PROMPT_OPTIONS: | |
| if require_ui and not UI_AVAILABLE: | |
| continue | |
| if _check_command(command): | |
| return function | |
| raise ValueError('Could not find any alternative to show dialogs. ' | |
| 'Please install either dialog (for terminal UI) or ' | |
| 'zenity (for graphical UI)') | |
| def prompt_selection(choices, title='Your choice'): | |
| func = _get_prompt_option() | |
| return func(choices, title=title) | |
| def _prompt_selection_dialog(choices, title): | |
| args = [ | |
| 'dialog', '--stdout', '--no-tags', | |
| '--menu', title, '0', '0', '0' | |
| ] | |
| for item in choices: | |
| args += [item, item] | |
| output = subprocess.check_output(args) | |
| return output.splitlines()[0].decode() | |
| def _prompt_selection_zenity(choices, title): | |
| args = [ | |
| 'zenity', '--list', '--hide-header', | |
| '--text', title, | |
| '--print-column', '1', # Label | |
| '--separator', r'\n', | |
| '--column', 'Name', | |
| ] | |
| for item in choices: | |
| args.append(item) | |
| output = subprocess.check_output(args) | |
| return output.splitlines()[0].decode() | |
| if __name__ == '__main__': | |
| device_name = prompt_selection( | |
| sorted(list_connected_devices()), | |
| title='Select device') | |
| passwords = dict(list_credentials()) | |
| user_name = prompt_selection( | |
| sorted(passwords.keys()), | |
| title='Select user credentials') | |
| print('Device: {}'.format(device_name)) | |
| print('User: {}'.format(user_name)) | |
| user_passowrd = passwords[user_name] | |
| command = [ | |
| 'adb', '-s', device_name, 'shell', | |
| 'input', 'text', user_name, ';', | |
| 'input', 'keyevent', 'TAB', ';', | |
| 'input', 'text', user_passowrd, ';', | |
| 'input', 'keyevent', 'ENTER'] | |
| subprocess.check_call(command) |