Android Upgrades, Custom ROMs (LineageOS), & Kernels

Automating Factory Image Flashes: Scripting ADB Sideload for Multiple Android Devices

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction: Streamlining Android Device Management with ADB Sideload Scripting

Managing and updating multiple Android devices can be a time-consuming and repetitive task, especially when dealing with custom ROMs, official OTA update packages, or specific firmware updates. Manually navigating each device through recovery mode and initiating ADB sideload commands is inefficient and prone to errors. This article provides an expert-level guide on how to automate the ADB sideload process, allowing you to efficiently flash update packages to several Android devices simultaneously or in sequence.

It’s important to clarify a common point of confusion: ‘factory images’ typically refer to complete device firmwares (bootloader, radio, system, vendor, etc.) that are flashed using Fastboot commands (e.g., via a flash-all.sh script). In contrast, adb sideload is specifically designed for flashing signed update packages (.zip files) from a custom or stock recovery. These packages often contain OTA updates, custom ROMs like LineageOS, GApps, or other flashable zips. This guide focuses on automating the process for these .zip update packages via adb sideload.

Prerequisites for Automated Sideloading

Before diving into scripting, ensure you have the following:

  • Android SDK Platform-Tools: This includes ADB (Android Debug Bridge) and Fastboot. Ensure they are installed and accessible in your system’s PATH.
  • Device Drivers: Proper USB drivers for your Android devices installed on your computer.
  • USB Cables: Reliable USB cables for all devices.
  • Update Packages: The specific .zip update files you intend to flash (e.g., LineageOS ROMs, GApps packages, official OTA update zips). Ensure these files are correctly signed for your device’s recovery or that you are using a custom recovery like TWRP.
  • Multiple Android Devices: All devices should have USB debugging enabled and be authorized for ADB connections.
  • Basic Shell Scripting Knowledge: Familiarity with Bash (Linux/macOS) or Batch (Windows) scripting will be helpful.

Understanding ADB Sideload and Recovery Mode

adb sideload is a feature within Android’s recovery environment that allows users to push and install a .zip update package directly from a connected computer via ADB. When a device is in recovery mode and the ‘Apply update from ADB’ option is selected, it listens for an ADB sideload command.

The Manual Sideload Process (Single Device)

  1. Enable USB Debugging on your Android device.
  2. Connect the device to your computer via USB.
  3. Open a terminal/command prompt and verify ADB connection:
    adb devices

    You should see your device listed.

  4. Reboot the device into recovery mode. This often involves a specific key combination during boot (e.g., Power + Volume Down) or via ADB:
    adb reboot recovery

  5. Once in recovery, navigate to ‘Apply update from ADB’ (this might be under ‘Advanced’ or ‘Install’).
  6. On your computer, execute the sideload command:
    adb sideload /path/to/your_update_package.zip

  7. Wait for the process to complete, then reboot the device from recovery.

Scripting for Multiple Devices: The Sequential Approach

Automating sideload for multiple devices typically involves a sequential process. While concurrent flashing might seem appealing, it adds significant complexity in managing device states, potential conflicts, and error handling. A sequential approach ensures each device is properly processed before moving to the next, simplifying debugging and reliability.

Identifying Connected Devices

The first step in any multi-device ADB script is to identify all connected devices. The adb devices -l command is invaluable as it lists devices along with their unique serial numbers and connection types.

Automated Sideload Bash Script Example

Below is a Bash script designed to automate the sideloading of a single .zip file to multiple connected Android devices. This script assumes all devices will receive the same update package. Adapt the UPDATE_ZIP variable to your specific file.

#!/bin/bash

# Configuration
UPDATE_ZIP="./lineage-18.1-20211027-nightly-dumpling-signed.zip" # Path to your update .zip file
WAIT_TIME_ADB_MODE=10 # Time to wait for device in ADB mode (seconds)
WAIT_TIME_RECOVERY_MODE=30 # Time to wait for device in recovery mode (seconds)

echo "Starting automated ADB sideload process..."
echo "Update package: ${UPDATE_ZIP}"

if [ ! -f "${UPDATE_ZIP}" ]; then
echo "Error: Update package not found at ${UPDATE_ZIP}"
exit 1
fi

# Get a list of connected devices
DEVICES=($(adb devices | grep -E 'device|sideload' | awk '{print $1}' | sort -u))

if [ ${#DEVICES[@]} -eq 0 ]; then
echo "No Android devices found. Please connect devices and ensure ADB debugging is enabled."
exit 1
fi

echo "Found ${#DEVICES[@]} device(s): ${DEVICES[@]}"

for SERIAL in "${DEVICES[@]}"; do
echo "
Processing device: ${SERIAL}"

# Check current device state
DEVICE_STATE=$(adb -s "$SERIAL" get-state)
echo "Current state of ${SERIAL}: ${DEVICE_STATE}"

if [ "${DEVICE_STATE}" == "device" ]; then
echo "Rebooting device ${SERIAL} into recovery..."
adb -s "$SERIAL" reboot recovery

# Wait for the device to enter recovery and ADB sideload mode
echo "Waiting for device ${SERIAL} to enter sideload mode (up to ${WAIT_TIME_RECOVERY_MODE}s)..."

# A loop to check device state until it's 'sideload' or timeout
ELAPSED_TIME=0
until [[ $(adb devices | grep "${SERIAL}") =~ "sideload" ]] || [ ${ELAPSED_TIME} -ge ${WAIT_TIME_RECOVERY_MODE} ]; do
sleep 5
ELAPSED_TIME=$((ELAPSED_TIME + 5))
echo "Still waiting for ${SERIAL} in sideload mode... (${ELAPSED_TIME}s)"
done

if [[ $(adb devices | grep "${SERIAL}") =~ "sideload" ]]; then
echo "Device ${SERIAL} is in sideload mode."
else
echo "Error: Device ${SERIAL} did not enter sideload mode within ${WAIT_TIME_RECOVERY_MODE} seconds. Skipping."
continue
fi

elif [ "${DEVICE_STATE}" == "sideload" ]; then
echo "Device ${SERIAL} is already in sideload mode. Proceeding."
else
echo "Error: Device ${SERIAL} is in an unexpected state (${DEVICE_STATE}). Please check manually. Skipping."
continue
fi

# Perform sideload
echo "Sideloading ${UPDATE_ZIP} to ${SERIAL}..."
if adb -s "$SERIAL" sideload "${UPDATE_ZIP}"; then
echo "Sideload successful for ${SERIAL}."
echo "Rebooting device ${SERIAL}..."
adb -s "$SERIAL" reboot
echo "Waiting for ${SERIAL} to boot up (up to ${WAIT_TIME_ADB_MODE}s)..."
adb -s "$SERIAL" wait-for-device
echo "Device ${SERIAL} has booted."
else
echo "Error: Sideload failed for ${SERIAL}. Please check output above."
echo "Attempting to reboot device ${SERIAL} anyway..."
adb -s "$SERIAL" reboot || true # Try to reboot even if previous command failed
fi

echo "Finished processing device: ${SERIAL}"
echo "------------------------------------"
sleep 5 # Give a small pause before the next device

done

echo "Automated sideload process completed for all detected devices."

Key Script Components Explained

  • UPDATE_ZIP: Defines the path to your update package. Ensure it’s correct.
  • `adb devices | grep -E ‘device|sideload’ | awk ‘{print $1}’ | sort -u`: This robust command extracts unique serial numbers of devices that are either in ‘device’ state (normal operation) or ‘sideload’ state (waiting for sideload).
  • `adb -s “$SERIAL” `: The -s flag is crucial for targeting specific devices by their serial number, preventing commands from being sent to unintended devices when multiple are connected.
  • `adb -s “$SERIAL” reboot recovery`: Reboots the targeted device directly into recovery mode.
  • Waiting for Sideload Mode: The script includes a loop that repeatedly checks adb devices output for the device to transition into ‘sideload’ state. This is essential because it takes time for a device to boot into recovery and then for the user (or a script) to select the ‘Apply update from ADB’ option. For fully automated scenarios, some custom recoveries (like TWRP) can be configured to automatically enter sideload mode, or you might need a mechanism to interact with the recovery menu. For stock recovery, manual intervention to select ‘Apply update from ADB’ is usually required after the reboot command, which the script waits for.
  • `adb -s “$SERIAL” sideload “${UPDATE_ZIP}”`: Executes the actual sideload command, pushing the specified ZIP file to the device.
  • Error Handling and Reboot: The script checks the exit status of the sideload command. If successful, it reboots the device into the system. If it fails, it logs an error and attempts a reboot to prevent the device from being stuck in recovery.
  • `adb -s “$SERIAL” wait-for-device`: A powerful ADB command that pauses the script until the specified device is detected as fully connected and online. This is useful after a reboot.

Advanced Scripting Considerations

1. Error Handling and Logging

For production environments or large batches, robust error handling is vital. You can redirect the script’s output to a log file:

./sideload_script.sh > sideload_log_$(date +%Y%m%d_%H%M%S).log 2>&1

Within the script, you could use `set -e` to exit immediately on non-zero command exit codes or add more specific `if` checks around each critical ADB command.

2. Handling Different Update Files

If you need to flash different .zip files to different devices, you can extend the script by maintaining an associative array or a configuration file that maps device serial numbers to their respective update packages.

declare -A DEVICE_UPDATES
DEVICE_UPDATES["SERIAL12345"]="./update_for_device_A.zip"
DEVICE_UPDATES["SERIAL67890"]="./update_for_device_B.zip"

# Inside the loop:
UPDATE_ZIP=${DEVICE_UPDATES[$SERIAL]}
if [ -z "$UPDATE_ZIP" ]; then
echo "No specific update found for ${SERIAL}. Skipping."
continue
fi

3. User Interaction and Confirmation

For safety, especially when flashing custom ROMs, you might want to add prompts for user confirmation before proceeding with each device’s flash.

read -p "Proceed with sideload for ${SERIAL}? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
echo "Skipping device ${SERIAL}."
continue
fi

4. Windows Batch Script Equivalent

For Windows users, a similar script can be created using batch commands, though error handling and looping constructs are somewhat different. The core ADB commands remain the same.

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

REM Configuration
SET UPDATE_ZIP=lineage-18.1-20211027-nightly-dumpling-signed.zip
SET WAIT_TIME_ADB_MODE=10
SET WAIT_TIME_RECOVERY_MODE=30

echo Starting automated ADB sideload process...
echo Update package: %UPDATE_ZIP%

IF NOT EXIST "%UPDATE_ZIP%" (
echo Error: Update package not found at %UPDATE_ZIP%
GOTO :EOF
)

REM Get a list of connected devices
adb devices | findstr /R "device sideload" > devices.tmp

SET DEVICE_COUNT=0
FOR /F "tokens=1" %%A IN (devices.tmp) DO (
SET /A DEVICE_COUNT=!DEVICE_COUNT! + 1
SET "DEVICE_SERIAL[!DEVICE_COUNT!]=%%A"
)
DEL devices.tmp

IF %DEVICE_COUNT% EQU 0 (
echo No Android devices found. Please connect devices and ensure ADB debugging is enabled.
GOTO :EOF
)

echo Found %DEVICE_COUNT% device(s).

FOR /L %%i IN (1,1,%DEVICE_COUNT%) DO (
SET "SERIAL=!DEVICE_SERIAL[%%i]!"
echo(
echo Processing device: !SERIAL!

REM Check current device state
FOR /F "tokens=*" %%S IN ('adb -s !SERIAL! get-state') DO (SET DEVICE_STATE=%%S)
echo Current state of !SERIAL!: !DEVICE_STATE!

IF "!DEVICE_STATE!" == "device" (
echo Rebooting device !SERIAL! into recovery...
adb -s !SERIAL! reboot recovery

REM Wait for the device to enter sideload mode
echo Waiting for device !SERIAL! to enter sideload mode (up to %WAIT_TIME_RECOVERY_MODE%s)...
SET ELAPSED_TIME=0
:WAIT_SIDELOAD_LOOP
timeout /t 5 /nobreak >NUL
SET /A ELAPSED_TIME=!ELAPSED_TIME! + 5

adb devices | findstr /C:"!SERIAL!" | findstr /C:"sideload" >NUL
IF %ERRORLEVEL% EQU 0 (
echo Device !SERIAL! is in sideload mode.
) ELSE IF !ELAPSED_TIME! LSS %WAIT_TIME_RECOVERY_MODE% (
echo Still waiting for !SERIAL! in sideload mode... (!ELAPSED_TIME!s)
GOTO WAIT_SIDELOAD_LOOP
) ELSE (
echo Error: Device !SERIAL! did not enter sideload mode within %WAIT_TIME_RECOVERY_MODE% seconds. Skipping.
GOTO :NEXT_DEVICE
)

) ELSE IF "!DEVICE_STATE!" == "sideload" (
echo Device !SERIAL! is already in sideload mode. Proceeding.
) ELSE (
echo Error: Device !SERIAL! is in an unexpected state (!DEVICE_STATE!). Please check manually. Skipping.
GOTO :NEXT_DEVICE
)

REM Perform sideload
echo Sideloading %UPDATE_ZIP% to !SERIAL!...
adb -s !SERIAL! sideload "%UPDATE_ZIP%"
IF %ERRORLEVEL% EQU 0 (
echo Sideload successful for !SERIAL!.
echo Rebooting device !SERIAL!...
adb -s !SERIAL! reboot
echo Waiting for !SERIAL! to boot up (up to %WAIT_TIME_ADB_MODE%s)...
adb -s !SERIAL! wait-for-device
echo Device !SERIAL! has booted.
) ELSE (
echo Error: Sideload failed for !SERIAL!. Please check output above.
echo Attempting to reboot device !SERIAL! anyway...
adb -s !SERIAL! reboot
)

echo Finished processing device: !SERIAL!
echo ------------------------------------
timeout /t 5 /nobreak >NUL

:NEXT_DEVICE
)

echo Automated sideload process completed for all detected devices.
ENDLOCAL

Conclusion

Automating the ADB sideload process significantly reduces the effort and potential for human error when updating multiple Android devices. By leveraging simple shell scripts, you can streamline your workflow for flashing custom ROMs, OTA updates, or other update packages. Remember to always use reliable USB cables, ensure proper drivers are installed, and verify your update packages before beginning. With these scripts, you gain a powerful tool for efficient Android fleet management.

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner