如何从AAR依赖中排除特定资源?

时间:2015-12-21 14:18:13

标签: android android-gradle

模块的build.gradle文件是否有一种相当简单的方法来表明应该排除来自依赖项的某些文件?我特别想从AAR中排除某些资源。

LeakCanary是一个有趣的库,可帮助追踪内存泄漏。但是,它的无记录要求compileSdkVersion为21或更高。虽然大多数项目都不应该有这个问题,但是图书馆没有充分理由要求某个compileSdkVersion是不合适的。开发团队可能已冻结其compileSdkVersion作为一般政策的一部分,仅将这些设置更改为其应用程序或其他内容的主要版本更新的一部分。

在这种情况下,对于LeakCanary的v1.3.1,至少需要compileSdkVersion的唯一原因AFAICT,因为AAR有一个res/values-v21/目录,其中包含一个继承自{的主题定义{1}}。诊断活动使用此主题。最终用户从未见过该活动,只有Theme.Material版本的开发人员才能看到。坦率地说,主题方面的活动看起来并不重要。强迫debug 21只是为了让诊断活动具有某个主题,恕我直言,愚蠢。

如果作为compileSdkVersion指令的一部分我们可以说"嘿,请从此AAR中跳过compile,m' kay?&#34 ;。由于res/values-v21/主题只是提供了其他地方定义的主题的替代定义,因此删除-v21主题不会破坏构建或在运行时中断事物,而只会给我们-v21主题诊断活动。

我无法看到this answer如何使用依赖项。我也不确定if it is complete, and it certainly does not appear to be supported。它也没有真正的资格作为"简单" - 我不希望有人尝试将其放在Holo文件中,只是为了阻止来自LeakCanary等诊断库的单个文件。

那么,有没有比这更简单的东西适用于现有版本的Gradle Android插件?

4 个答案:

答案 0 :(得分:15)

修改

为您写了高级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()方法调用。

答案 1 :(得分:1)

尝试使用compileOnly关键字将资源标记为仅用于编译。

dependencies {
      compileOnly fileTree(include: ['*.jar'], dir: 'libs')
}

答案 2 :(得分:0)

我相信您可以使用Android Gradle Plugin DSL的PackagingOptions功能更优雅地解决此问题。

我能够自己使用它来排除我在项目中不需要AAR引入的一些本地库。

android {
    ...
    packagingOptions {
        exclude '/lib/armeabi-v7a/<file_to_exclude>'
    }
}

对于问题中概述的案例,我相信这会奏效:

android {
    ...
    packagingOptions {
        exclude '/res/values-v21/<file_to_exclude>'
    }
}

答案 3 :(得分:-4)

是的,您可以使用Proguard

$('.login').on('submit', function(e) {
  e.preventDefault();
  var $this = $(this),
    $state = $this.find('button > .state');
  $this.addClass('loading');
  $state.html('Authenticating');
//Use Ajax here to validate login
//if validate success:
  setTimeout(function() {
    window.href.location = 'adminpage.php';
    }, 4000);
//if failed: alert('login failed.')
  }, 3000);
});