备份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

效果

相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui