From ceec14c98dc08d1232a4b62c0b2891d57df5df57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Woirhaye?= Date: Mon, 25 Aug 2025 21:02:29 +0200 Subject: [PATCH] feat: Add install_multi_package in android_device and adb client --- examples/install_apks.py | 27 ++++++++++++++++++++ src/android_device_manager/adb/client.py | 21 +++++++++++++++ src/android_device_manager/android_device.py | 15 +++++++++++ 3 files changed, 63 insertions(+) create mode 100644 examples/install_apks.py diff --git a/examples/install_apks.py b/examples/install_apks.py new file mode 100644 index 0000000..ffe6cc2 --- /dev/null +++ b/examples/install_apks.py @@ -0,0 +1,27 @@ +from android_device_manager import AndroidDevice +from android_device_manager.avd import AVDConfiguration +from android_device_manager.emulator import EmulatorConfiguration + +# Configure your AVD +avd_config = AVDConfiguration( + name="example_avd", + package="system-images;android-36;google_apis;x86_64" +) + +# Configure your Emulator +emulator_config = EmulatorConfiguration( + no_window=False +) + +with AndroidDevice(avd_config,emulator_config) as device: + # Install APK + device.install_multi_package([ + "/home/jwoirhay/Bureau/temp/apk_download/apks/safetravelsmain.apk", + "/home/jwoirhay/Bureau/temp/apk_download/apks/sitiosarequipa.apk" + ]) + + # List installed packages + packages = device.list_installed_packages() + print("Installed packages:") + for p in packages: + print(f"\t- {p}") diff --git a/src/android_device_manager/adb/client.py b/src/android_device_manager/adb/client.py index 5035ba7..ba632d7 100644 --- a/src/android_device_manager/adb/client.py +++ b/src/android_device_manager/adb/client.py @@ -178,6 +178,27 @@ def install_apk(self, apk_path: str, timeout: int = 60): except ADBError as e: raise ADBError(f"Failed to install APK {apk_path}: {str(e)}") + def install_multi_package(self, apk_paths: list[str], timeout: int = 120): + """ + Install multiple APKs in a single transaction using 'adb install-multi-package'. + + Args: + apk_paths (list[str]): List of APK file paths on the host. + timeout (int): Timeout in seconds for the installation. + + Raises: + ADBError: If the installation fails. + """ + if not apk_paths: + raise ADBError("No APKs provided for installation.") + + try: + args = ["install-multi-package", *apk_paths] + self._run_adb_command(args, check=True, timeout=timeout) + logger.info(f"Successfully installed APKs {apk_paths} on {self._serial}") + except ADBError as e: + raise ADBError(f"Failed to install APKs {apk_paths}: {str(e)}") + def uninstall_package( self, package_name: str, keep_data: bool = False, timeout: int = 60 ) -> None: diff --git a/src/android_device_manager/android_device.py b/src/android_device_manager/android_device.py index 67ade56..a56287e 100644 --- a/src/android_device_manager/android_device.py +++ b/src/android_device_manager/android_device.py @@ -278,6 +278,21 @@ def install_apk(self, apk_path: str, timeout: int = 30) -> None: self._ensure_running() self._adb_client.install_apk(apk_path, timeout=timeout) + def install_multi_package(self, apk_paths: list[str], timeout: int = 60) -> None: + """ + Install multiple APKs on the device in a single transaction. + + Args: + apk_paths (list[str]): A list of file paths to the APKs. + timeout (int): Timeout in seconds for the installation process (default: 60). + + Raises: + AndroidDeviceError: If the device is not running or the ADB client is not initialized. + ADBError: If the command fails. + """ + self._ensure_running() + self._adb_client.install_multi_package(apk_paths, timeout=timeout) + def uninstall_package(self, package_name: str, keep_data: bool = False) -> None: """ Uninstall a package from the device.