备份apk 工具

序言

在开发工作中,有时候需要构造高负载环境,需要安装一些大型的游戏应用。比如和平精英。和平精英的安装器有1.9G 但是安装完之后,还需要下载7G左右的内容。每次花费大量时间。写了一个备份apk的工具。

使用

命令

备份内容

每个 .apk_backup 是一个 未压缩 tar 包(大体积备份更快),内含:

apks/ --- 所有 APK 分包

obb/ --- OBB 目录(有数据才包含)

data/ --- /sdcard/Android/data/<包名>/ 内容

package.txt --- 包名(恢复时优先读取)

使用示例

bash 复制代码
app_backup com.tencent.tmgp.pubgmhd
app_backup -restore com.tencent.tmgp.pubgmhd.apk_backup

源文件

app_backup.bat

c 复制代码
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion

where adb >nul 2>nul
if errorlevel 1 (
    echo 错误:未找到 adb 命令,请确保 Android SDK 已安装并配置环境变量。
    pause
    exit /b 1
)

adb get-state >nul 2>nul
if errorlevel 1 (
    echo 错误:未检测到已连接的设备,请连接手机并开启 USB 调试。
    pause
    exit /b 1
)

if "%1"=="" goto :usage
if /i "%1"=="-h" goto :usage
if /i "%1"=="--help" goto :usage
if /i "%1"=="help" goto :usage

if /i "%1"=="-restore" goto :do_restore
if /i "%1"=="-resotre" goto :do_restore

set PACKAGE=%1
call :backup "%PACKAGE%"
goto :eof

:do_restore
if "%2"=="" (
    echo 错误:请指定要恢复的 .apk_backup 文件。
    goto :usage
)
call :restore "%~2"
goto :eof

:usage
echo 用法:
echo   app_backup ^<包名^>                    备份应用(APK + OBB + data)
echo   app_backup -restore ^<文件.apk_backup^>  从备份恢复
echo.
echo 示例:
echo   app_backup com.tencent.tmgp.pubgmhd
echo   app_backup -restore com.tencent.tmgp.pubgmhd.apk_backup
pause
exit /b 0

:backup
set "PACKAGE=%~1"
echo ========================================
echo 正在备份 %PACKAGE%
echo ========================================
echo.

set "TEMP_DIR=%TEMP%\%PACKAGE%_backup_%RANDOM%"
set "SCRIPT_DIR=%~dp0"
set "BACKUP_FILE=%SCRIPT_DIR%%PACKAGE%.apk_backup"

mkdir "%TEMP_DIR%" 2>nul
if not exist "%TEMP_DIR%" (
    echo 错误:无法创建临时目录。
    pause
    exit /b 1
)

cd /d "%TEMP_DIR%"

echo [1/5] 获取 APK 路径...
set APK_COUNT=0
for /f "usebackq tokens=1,* delims=:" %%a in (`adb shell pm path %PACKAGE% 2^>nul`) do (
    if /i "%%a"=="package" (
        set /a APK_COUNT+=1
        set "APK_PATH_!APK_COUNT!=%%b"
    )
)

if !APK_COUNT! equ 0 (
    echo 错误:找不到包 %PACKAGE%,请检查包名或应用是否已安装。
    call :cleanup_temp "%TEMP_DIR%"
    pause
    exit /b 1
)

echo 发现 !APK_COUNT! 个 APK 分包

echo [2/5] 拉取 APK 文件...
mkdir "apks" 2>nul
set IDX=0
for /l %%n in (1,1,!APK_COUNT!) do (
    set /a IDX+=1
    set "SRC=!APK_PATH_%%n!"
    if "!SRC:~0,1!"==" " set "SRC=!SRC:~1!"
    for %%f in ("!SRC!") do set "APK_NAME=%%~nxf"
    echo   拉取 !APK_NAME! ...
    adb pull "!SRC!" "apks\!APK_NAME!"
    if errorlevel 1 (
        echo 错误:拉取 APK 失败:!SRC!
        call :cleanup_temp "%TEMP_DIR%"
        pause
        exit /b 1
    )
)

echo [3/5] 拉取 OBB 目录...
set "OBB_DIR=/sdcard/Android/obb/%PACKAGE%"
adb shell "[ -d '%OBB_DIR%' ] && ls -A '%OBB_DIR%' 2>/dev/null | grep -q . && echo has_files || echo empty" 2>nul | findstr /i "has_files" >nul
if not errorlevel 1 (
    echo   源路径: %OBB_DIR%
    echo   数据较大时请耐心等待...
    adb pull "%OBB_DIR%" "obb"
    if errorlevel 1 (
        echo 警告:拉取 OBB 失败,跳过。
        rmdir /s /q "obb" 2>nul
    ) else (
        echo   OBB 已备份。
    )
) else (
    echo   无 OBB 数据,跳过。
)

echo [4/5] 拉取 data 目录...
set "DATA_DIR=/sdcard/Android/data/%PACKAGE%"
adb shell "[ -d '%DATA_DIR%' ] && ls -A '%DATA_DIR%' 2>/dev/null | grep -q . && echo has_files || echo empty" 2>nul | findstr /i "has_files" >nul
if not errorlevel 1 (
    echo   源路径: %DATA_DIR%
    echo   数据较大时请耐心等待...
    adb pull "%DATA_DIR%" "data"
    if errorlevel 1 (
        echo 警告:拉取 data 失败,跳过。
        rmdir /s /q "data" 2>nul
    ) else (
        echo   data 已备份。
    )
) else (
    echo   无 data 数据,跳过。
)

echo %PACKAGE%> package.txt

echo [5/5] 打包为 %PACKAGE%.apk_backup ...
if exist "%BACKUP_FILE%" del /f /q "%BACKUP_FILE%"
tar -cf "%BACKUP_FILE%" *
if errorlevel 1 (
    echo 错误:打包失败,请确保系统支持 tar 命令(Windows 10 及以上)。
    call :cleanup_temp "%TEMP_DIR%"
    pause
    exit /b 1
)

for %%A in ("%BACKUP_FILE%") do set "BACKUP_SIZE_STR=%%~zA bytes"

call :cleanup_temp "%TEMP_DIR%"

echo.
echo ========================================
echo 备份完成!
echo 文件: !BACKUP_FILE!
echo 大小: !BACKUP_SIZE_STR!
echo ========================================
exit /b 0

:restore
set "BACKUP_FILE=%~f1"
if not exist "%BACKUP_FILE%" (
    echo 错误:找不到备份文件 %BACKUP_FILE%
    pause
    exit /b 1
)

echo ========================================
echo 正在从备份恢复
echo 文件: "!BACKUP_FILE!"
echo ========================================
echo.

set "RESTORE_DIR=%TEMP%\restore_%RANDOM%"
mkdir "%RESTORE_DIR%" 2>nul
cd /d "%RESTORE_DIR%"

echo [1/5] 解压备份...
tar -xf "%BACKUP_FILE%"
if errorlevel 1 (
    echo 错误:解压失败,文件可能损坏。
    call :cleanup_temp "%RESTORE_DIR%"
    pause
    exit /b 1
)

set "PACKAGE="
if exist "package.txt" (
    set /p PACKAGE=<package.txt
)

if "!PACKAGE!"=="" (
    set "FNAME=%~n1"
    if /i "!FNAME:~-11!"==".apk_backup" (
        set "PACKAGE=!FNAME:~0,-11!"
    ) else (
        set "PACKAGE=!FNAME!"
    )
)

if "!PACKAGE!"=="" (
    echo 错误:无法确定包名,请检查备份文件。
    call :cleanup_temp "%RESTORE_DIR%"
    pause
    exit /b 1
)

echo 目标包名:!PACKAGE!
echo.

echo [2/5] 停止应用...
adb shell am force-stop !PACKAGE! 2>nul

echo [3/5] 安装 APK...
set "INSTALL_OK=0"
if exist "apks" (
    set APK_INSTALL_COUNT=0
    for %%f in (apks\*.apk) do set /a APK_INSTALL_COUNT+=1
    if !APK_INSTALL_COUNT! gtr 1 (
        echo   检测到 !APK_INSTALL_COUNT! 个分包,使用 install-multiple...
        set "INSTALL_CMD=adb install-multiple -r -d"
        for %%f in (apks\*.apk) do set "INSTALL_CMD=!INSTALL_CMD! apks\%%~nxf"
        !INSTALL_CMD!
    ) else if exist "apks\base.apk" (
        adb install -r -d "apks\base.apk"
    ) else (
        for %%f in (apks\*.apk) do adb install -r -d "%%f"
    )
    if not errorlevel 1 set "INSTALL_OK=1"
) else if exist "base.apk" (
    adb install -r -d "base.apk"
    if not errorlevel 1 set "INSTALL_OK=1"
) else (
    echo 错误:备份中没有 APK 文件。
    call :cleanup_temp "%RESTORE_DIR%"
    pause
    exit /b 1
)

if "!INSTALL_OK!"=="1" (
    echo   APK 安装成功。
) else (
    echo 警告:APK 安装失败,可能签名冲突。请手动安装后继续恢复数据。
)

echo [4/5] 恢复 OBB...
if exist "obb" (
    adb shell "mkdir -p '/sdcard/Android/obb/!PACKAGE!'" 2>nul
    adb shell "rm -rf '/sdcard/Android/obb/!PACKAGE!/'*" 2>nul
    echo   推送至 /sdcard/Android/obb/!PACKAGE!/ ...
    adb push "obb" "/sdcard/Android/obb/!PACKAGE!/"
    if errorlevel 1 (
        echo 警告:OBB 恢复失败。
    ) else (
        echo   OBB 恢复完成。
    )
) else (
    echo   备份中无 OBB,跳过。
)

echo [5/5] 恢复 data...
if exist "data" (
    adb shell "mkdir -p '/sdcard/Android/data/!PACKAGE!'" 2>nul
    adb shell "rm -rf '/sdcard/Android/data/!PACKAGE!/'*" 2>nul
    echo   推送至 /sdcard/Android/data/!PACKAGE!/ ...
    adb push "data" "/sdcard/Android/data/!PACKAGE!/"
    if errorlevel 1 (
        echo 警告:data 恢复失败。
    ) else (
        echo   data 恢复完成。
    )
) else (
    echo   备份中无 data,跳过。
)

call :cleanup_temp "%RESTORE_DIR%"

echo.
echo ========================================
echo 恢复完成!请手动启动应用检查数据。
echo ========================================
exit /b 0

:cleanup_temp
cd /d "%~dp0"
if not "%~1"=="" rmdir /s /q "%~1" 2>nul
exit /b 0

效果

相关推荐
私人珍藏库6 小时前
【Android】BotHub-多模型AI机器人聚合库-内置免费模型
android·人工智能·智能手机·app·工具·多功能
普马萨特6 小时前
Wi-Fi 扫描频率限制与 Android 演进全解析
android
张拭心7 小时前
Android 17 新特性:后台音频交互限制加强
android·前端
张拭心7 小时前
Android 17 新特性:ProfilingManager 新触发器
android·前端
张拭心7 小时前
Android 17 新特性:MessageQueue 无锁实现
android·前端
brycegao7 小时前
如何搭建标准化 Git 工具流,保障 Android 团队代码质量
android·ci/cd
AI科技星7 小时前
数术江湖·全卷合集 - 硬核江湖・数理史诗
android·人工智能·架构·概率论·学习方法
五月君_7 小时前
安卓也支持了!微信链接 Claude Code 保姆级教程
android·微信
柚鸥ASO优化8 小时前
一篇讲透安卓ASO!开发者千万别只盯着iOS了
android·ios·aso优化