如何从AAR行为中排除特定资源? [英] How To Exclude Specific Resources from an AAR Depedency?

查看:689
本文介绍了如何从AAR行为中排除特定资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于模块的build.gradle文件,是否存在一种合理简单的方法来指示应将依赖项中的某些文件排除在外?我特别想从AAR中排除某些资源.


LeakCanary 是一个有趣的库,用于帮助跟踪内存泄漏.但是,它的compileSdkVersion的未记录要求为21或更高.尽管大多数项目都不会对此产生问题,但是对于图书馆来说,在没有充分理由的情况下要求使用特定的compileSdkVersion是不合理的.开发团队可能已将其compileSdkVersion冻结为一般策略的一部分,而仅将这些设置更改为其应用或某些内容的主要版本更新的一部分.

在这种情况下,至少对于LeakCanary v1.3.1,需要compileSdkVersion的唯一原因是AFAICT,这是因为AAR具有res/values-v21/目录,其中包含从Theme.Material继承的主题定义.诊断活动将使用此主题.最终用户永远不会看到该活动,只有debug版本中的开发人员才能看到.坦白说,从主题角度看,该活动的外观并不重要.强制compileSdkVersion为21只是为了使诊断活动具有特定主题,恕我直言,这是愚蠢的.

如果作为compile指令的一部分,我们可以说嘿,请从此AAR中跳过res/values-v21/,好吗?",这将是很好的.由于-v21主题只是提供了在其他地方定义的主题的替代定义,因此删除-v21主题不会破坏构建或在运行时破坏事物,而只会为我们提供以Holo为主题的诊断活动./p>

我看不到此答案如何与依赖项一起工作.我也不确定它是否完整,并且肯定不被支持 一个>.它也不是真正意义上的简单"—.我不希望有人尝试将其拖放到build.gradle文件中只是为了阻止诸如LeakCanary之类的诊断库中的单个文件.

那么,有比现在更简单的东西适用于Gradle的最新版本的Android插件吗?

解决方案

为您编写了高级gradle任务:

final List<String> exclusions = [];

Dependency.metaClass.exclude = { String[] currentExclusions ->
    currentExclusions.each {
        exclusions.add("${getGroup()}/${getName()}/${getVersion()}/${it}")
    }
    return thisObject
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile ('com.android.support:appcompat-v7:20.+')
    debugCompile ('com.squareup.leakcanary:leakcanary-android:1.3.1')
            .exclude("res/values-v21/values-v21.xml")
    releaseCompile ('com.squareup.leakcanary:leakcanary-android-no-op:1.3.1')
}

tasks.create("excludeTask") << {
    exclusions.each {
        File file = file("${buildDir}/intermediates/exploded-aar/${it}")
        println("Excluding file " + file)
        if (file.exists()) {
            file.delete();
        }
    }
}

tasks.whenTaskAdded({
    if (it.name.matches(/^process.*Resources$/)) {
        it.dependsOn excludeTask
    }
})

现在,您可以对每个依赖项使用方法.exclude(),以提供要从指定依赖项中排除的路径列表. 另外,您可以堆叠.exclude()方法调用.

Is there a reasonably simple way for a module's build.gradle file to indicate that certain files from a dependency should be excluded? I am specifically interested in excluding certain resources from an AAR.


LeakCanary is an interesting library for helping to track down memory leaks. However, it has an undocumented requirement of compileSdkVersion of 21 or higher. While most projects should not have a problem with this, it's unseemly for a library to require a certain compileSdkVersion without a good reason. A development team may have frozen their compileSdkVersion as part of a general policy to only change those sorts of settings as part of major version updates of their app or something.

In this case, for v1.3.1 of LeakCanary at least, the only reason compileSdkVersion is required, AFAICT, is because the AAR has a res/values-v21/ directory, containing a theme definition that inherits from Theme.Material. This theme is used by a diagnostic activity. That activity is never seen by end users, only by developers in debug builds. Frankly, what that activity looks like, theme-wise, does not really matter. Forcing a compileSdkVersion of 21 just to have that diagnostic activity have a certain theme is, IMHO, stupid.

It'd be nice if as part of a compile directive we could say "hey, please skip res/values-v21/ from this AAR, m'kay?". Since the -v21 theme is simply providing an alternative definition of a theme defined elsewhere, dropping the -v21 theme will not break the build or break things at runtime, but merely will give us a Holo-themed diagnostic activity.

I fail to see how this answer works with dependencies. I am also uncertain if it is complete, and it certainly does not appear to be supported. It also doesn't really qualify as "simple" — I would not expect somebody to try dropping this in a build.gradle file just to block a single file from a diagnostic library like LeakCanary.

So, is there something simpler than this that works with now-current editions of the Android Plugin for Gradle?

解决方案

EDIT:

Wrote advanced gradle task for you:

final List<String> exclusions = [];

Dependency.metaClass.exclude = { String[] currentExclusions ->
    currentExclusions.each {
        exclusions.add("${getGroup()}/${getName()}/${getVersion()}/${it}")
    }
    return thisObject
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile ('com.android.support:appcompat-v7:20.+')
    debugCompile ('com.squareup.leakcanary:leakcanary-android:1.3.1')
            .exclude("res/values-v21/values-v21.xml")
    releaseCompile ('com.squareup.leakcanary:leakcanary-android-no-op:1.3.1')
}

tasks.create("excludeTask") << {
    exclusions.each {
        File file = file("${buildDir}/intermediates/exploded-aar/${it}")
        println("Excluding file " + file)
        if (file.exists()) {
            file.delete();
        }
    }
}

tasks.whenTaskAdded({
    if (it.name.matches(/^process.*Resources$/)) {
        it.dependsOn excludeTask
    }
})

Now you can use method .exclude() on each dependency, providing into list of paths, you want to exclude from specified dependency. Also, you can stack the .exclude() method calls.

这篇关于如何从AAR行为中排除特定资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆