from __future__ import print_function import os import os.path import shutil import subprocess import sys import platform # # Run script from command line ## Debian Linux / WSL ### python3 install_minimum_android_sdk_prerequisites.py ## ## Windows ### python install_minimum_android_sdk_prerequisites.py # SUPPORTED_PYTHON_PLATFORMS = ['Windows', 'Linux', 'Darwin'] # Version numbers, SHA256 and URLs taken from ## https://developer.android.com/studio ANDROID_SDK_TOOLS_VERSION = '11076708' ANDROID_SDK_TOOLS_SHASUM_LINUX = '2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258' ANDROID_SDK_TOOLS_SHASUM_WINDOWS = '4d6931209eebb1bfb7c7e8b240a6a3cb3ab24479ea294f3539429574b1eec862' ANDROID_SDK_VERSION = '36' def fail(message, *args, **kwargs): print((message % args).format(**kwargs)) sys.exit(1) def which_raw(program): import os def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None def which(program): if (sys.platform == 'win32'): which_result = which_raw(program + ".bat") if not which_result: which_result = which_raw(program + ".cmd") if not which_result: which_result = which_raw(program + ".exe") return which_result else: return which_raw(program) def change_permissions_recursive(path, mode): import os for root, dirs, files in os.walk(path, topdown=False): for dir in [os.path.join(root,d) for d in dirs]: os.chmod(dir, mode) for file in [os.path.join(root, f) for f in files]: os.chmod(file, mode) def install_sdk_tools(): import os import tarfile import zipfile import hashlib if sys.version_info[0] >= 3: from urllib.request import urlretrieve else: from urllib import urlretrieve if not os.path.isdir(prerequisite_tools_dir): os.makedirs(prerequisite_tools_dir) zip_fullfn = prerequisite_tools_dir + os.path.sep + 'sdk-tools.zip'; if sys.platform == 'win32': url = 'https://dl.google.com/android/repository/commandlinetools-win-' + ANDROID_SDK_TOOLS_VERSION + '_latest.zip' expected_shasum = ANDROID_SDK_TOOLS_SHASUM_WINDOWS else: url = 'https://dl.google.com/android/repository/commandlinetools-linux-' + ANDROID_SDK_TOOLS_VERSION + '_latest.zip' expected_shasum = ANDROID_SDK_TOOLS_SHASUM_LINUX # Download sdk-tools. url_base_name = os.path.basename(url) if not os.path.isfile(zip_fullfn): print('Downloading sdk-tools to:', zip_fullfn) zip_fullfn = urlretrieve(url, zip_fullfn)[0] print('Downloaded sdk-tools to:', zip_fullfn) # Verify SHA-1 checksum of downloaded files. with open(zip_fullfn, 'rb') as f: contents = f.read() found_shasum = hashlib.sha256(contents).hexdigest() print("SHA-256:", zip_fullfn, "%s" % found_shasum) if found_shasum != expected_shasum: fail('Error: SHA-256 checksum ' + found_shasum + ' of downloaded file does not match expected checksum ' + expected_shasum) print("[ok] Checksum of", zip_fullfn, "matches expected value.") # Proceed with extraction of the SDK if necessary. sdk_tools_path = prerequisite_tools_dir + os.path.sep + 'cmdline-tools' if not os.path.isfile(sdk_tools_path + os.path.sep + "source.properties"): print("Extracting sdk-tools ...") # This will go to a subfolder "tools" in the current path. file_name, file_extension = os.path.splitext(url_base_name) zip = zipfile.ZipFile(zip_fullfn, 'r') zip.extractall(prerequisite_tools_dir) zip.close() # Move contents of cmdline-tools one level deeper into cmdline-tools/latest sdk_tools_latest_path = sdk_tools_path + os.path.sep + 'latest' if os.path.isdir(sdk_tools_latest_path): shutil.rmtree(sdk_tools_latest_path) os.makedirs(sdk_tools_latest_path) shutil.move(sdk_tools_path + os.path.sep + 'NOTICE.txt', sdk_tools_latest_path) shutil.move(sdk_tools_path + os.path.sep + 'source.properties', sdk_tools_latest_path) shutil.move(sdk_tools_path + os.path.sep + 'bin', sdk_tools_latest_path) shutil.move(sdk_tools_path + os.path.sep + 'lib', sdk_tools_latest_path) # Linux only - Set executable permission on files. if platform.system() == 'Linux': print("Setting permissions on sdk-tools executables ...") change_permissions_recursive(sdk_tools_path, 0o755); # Add tools/bin to PATH. sdk_tools_bin_path = sdk_tools_latest_path + os.path.sep + 'bin' print('Adding to PATH:', sdk_tools_bin_path) os.environ["PATH"] += os.pathsep + sdk_tools_bin_path os.environ["ANDROID_HOME"] = os.path.realpath(prerequisite_tools_dir) os.environ["ANDROID_SDK_ROOT"] = os.path.realpath(prerequisite_tools_dir) # # SCRIPT MAIN. # if platform.system() not in SUPPORTED_PYTHON_PLATFORMS: fail('Unsupported python platform %s. Supported platforms: %s', platform.system(), ', '.join(SUPPORTED_PYTHON_PLATFORMS)) prerequisite_tools_dir = os.path.dirname(os.path.realpath(__file__)) + os.path.sep + ".." + os.path.sep + ".." + os.path.sep + "syncthing-android-prereq" # Check if "sdk-manager" of sdk-tools package is available. sdk_manager_bin = which("sdkmanager") if not sdk_manager_bin: print('Warning: sdkmanager from sdk-tools package is not available on PATH.') install_sdk_tools(); # Retry. sdk_manager_bin = which("sdkmanager") if not sdk_manager_bin: fail('Error: sdkmanager from sdk-tools package is not available on PATH.') print('sdk_manager_bin=\'' + sdk_manager_bin + '\'') # # Update SDK repository. print('[INFO] sdk_manager_bin --update') subprocess.check_call([sdk_manager_bin, '--update']) # # Auto accept all sdkmanager licenses. if sys.platform == 'win32': powershell_bin = which('powershell') subprocess.check_call([powershell_bin, 'for($i=0;$i -lt ' + ANDROID_SDK_VERSION + ';$i++) { $response += \"y`n\"}; $response | sdkmanager --licenses'], stdout=subprocess.DEVNULL) else: print('[INFO] sdkmanager --licenses') os.system('yes | sdkmanager --licenses') # print('Done.')