【问题标题】:Exclude assets for release build type排除发布构建类型的资产
【发布时间】:2015-03-06 11:04:12
【问题描述】:

我正在使用 gradle 构建的应用程序中导入一个 android 库,如下所示:

dependencies {
    compile 'com.example:great-lib:0.1-SNAPSHOT'
}

这个库只包含要在 webview 中使用的资产、js、css 和图像,布局如下:

assets/
|-> great.css
|-> great.min.js
|-> great.min.js.map
|-> js/
|   |-> plop.js
|   |-> foo.js
|   ...
|-> img/
|   ...

js 文件夹包含源文件(用于源映射)。我想在调试版本中包含它和 .map 文件,并且在发布版本中只有缩小的 js,但我找不到这样做的方法。

到目前为止,我已经尝试过:

android {
    // this doesn't exclude anything
    packageOptions {
        exclude 'assets/js'
    }
    buildTypes {
        release {
            // this does exclude the js folder, but in both release and debug
            aaptOptions {
                ignoreAssetsPattern "!js"
            }
        }
    }
}

知道我想要的是否可以实现,如果可以,如何实现?

(我也想过发布两个版本的库(great-libgreat-lib-debug),并在 debugCompilereleaseCompile 中有依赖关系,但我更愿意避免这种情况并发布一个版本)

【问题讨论】:

    标签: android android-gradle-plugin aar


    【解决方案1】:

    我使用这种方法取得了成功(2019 年 5 月 13 日更新以支持 TaskProvider;请参阅旧版本的编辑历史记录):

    android {
    ⋮
        applicationVariants.all { variant ->
            if (variant.buildType.name == 'release') {
                variant.mergeAssetsProvider.configure {
                    doLast {
                        delete(fileTree(dir: outputDir, includes: ['**/js', '**/*.js.map']))
                    }
                }
            }
        }
    ⋮
    }
    

    这应该解决@Xavier 回答的问题:

    • 删除是作为变体的mergeAssets 任务的一部分完成的,因此删除会反映在任务的输出中,并且不影响最新的检查。
    • 计算路径时不使用魔法字符串。如果我的示例过于宽松,您可能需要调整包含模式。
    • 变体是由buildType 名称选择的,这比匹配整个变体名称的问题要小(尽管它仍然是字符串类型)。

    请注意,这种方法也适用于res 文件而不是assets:只需将mergeAssets 替换为mergeResources

    提到packagingOptionsaaptOptions 的其他答案是错误的树,因为它们的范围是所有 变体(它们是在android 范围内定义的,而不是buildTypeproductFlavor)。

    【讨论】:

    • 像魅力一样工作!
    • 这可以在 variables.outputs.each 中完成吗?并检查输出架构?
    • 值得一提的是,这段代码位于inside buildTypes 部分,该部分位于应用程序 build.gradle 的 android 部分中。
    • 非常感谢!你为我节省了很多时间。
    • 谢谢@Drarok 我希望每个人都像你一样关注和了解清楚!
    【解决方案2】:

    我最终做了以下事情:

    android.applicationVariants.all { variant ->
    
      if (variant.name.contains('Release')) {
        // exclude source and sourcemap from release builds
        def noJsSourceTask = task("delete${variant.name}JsSource", type: Delete) {
          delete "${buildDir}/intermediates/assets/${variant.dirName}/js"
          delete "${buildDir}/intermediates/assets/${variant.dirName}/great.min.js.map"
        }
        variant.mergeAssets.finalizedBy noCeJsSourceTask
      }
    }
    

    它工作正常,但有几件事我不太喜欢:

    • 我正在处理任务完成后生成的文件(finalizedBy),因此它不适用于“最新”检查。但这仅适用于发布版本,我更频繁地进行调试
    • 要删除的文件的路径是手动构建的。我不确定它是否足够通用,可以按原样在其他项目中重用
    • 我根据它们的名称选择变体。我会喜欢更有条理的东西。

    【讨论】:

    • 感谢分享您的解决方案!我仍然希望有一个不那么麻烦/脆弱的解决方案。
    • 在 2019 年尝试这个,得到WARNING: API 'variant.getMergeAssets()' is obsolete and has been replaced with 'variant.getMergeAssetsProvider()'.。会喜欢显示正确的新语法的编辑
    【解决方案3】:

    Gradle 提供“aaptOptions, ignoreAssetsPattern”来过滤/排除资产文件夹和文件从发布或调试构建。

    调试构建示例(js 文件夹和great.css 文件):

    debug {            
            aaptOptions {
                ignoreAssetsPattern '!js:!great.css:'
            }
        }
    

    发布版本示例(js 文件夹和great.css 文件):

    release {
            aaptOptions {
                ignoreAssetsPattern '!js:!great.css:'
            }
        }
    

    【讨论】:

    【解决方案4】:

    我认为你可以使用 proguard。 Proguard 包含在 android studio 中,混淆代码,并删除未使用的类,如果您想删除应用程序未使用的所有资源。只在你的 build.gradle 中加入这个:

     release {
    
                minifyEnabled true //remove classes, obfuscate code and zipalign
                shrinkResources true //remove resources
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//autogenerated files
            }
    

    这是相关的链接信息:

    您可以个性化、排除特定文件或忽略特定文件

    【讨论】:

    • 感谢您使用 proguard 的建议。我已经使用了 proguard,但我找不到任何关于使用它来删除/不包括特定文件的文档。你能说得更具体点吗?
    • 是的,你应该在 gradle.build 中激活shrinkResources,这应该删除项目中没有使用的所有资源,这应该删除所有js文件,为了保留一些资源你应该创建一个xml文件,在这个里面文件定义哪些文件或资源不被删除。在 KeepResources 部分的 link 中。之后你应该好好测试,保证它的复杂配置和理解。希望对你有帮助
    • 我已经激活了shrinkResources。它不会删除我不想要的资产,因为我使用的库使用这些文件。但是我不使用库的那部分,所以我可以并且想要不使用这些文件。
    • 没有太多信息可以用 Proguard 做到这一点,理论上应该检测到你没有使用。正如他们在其他答案中所说,在 build.gradle 中创建一个脚本,应该是更好的解决方案,抱歉造成误解
    【解决方案5】:

    无法通过过滤器。

    不过,您可以有 2 个资产文件夹。一个主要的 (src/main/assets) 用于 debugrelease 和一个 (src/debug/assets) 仅用于调试构建。

    source

    【讨论】:

    • 嗨,这不是我的选择,因为不需要的资产在我使用的库中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    相关资源
    最近更新 更多