You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何批量导入/更新Android PNG格式Drawable并覆盖原有WEBP文件?

高效解决PNG与WEBP冲突的非手动方案

嘿,这个场景我太熟悉了——之前团队转WEBP后也遇到过设计临时给PNG更新的情况,给你几个不用手动一个个改的方案,亲测有效:

方案一:Gradle批量处理任务(推荐)

直接在项目的Module级build.gradle里加一个自定义任务,自动完成「删除旧WEBP→转换新PNG为WEBP→删除原PNG」的完整流程:

  1. 把以下代码加到你的Module级build.gradle文件末尾:
task updateDrawablesToWebp {
    doLast {
        // 遍历所有drawable目录
        def drawableDirs = fileTree(dir: 'src/main/res', include: 'drawable-*/').dirs
        // 筛选出所有更新的PNG文件
        def updatedPngs = fileTree(dir: 'src/main/res', include: 'drawable-*/**.png').files

        updatedPngs.each { pngFile ->
            // 构建对应的WEBP文件路径
            def webpPath = pngFile.path.replace('.png', '.webp')
            def webpFile = new File(webpPath)

            // 删除已存在的同名WEBP
            if (webpFile.exists()) {
                println "清理旧WEBP文件: ${webpFile.name}"
                webpFile.delete()
            }

            // 调用Android SDK自带的cwebp工具转换(自动适配当前项目的build-tools版本)
            def cwebpTool = "${android.sdkDirectory}/build-tools/${android.buildToolsVersion}/cwebp"
            def convertCmd = "\"${cwebpTool}\" -lossless \"${pngFile.path}\" -o \"${webpPath}\""
            
            println "开始转换PNG→WEBP: ${pngFile.name}"
            def process = convertCmd.execute()
            process.waitFor()

            // 转换成功后删除原PNG
            if (webpFile.exists() && webpFile.size() > 0) {
                println "删除原PNG文件: ${pngFile.name}"
                pngFile.delete()
            } else {
                println "⚠️ 转换失败,请检查${pngFile.name}"
            }
        }
    }
}
  1. 在Android Studio的Gradle面板里,找到你的Module→Tasks→other→updateDrawablesToWebp,双击运行即可。

注意:运行前建议先备份项目,避免意外;如果你的build-tools版本较低,可能需要升级到28+版本(确保支持cwebp工具)。

方案二:Bash脚本(适合熟悉命令行的同学)

如果更习惯用命令行,可以写一个简单的Bash脚本,逻辑和上面的Gradle任务一致:

#!/bin/bash

# 替换成你的Android SDK路径,或确保ANDROID_HOME环境变量已设置
ANDROID_SDK="${ANDROID_HOME:-~/Library/Android/sdk}"
# 替换成你的build-tools版本(比如34.0.0)
BUILD_TOOLS_VERSION="34.0.0"
CWEBP_PATH="${ANDROID_SDK}/build-tools/${BUILD_TOOLS_VERSION}/cwebp"

# 遍历所有drawable目录
for dir in src/main/res/drawable-*; do
    echo "处理目录: $dir"
    # 遍历当前目录下的所有PNG
    for png_file in "$dir"/*.png; do
        # 跳过空匹配(目录里没有PNG的情况)
        [ -e "$png_file" ] || continue
        
        # 获取文件名(不带后缀)
        file_name=$(basename "$png_file" .png)
        webp_file="$dir/${file_name}.webp"

        # 删除旧WEBP
        if [ -f "$webp_file" ]; then
            echo "→ 删除旧WEBP: $webp_file"
            rm "$webp_file"
        fi

        # 转换PNG到无损WEBP
        echo "→ 转换PNG→WEBP: $png_file"
        "$CWEBP_PATH" -lossless "$png_file" -o "$webp_file"

        # 删除原PNG(转换成功才删)
        if [ -f "$webp_file" ]; then
            echo "→ 删除原PNG: $png_file"
            rm "$png_file"
        else
            echo "⚠️ 转换失败: $png_file"
        fi
    done
done

使用方法:

  1. 把脚本保存为update_webp.sh,放到项目根目录
  2. 给脚本加执行权限:chmod +x update_webp.sh
  3. 运行脚本:./update_webp.sh

方案三:精准处理指定的33个文件(避免全量遍历)

如果不想处理所有PNG,只针对这33个更新文件,可以修改Gradle任务,先把新PNG按drawable目录结构放到项目根目录的new_drawables文件夹(比如new_drawables/drawable-xxhdpi/ic_icon.png),然后用下面的任务只处理这些文件:

task updateSpecificDrawables {
    doLast {
        def newDrawableRoot = file('new_drawables')
        def newPngs = fileTree(dir: newDrawableRoot, include: 'drawable-*/**.png').files

        newPngs.each { newPng ->
            // 计算项目中对应的文件路径
            def relativePath = newDrawableRoot.toURI().relativize(newPng.toURI()).getPath()
            def projectPng = file("src/main/res/${relativePath}")
            def projectWebp = file(projectPng.path.replace('.png', '.webp'))

            // 删除旧WEBP
            if (projectWebp.exists()) {
                println "删除旧WEBP: ${projectWebp.name}"
                projectWebp.delete()
            }

            // 复制新PNG到项目目录(覆盖旧PNG)
            println "复制新PNG到项目: ${newPng.name}"
            projectPng.parentFile.mkdirs()
            newPng.copyTo(projectPng, overwrite: true)

            // 转换为WEBP
            def cwebpTool = "${android.sdkDirectory}/build-tools/${android.buildToolsVersion}/cwebp"
            def convertCmd = "\"${cwebpTool}\" -lossless \"${projectPng.path}\" -o \"${projectWebp.path}\""
            def process = convertCmd.execute()
            process.waitFor()

            // 删除原PNG
            if (projectWebp.exists()) {
                println "删除原PNG: ${projectPng.name}"
                projectPng.delete()
            }
        }
    }
}

这样就只会处理你指定的33个文件,效率更高。


内容的提问来源于stack exchange,提问作者Notlaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:42:38