diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index c8f9f7b..e77e8bd 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -58,4 +58,4 @@ jobs: run: uv sync --all-groups - name: Publish documentation - run: uv run mkdocs gh-deploy --force + run: uv run mkdocs gh-deploy --force \ No newline at end of file diff --git a/README.md b/README.md index e9675e7..a788f57 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Android Device Manager Python Android Device Manager is a Python library for creating, launching, and managing Android emulators (AVDs) programmatically. -[![PyPI](https://img.shields.io/pypi/v/python-android-avd-manager?label=PyPI)](https://pypi.org/project/android-device-manager/) +![PyPI - Version](https://img.shields.io/pypi/v/android-device-manager) [![CI](https://github.com/jwoirhaye/android-device-manager-python/actions/workflows/ci.yml/badge.svg)](https://github.com/jwoirhaye/android-device-manager-python/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/jwoirhaye/android-device-manager-python/branch/main/graph/badge.svg)](https://codecov.io/gh/jwoirhaye/android-device-manager-python) [![Docs](https://img.shields.io/badge/docs-mkdocs-blue?logo=readthedocs)](https://jwoirhaye.github.io/android-device-manager-python/) @@ -54,7 +54,7 @@ Android Device Manager is a Python library for creating, launching, and managing ### 📦 From PyPI (Recommended) ```bash -pip install python-android-avd-manager +pip install android-device-manager ``` ### 🚧 From Source diff --git a/docs/examples/apk-management.md b/docs/examples/apk-management.md index d84ea0d..607784a 100644 --- a/docs/examples/apk-management.md +++ b/docs/examples/apk-management.md @@ -18,7 +18,7 @@ emulator_config = EmulatorConfiguration( no_window=True ) -with AndroidDevice(avd_config) as device: +with AndroidDevice(avd_config,emulator_config) as device: # Install APK device.install_apk("/path/to/app.apk") diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index e94d1c9..8080473 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -72,16 +72,16 @@ emulator -version sdkmanager --list_installed ``` -## Install python-android-avd-manager +## Install android-device-manager ### 📦 From PyPI (Recommended) ```bash -pip install python-android-avd-manager +pip install android-device-manager ``` ### 🚧 From Source ```bash -git clone https://github.com/jwoirhaye/python-android-avd-manager-python.git -cd python-android-avd-manager +git clone https://github.com/jwoirhaye/android-device-manager-python.git +cd android-device-manager-python pip install -e . ``` \ No newline at end of file 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/pyproject.toml b/pyproject.toml index d83531e..da613cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,23 @@ maintainers = [ requires-python = ">=3.10" dependencies = [] +readme = { file = "README.md", content-type = "text/markdown" } +license = { file = "LICENSE" } +keywords = [ + "android", "adb", "emulator", "android emulator", "device manager", + "automation", "testing", "devtools", "python" +] +classifiers = [ + "Intended Audience :: Developers", + "Topic :: Software Development", + "Topic :: Utilities", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Typing :: Typed" +] + [project.urls] Homepage = "https://github.com/jwoirhaye/android-device-manager-python" Source = "https://github.com/jwoirhaye/android-device-manager-python" 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.