Gradle 都做了哪些缓存?

前言

GradleAndroid的构建工具,它的主要目标就是实现快速的编译构建,而这主要就是通过缓存实现的。本文主要介绍Gradle的缓存机制,具体包括以下内容

  1. Gradle缓存机制
  2. Gradle内存缓存
  3. Gradle项目缓存
  4. Gradle本机缓存
  5. Gradle远程缓存

继续阅读Gradle 都做了哪些缓存?

使用allowInsecureProtocol属性解决gradle的仓库地址不安全警告

使用 allowInsecureProtocol 属性解决 gradle 的仓库地址不安全警告,在 IDEATerminal 中使用命令

$ gradlew --warning-mode all

可以打印出当前 gradle 存在的所有警告信息。

如果有报以下警告:

Using insecure protocols with repositories, without explicit opt-in, has been deprecated. This is scheduled to be removed in Gradle 7.0. Switch Maven repository 'm
aven(http://maven.aliyun.com/nexus/content/groups/public/)' to a secure protocol (like HTTPS) or allow insecure protocols. See https://docs.gradle.org/6.8.3/dsl/or
g.gradle.api.artifacts.repositories.UrlArtifactRepository.html#org.gradle.api.artifacts.repositories.UrlArtifactRepository:allowInsecureProtocol for more details.
Configuration on demand is an incubating feature.

说明你配置了除 maven 中央仓库之外的其他不安全的仓库(至于“不安全”在这里的定义,我也不是很清楚,一些国内的镜像仓库例如阿里的也是“不安全”的)gradle 中有一个属性可以允许 gradle 使用“不安全”的仓库并且不报警告信息,该属性是 allowInsecureProtocol,官方的

Description :Specifies whether it is acceptable to communicate with a repository over an insecure HTTP connection.

翻译过来就是指定通过不安全的HTTP连接与仓库通信是否可接受,如果该属性的值设置为 true,则表示接受“不安全”的仓库地址。

目前,升级项目的 gradle 7.0.2 版本之后,报错如下:

* What went wrong:
A problem occurred configuring root project 'xxxx'.
> Could not resolve all dependencies for configuration ':classpath'.
   > Using insecure protocols with repositories, without explicit opt-in, is unsupported. Switch Maven repository 'maven(http://xxx.xxx.xxx.xxx/jcenter/)' to red
irect to a secure protocol (like HTTPS) or allow insecure protocols. See https://docs.gradle.org/7.0.2/dsl/org.gradle.api.artifacts.repositories.UrlArtifactRepos
itory.html#org.gradle.api.artifacts.repositories.UrlArtifactRepository:allowInsecureProtocol for more details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

只需要在 build.gradle 中进行如下的配置即可:

repositories {
	...
        
    maven {
        allowInsecureProtocol = true
        ...
    }
}

参考链接


使用 allowInsecureProtocol 属性解决 gradle 的仓库地址不安全警告

gradle cache目录(.gradle)剖析

gradle下载后会对文件路径进行修饰,本文给出反向解析,把文件路径修改为原始路径的办法。

之所以研究这个,本来的目的是为了让Gradle支持离线编译,但是由于Gradle目录组织的缺陷,如.gradle/caches/modules-2/metadata-2.23(metadata-xx跟使用的gradle版本有关)目录下module-artifacts.bin等bin文件中存的是本机的绝对路径,导致就算将.gradle拷贝给另一台机器,还是需要联网验证。

将gradle的jcenter重定向的方法见我的另一篇文章:[android]gradle下载加速 - 知乎专栏,例如阿里云的jcenter是Index of /repositories/jcenter

我在内网中搭建了jcenter仓库。然而我不想搭建一个大而全的jcenter的仓库,搭建大而全的仓库可以使用nexus来搭建,阿里云也是那么搭的,由于公司的网络需要上网认证,时不时会断一下,所以我的做法是通过利用.gradle目录来创建jcenter仓库。

下面先介绍.gradle目录的组织。

1 .gradle顶级目录

目录| 功能
caches | gradle缓存目录
daemon | daemon日志目录
native | gradle平台相关目录
wrapper | gradle-wrapper下载目录

2 caches目录

目录 | 功能
2.14.1 | gradle程序的脚本(gradle程序版本)
3.2.1 | gradle程序的脚本(gradle程序版本)
jars-1 | ?
jars-2 | ?
modules-2 | 下载缓存目录

2.1 caches/modules-2目录

目录 | 功能
files-2.1 | gradle下载的jar/aar目录
metadata-2.16 | gradle-2.14.1的描述文件?
metadata-2.23 | gradle-3.2.1的描述文件?

2.1.1 files-2.1的目录组织(jar/aar都下载到这里)

${org}/${package}/${version}/${shanum1}/${package-version}.pom 
${org}/${package}/${version}/${shanum2}/${package-version}.jar

例如:

#jcenter上jar的路径
https://jcenter.bintray.com/com/android/tools/lint/lint-api/25.1.3/lint-api-25.1.3.jar
#对应的缓存目录为
.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/${shasum1}/lint-api-25.1.3.jar

#看下这个目录下有什么?
~ find .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/ -type f
#除了jar包还有pom,用于描述jar。
.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/14c6a94811fb8114a61b8f3ab29214f9466b5c59/lint-api-25.1.3.jar
.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/c4844e26d84dd1f450f90d89d7e2d2d09f52760/lint-api-25.1.3.pom

#看下jar的shasum
~ shasum .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/14c6a94811fb8114a61b8f3ab29214f9466b5c59/lint-api-25.1.3.jar

14c6a94811fb8114a61b8f3ab29214f9466b5c59  .gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-api/25.1.3/14c6a94811fb8114a61b8f3ab29214f9466b5c59/lint-api-25.1.3.jar
#即目录名。

注意:创建jcenter时,对于jar包,可以没有pom,但是如果使用aar,则必须有pom,所以最好是每个版本都有个pom。因为pom中也描述了依赖关系。

3 daemon目录(无需离线)

用于存放gradle daemon的运行日志。按gradle程序版本存放。

目录 | 功能
2.14.1 | gradle-2.14.1运行的日志
3.2.1 | gradle-3.2.1运行的日志

4 native目录(无需离线)

用于存放平台相关(Windows/Linux/Mac)的库。

目录 | 功能
19 | gradle-2.14.1对应的lib目录,按平台存放,如osx-amd64
21 | gradle-3.2.1对应的lib目录,按平台存放,如osx-amd64
jansi | ?

5 wrapper目录

用于存放gradle-wrapper下载gradle的zip包和解压后的文件夹。 
wrapper的目录规则是 
wrapper/dists/gradle-2.14.1-all/${base36}/gradle-2.14.1-all.zip 
wrapper/dists/gradle-2.14.1-all/${base36}/gradle-2.14.1-all.zip.lck 
wrapper/dists/gradle-2.14.1-all/${base36}/gradle-2.14.1-all.zip.ok

其中base36的规则为:

从gradle-wrapper的jar包中提取的Java代码如下:

import java.math.BigInteger;
import java.security.MessageDigest;

public class Hash {

    public static void main(String[] args) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            byte[] bytes = args[0].getBytes();
            messageDigest.update(bytes);
            String str = new BigInteger(1, messageDigest.digest()).toString(36);
            System.out.println(str);
        } catch (Exception e) {
            throw new RuntimeException("Could not hash input string.", e);
        }
    }
}

c++跟java代码见

6. 使用.gradle/caches/modules-2创建jcenter的方法

以下是mirror.sh,我把它放在.gradle目录下。运行脚本会在.gradle目录下生成jcenter目录。把它移走或直接把jcenter目录加入http服务器即可。

目前我的做法是在本地使用gradle编译一次,然后把gradle下载下来的jar/aar/pom全部提交到版本管理,然后由持续集成去拉版本库上的.gradle目录,然后生成jcenter提供给内网编译服务器。

#!/bin/bash
#use .gradle/caches/modules-2/files-2.1/ to create jcenter
SHPATH=$(cd "$(dirname "$0")"; pwd)
DIR="${SHPATH}/caches/modules-2/files-2.1/"
DIR_LENGTH=${#DIR}
if [ `uname` = "Darwin" ]; then
#mac will add "/"
	DIR_LENGTH=$((DIR_LENGTH+1))
fi
rm -rf ${SHPATH}/jcenter/*
find ${DIR} -type f | grep -Ev "DS_Store" | while read line
do
	SRC=${line}
	URL=${line:${DIR_LENGTH}}

	ORG=${URL%%/*}
	URL=${URL#*/}

	MODULE=${URL%%/*}
	URL=${URL#*/}

	REVISION=${URL%%/*}
	URL=${URL#*/}

	SHA1=${URL%%/*}
	URL=${URL#*/}

	FILE=${URL}
#echo "ORG=$ORG, MODULE=$MODULE, REVISION=$REVISION, SHA1=$SHA1, FILE=$FILE"

	DST=${SHPATH}/jcenter/${ORG//.//}/${MODULE}/${REVISION}/${FILE}
echo "$DST"
	mkdir -p `dirname ${DST}`
	if [ ! -f ${DST} ]; then
		cp -a ${SRC} ${DST}
fi
done

另外,上面提到aar有可能会因为缺失pom导致无法使用,我还写了一个脚本,也是放在.gradle目录下,用于修复aar问题。本地运行时,可以只运行这个脚本,因为它会顺路执行上面的脚本。

以下是fix_aar_cache.sh的内容:

#!/bin/bash
SHPATH=$(cd "$(dirname "$0")"; pwd)

SRC_DIR=${SHPATH}/jcenter
CACHE_DIR="${SHPATH}/caches/modules-2/files-2.1/"
${SHPATH}/mirror.sh > /dev/null

DIR_LENGTH=${#SRC_DIR}
if [ `uname` = "Darwin" ]; then
#mac will add "/"
	DIR_LENGTH=$((DIR_LENGTH+1))
fi
find ${SRC_DIR} -name "*.aar" | while read line
do
	SRC=${line}
	LOCAL_POM=${SRC/.aar/.pom}
if [ -f ${LOCAL_POM} ]; then
continue
fi
echo "$LOCAL_POM not found"

	URL=${line:${DIR_LENGTH}}
	URL=${URL/.aar/.pom}
	REMOTE_POM=http://maven.aliyun.com/nexus/content/repositories/jcenter/${URL}
	REMOTE_POM_SHA1=${REMOTE_POM}.sha1

	SHA1=`wget -q -O- ${REMOTE_POM_SHA1}`
	SHA1=${SHA1:2} #remove additional \r\n
echo $SHA1
#reverse to get it
	FILE=${URL##*/}
	URL=${URL%/*}

	REVISION=${URL##*/}
	URL=${URL%/*}

	MODULE=${URL##*/}
	URL=${URL%/*}

	ORG=${URL}
echo "ORG=$ORG, MODULE=$MODULE, REVISION=$REVISION, FILE=$FILE"
#org /->.
	DST=${CACHE_DIR}/${ORG//\//\.}/${MODULE}/${REVISION}/${SHA1}/${FILE}
echo "$DST"
	mkdir -p `dirname ${DST}`
	if [ ! -f ${DST} ]; then
		wget -O ${DST} ${REMOTE_POM}
fi
done

参考链接


集成华为HMS debug/release 修改包名,取不同包名下的agconnect-services.json 文件

debug/release 修改包名,取不同包名下的agconnect-services.json 文件 V2 解决每次更换包名,都是要手动删除agconnect-services.json文件操作

问题描述

集成华为HMS Core/Push在打多渠道包的时候,我需要区分debug版本,release版本,其中涉及到包名的不同,我使用release编译的时候,发现如下错误信息。这个原因是因为你的agconnect-services文件里面含有一个 package_name 参数,这个参数是需要指定包名的,如果 package_name 填写的报名,和目前你所使用的包名没有对应上就会出现这样的错误

修改过程中遇到的错误信息
* What went wrong:
Execution failed for task ':app:processDebugAGCPlugin'.
> ERROR: Failed to verify AGConnect-Config '/client/package_name', expected: 'com.gxx.fast', but was: 'com.gxx.fast.debug'
不是很完美的解决问题

既然是需要区分包名的,我不如直接copy 2份出来,放到src下面,并新建一个类 pushservices 里面存放 debug/release 的类并存放 agconnect-services.json文件,这样我们想使用哪个版本的,就使用哪个版本的

继续阅读集成华为HMS debug/release 修改包名,取不同包名下的agconnect-services.json 文件

Gradle传递System Property

最近在搭建`Jenkins`环境,实现`Android`自动化编译的过程中,由于内网服务器不能访问外网,因此只能配置`Robolectric`访问内网的服务器。

根据官方文档 Configuring Robolectric,发现如果要更改`Robolectric`默认的下载服务器链接地址,需要在项目的每个`lib`库中都配置如下参数,才能实现:

android {
  testOptions {
    unitTests.all {
      systemProperty 'robolectric.dependency.repo.url', 'https://local-mirror/repo'
      systemProperty 'robolectric.dependency.repo.id', 'local'
    }
  }
}

但是这样配置有一个问题,就是没办法动态调整链接地址。

而我们使用

$ bash gradlew clean build -Drobolectric.dependency.repo.url=http://127.0.0.1/jcenter

手工指定的参数,并没有在编译的时候生效。

参数丢失的原因是因为测试用例在新的`JVM`中执行,传入的参数不会自动带给新创建的`JVM`。

这时需要在`Gradle`脚本中将读到的值重新设到系统属性里面,才可以被`Java`程序读到。

android {
    testOptions {
        unitTests.all {
            //命令行下 单元测试可能卡住的问题
            jvmArgs '-noverify'
            //robolectric外部指定下载资源链接的参数,使用 -D 参数指定 bash gradlew clean build -Drobolectric.dependency.repo.url=http://127.0.0.1/jcenter
            systemProperty 'robolectric.dependency.repo.url', System.getProperty("robolectric.dependency.repo.url")
            systemProperty 'robolectric.dependency.repo.id', System.getProperty("robolectric.dependency.repo.id")
        }
    }
}

每个项目的`build.gradle`中都增加上面的配置之后,就可以保证在外部编译的时候动态指定参数了。

Android Studio Chipmunk | 2021.2.1 Patch 1 以及以上的版本,可能会发生如下报错:

URI is not absolute
java.lang.IllegalArgumentException: URI is not absolute
	at java.base/java.net.URL.fromURI(URL.java:692)
	at java.base/java.net.URI.toURL(URI.java:1116)
	at org.robolectric.internal.dependency.MavenArtifactFetcher.getRemoteUrl(MavenArtifactFetcher.java:138)
	at org.robolectric.internal.dependency.MavenArtifactFetcher.fetchToStagingRepository(MavenArtifactFetcher.java:145)
	at org.robolectric.internal.dependency.MavenArtifactFetcher.fetchArtifact(MavenArtifactFetcher.java:65)
	at org.robolectric.internal.dependency.MavenDependencyResolver.lambda$getLocalArtifactUrls$0(MavenDependencyResolver.java:80)
	at org.robolectric.internal.dependency.MavenDependencyResolver.whileLocked(MavenDependencyResolver.java:100)
	at org.robolectric.internal.dependency.MavenDependencyResolver.getLocalArtifactUrls(MavenDependencyResolver.java:75)
	at org.robolectric.internal.dependency.MavenDependencyResolver.getLocalArtifactUrls(MavenDependencyResolver.java:65)
	at org.robolectric.internal.dependency.MavenDependencyResolver.getLocalArtifactUrl(MavenDependencyResolver.java:116)
	at org.robolectric.plugins.LegacyDependencyResolver.getLocalArtifactUrl(LegacyDependencyResolver.java:89)
	at org.robolectric.plugins.DefaultSdkProvider$DefaultSdk.getJarPath(DefaultSdkProvider.java:146)
	at org.robolectric.internal.AndroidSandbox$SdkSandboxClassLoader.<init>(AndroidSandbox.java:102)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at org.robolectric.util.inject.Injector.inject(Injector.java:250)
	at org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:232)
	at org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:498)
	at org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:224)
	at org.robolectric.util.inject.Injector.resolveDependencies(Injector.java:296)
	at org.robolectric.util.inject.Injector.inject(Injector.java:248)
	at org.robolectric.util.inject.Injector.lambda$memoized$1(Injector.java:232)
	at org.robolectric.util.inject.Injector$MemoizingProvider.get(Injector.java:498)
	at org.robolectric.util.inject.Injector.getInstanceInternal(Injector.java:224)
	at org.robolectric.util.inject.Injector.getInstance(Injector.java:208)
	at org.robolectric.util.inject.Injector.access$700(Injector.java:96)
	at org.robolectric.util.inject.Injector$ScopeBuilderProvider.create(Injector.java:564)
	at org.robolectric.util.inject.Injector$ScopeBuilderProvider.lambda$get$0(Injector.java:547)
	at com.sun.proxy.$Proxy19.build(Unknown Source)
	at org.robolectric.internal.SandboxManager.getAndroidSandbox(SandboxManager.java:57)
	at org.robolectric.RobolectricTestRunner.getSandbox(RobolectricTestRunner.java:285)
	at org.robolectric.RobolectricTestRunner.getSandbox(RobolectricTestRunner.java:68)
	at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:236)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:93)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

该报错的原因是 Android Studio 没有正确读取我们配置的 robolectric.dependency.repo.url 环境变量,导致无法成功下载,当然也可能是由于高版本不支持 HTTP ,链接地址必须是 HTTPS 导致此问题,这个没有深究。

解决方法是,在命令行执行

$ bash gradlew clean build -Drobolectric.dependency.repo.url=http://127.0.0.1/jcenter

确保在当前用户目录下的 .m2 目录下,成功完成 robolectric 需要的全部文件的下载。这样,执行测试用例的时候,就可以从本地获取依赖文件,而不需要再去服务器上获取。

参考链接


Gradle本站镜像

使用Android Studio开发,最痛苦的其中一项是Maven下载数据缓慢,目前已经可以根据在Ubuntu 14.04 系统中的Apache Tomcat上部署Apache Archiva 2.2.1来使用本站的代理服务器的方式进行提速了。另一个痛苦的事情就是下载Gradle工具包的速度异常缓慢了,不仅慢,而且还容易失败。
目前本网站已经提供了Gradle工具包的下载代理,具体的操作就是把services.gradle.org进行域名污染,指向本站的IP地址121.199.27.227
Windows下的解决方法为修改C:\Windows\System32\drivers\etc下的hosts文件,里面增加如下内容:

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost
121.199.27.227 services.gradle.org

接着修改Android Studio项目下的gradle\wrapper\gradle-wrapper.properties文件,把其中的

#Tue Aug 16 10:46:15 CST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

修改为:

#Tue Aug 16 10:46:15 CST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-2.14.1-all.zip

注意,上面的修改其实主要是把HTTPS修改成了HTTP,原因在于HTTPS无法进行域名污染。

当然,另外一个比较简单的修改方式为,只要修改distributionUrl为本站地址,更加省事:

#Tue Aug 16 10:46:15 CST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://www.mobibrw.com/distributions/gradle-2.14.1-all.zip

目前本站提供的Gradle工具包版本如下:

gradle-2.10-all.zip.sha256
gradle-2.10-all.zip

gradle-2.14.1-all.zip.sha256
gradle-2.14.1-all.zip

gradle-6.6-all.zip.sha256
gradle-6.6-all.zip

gradle-8.2.1-all.zip

当前更建议大家使用 腾讯的国内镜像 https://mirrors.cloud.tencent.com/gradle/

参考链接


gradle不同版本下载太慢---腾讯做了国内镜像可以直接下载

Android Studio(Gradle)解决库依赖冲突问题

最近在调整代码的时候,出现如下问题:

Cause: com.android.dex.DexException: Multiple dex files define Landroid/support/annotation/AnimRes;
    UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexException: Multiple dex files define Landroid/support/annotation/AnimRes;
        at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:579)
        at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:535)
        at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:517)
        at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:164)
        at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)
        at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:504)
        at com.android.dx.command.dexer.Main.runMonoDex(Main.java:334)
        at com.android.dx.command.dexer.Main.run(Main.java:277)
        at com.android.dx.command.dexer.Main.main(Main.java:245)
        at com.android.dx.command.Main.main(Main.java:106)

网上查询了一下,找到如下的解决方法:

我们常常用gradle.build文件导入依赖库,但是有时候库依赖会发生版本冲突或多个模块依赖同一个库的情况。

这就引出两个问题,如下:

  • 版本冲突时,Gradle会下载多个版本的依赖库吗?
  • 当多个模块依赖同一个库时,每个模块都会去下载该依赖库吗?
    为解决这疑问,接下来我们在Android StudioGradle举个例子:
    gradle.build依赖部分的配置:
dependencies {
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile ('com.android.support:design:22.2.1')
    compile 'com.shamanland:fonticon:0.1.8'
    androidTestCompile 'com.android.support:support-annotations:22.2.1'
    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2')
}

在文件目录下或Android StudioTerminal下敲gradlew -q app:dependencies 命令,便有以下输出:

_debugAndroidTestApk - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- com.android.support.test:rules:0.3
     |    \--- com.android.support.test:runner:0.3 (*)
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- javax.annotation:javax.annotation-api:1.2
     \--- com.android.support.test:runner:0.3 (*)

_debugAndroidTestCompile - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- com.android.support.test:rules:0.3
     |    \--- com.android.support.test:runner:0.3 (*)
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- javax.annotation:javax.annotation-api:1.2
     \--- com.android.support.test:runner:0.3 (*)

_debugApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_debugCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_debugUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_debugUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

_releaseApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_releaseCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_releaseUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_releaseUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

androidJacocoAgent - The Jacoco agent to use to get coverage data.
\--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidJacocoAnt - The Jacoco ant tasks to use to get execute Gradle tasks.
\--- org.jacoco:org.jacoco.ant:0.7.4.201502262128
     +--- org.jacoco:org.jacoco.core:0.7.4.201502262128
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     +--- org.jacoco:org.jacoco.report:0.7.4.201502262128
     |    +--- org.jacoco:org.jacoco.core:0.7.4.201502262128 (*)
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     \--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidTestApk - Classpath packaged with the compiled 'androidTest' classes.
No dependencies

androidTestCompile - Classpath for compiling the androidTest sources.
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- com.android.support.test:rules:0.3
     |    \--- com.android.support.test:runner:0.3 (*)
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- javax.annotation:javax.annotation-api:1.2
     \--- com.android.support.test:runner:0.3 (*)

androidTestProvided - Classpath for only compiling the androidTest sources.
No dependencies

androidTestWearApp - Link to a wear app to embed for object 'androidTest'.
No dependencies

apk - Classpath packaged with the compiled 'main' classes.
No dependencies

archives - Configuration for archive artifacts.
No dependencies

compile - Classpath for compiling the main sources.
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

可以看出:com.android.support.test:runner:0.3 这个模块原本是依赖于com.android.support:support-annotations22.2.0版本,但由于你又在gradle.build中加了这行androidTestCompile 'com.android.support:support-annotations:22.2.1'gradle就会下载com.android.support:support-annotations22.2.1版本,而不会去下载com.android.support:support-annotations22.2.0版本,因此com.android.support.test:runner:0.3 就会被强转变依赖于com.android.support:support-annotations22.2.1版本
第二个问题,我还是利用上面gradle命令行打出的信息来看看:

debugApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

仔细看上面的依赖,com.android.support:appcompat-v7:22.2.1com.android.support:design:22.2.1,有共同依赖一个com.android.support:support-v4:22.2.1库,且com.android.support:design:22.2.1 依赖于com.android.support:appcompat-v7:22.2.1,但从打印出的信息可以看出com.android.support:design:22.2.1 依赖两个库的信息被打了星号标记,这标记意思是忽略这两个依赖的意思,也就是说不去下载这两个库。
从上面的两个例子来看,gradle对于需要多个版本的依赖库来说,一般只会下载你配置导入那个版本,如果没有手动导入,那就会下载所有模块依赖的最新版本那个库,面对多个模块依赖同一个库,每个模块不都会去下载该依赖库,而是下载一个该依赖库,共享给多个模块。
修改配置文件为:

dependencies {
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile ('com.android.support:design:22.2.1')
            {
                exclude group: 'com.android.support'
            }
    compile 'com.shamanland:fonticon:0.1.8'
    androidTestCompile 'com.android.support:support-annotations:22.2.1'
    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2')
            {
                exclude  group:'com.android.support.test'
            }
}

打印信息:

$ gradlew -q app:dependencies

------------------------------------------------------------
Project :app
------------------------------------------------------------

_debugAndroidTestApk - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     \--- javax.annotation:javax.annotation-api:1.2

_debugAndroidTestCompile - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     \--- javax.annotation:javax.annotation-api:1.2

_debugApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_debugCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_debugUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_debugUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

_releaseApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_releaseCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_releaseUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_releaseUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

androidJacocoAgent - The Jacoco agent to use to get coverage data.
\--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidJacocoAnt - The Jacoco ant tasks to use to get execute Gradle tasks.
\--- org.jacoco:org.jacoco.ant:0.7.4.201502262128
     +--- org.jacoco:org.jacoco.core:0.7.4.201502262128
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     +--- org.jacoco:org.jacoco.report:0.7.4.201502262128
     |    +--- org.jacoco:org.jacoco.core:0.7.4.201502262128 (*)
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     \--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidTestApk - Classpath packaged with the compiled 'androidTest' classes.
No dependencies

androidTestCompile - Classpath for compiling the androidTest sources.
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     \--- javax.annotation:javax.annotation-api:1.2

androidTestProvided - Classpath for only compiling the androidTest sources.
No dependencies

androidTestWearApp - Link to a wear app to embed for object 'androidTest'.
No dependencies

apk - Classpath packaged with the compiled 'main' classes.
No dependencies

archives - Configuration for archive artifacts.
No dependencies

compile - Classpath for compiling the main sources.
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

比较上面两种配置compile信息部分,后面一种配置的 com.android.support:design:22.2.1 就没有输出两个打星号的依赖库信息了。
因此遇到这两种情况是,是gradle能自动帮我们解决掉了这两种情况,对于如何使用gralde命令行查看库依赖(depends)请看官方文档

参考链接


gradle 管理依赖库两个问题

Windows下搭建基于Jenkins+Git+Gradle的Android持续集成

下载Jenkins


官网下载,如果官网下载存在问题,也可以在本站下载Jenkins

下载Gradle


目前Android Studio支持的是Gradle 2.8版本,因此下载2.8版本的即可。Gradle 2.8,也可以本站下载

安装Tomcat


官方主页Apache Tomcat。Windows下面建议下载32-bit/64-bit Windows Service Installer版本。
DownloadTomcat9

安装Jenkins


将下载的jenkins.war包直接放到tomcat下的webapps目录,启动tomcat,在浏览器输入:http://127.0.0.1:8080/jenkins

安装Git plugin,Gradle plugin,Android Lint Plugin插件


点击Jenkins首页的"Manage Jenkins"链接,如下图:
ManageJenkins

进入设置,点击"Manage Plugins",添加Git plugin,Gradle plugin,Android Lint Plugin

ManagePlugins在打开的页面中,搜索并且安装插件

PluginManagerInstall

系统配置


返回首页,点击" Manage Plugins",然后进入页面中选择Configure System,配置JDK,Gradle,Git的选项。

JenkinsConfigure
设置JDK
SettingJava

SettingJavaManual

新建项目


首页点击"创建一个新任务",如下图:
NewJenkinsJobs
在接下来的页面中,输入工程的名字,并且选择"Freestyle project"

NewJobsCreateSelect
设置Git中源代码的路径,如果是使用SSH证书认证的登陆,则在Credentials中进行配置,如下图:

JenkinsJobAndroidConfigureGitNew

接下来配置触发构建的条件,目前我们设置为每天晚上3点,注意里面输入的是H 3 * * *,每个字符之间都有一个英文的空格。

JenkinsJobAndroidConfigureTrigger

接下来,配置Gralde的编译,在构建项目中选择"Invoke Gradle Script",如下图:
InvokeGradleScript
在选项的Tasks栏目中输入clean build --stacktrace --debug,如下图:

InvokeGradleScriptTasks
接下来,配置构建后操作,一般增加Publish Android Lint results,Archive the artifacts这两项即可,具体的配置参考下图:

InvokeGradleScriptTasksAfterBuild

构建项目


BuildNow

检验构建结果


构建完成以后检查一下,如果在:

当前用户目录\.jenkins\jobs\Android\workspace\app\build\outputs\apk\

下面成功生成了APK文件,则说明配置是成功的。

参考链接


基于Jenkins+git+gradle的android持续集成,jenkinsgradle

Mac Gradle 编译报告Failure initializing default system SSL context

Mac 10.9 版本下使用Gradle 编译 Android 项目,报告错误

Failure initializing default system SSL context

使用 -debug 参数,得到的详细输出如下

2:34:15.273 [ERROR] [org.gradle.BuildExceptionReporter]     at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:50)
22:34:15.278 [ERROR] [org.gradle.BuildExceptionReporter]     at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:32)
22:34:15.279 [ERROR] [org.gradle.BuildExceptionReporter]     at org.gradle.launcher.GradleMain.main(GradleMain.java:26)
22:34:15.281 [ERROR] [org.gradle.BuildExceptionReporter] Caused by: java.io.FileNotFoundException: /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Home/lib/security/cacerts (No such file or directory)
22:34:15.284 [ERROR] [org.gradle.BuildExceptionReporter]     at java.io.FileInputStream.open(Native Method)
22:34:15.285 [ERROR] [org.gradle.BuildExceptionReporter]     at java.io.FileInputStream.<init>(FileInputStream.java:106)
22:34:15.286 [ERROR] [org.gradle.BuildExceptionReporter]     at org.apache.http.conn.ssl.SSLSocketFactory.createSystemSSLContext(SSLSocketFactory.java:299)
22:34:15.288 [ERROR] [org.gradle.BuildExceptionReporter]     at org.apache.http.conn.ssl.SSLSocketFactory.createSystemSSLContext(SSLSocketFactory.java:366)
22:34:15.289 [ERROR] [org.gradle.BuildExceptionReporter]     ... 147 more

可以看到,异常信息为

22:34:15.281 [ERROR] [org.gradle.BuildExceptionReporter] Caused by: java.io.FileNotFoundException: /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Home/lib/security/cacerts (No such file or directory)

到具体的目录下面去看,这个文件果然是不存在的,有些版本链接到了一个不存在的目录,这种情况一般是经历过系统升级,往往会造成这个现象,另外,就是系统安装的Java 是Apple 提供的 Java 版本,而不是 Orcale 官网下载的独立版本。

解决方法是可以到Orcale 官网下载最新版本的 Java ,安装替换即可解决问题。

使用 Homebrew 安装指定版本的软件

在命令行下使用

$ brew install FORMULANAME

就可以安装 FORMULANAME 对应的工具,它会处理好依赖关系,非常方便。默认情况下,安装最新版本。但是现在在使用 Gradle 的时候,最新版本的 Gradle 是1.10,但是编译Android 的项目失败,只能降级成 1.9 版本的才行,解决方法如下

1.查看 brew 支持哪些版本的 gradle

$ sudo brew versions gradle
Warning: brew-versions is unsupported and may be removed soon.
Please use the homebrew-versions tap instead:
  https://github.com/Homebrew/homebrew-versions
1.10     git checkout 2b10422 Library/Formula/gradle.rb
1.9      git checkout 5bab5e9 Library/Formula/gradle.rb
1.8      git checkout 9214e60 Library/Formula/gradle.rb
1.7      git checkout f826cc9 Library/Formula/gradle.rb
1.6      git checkout fff7c0b Library/Formula/gradle.rb
1.5      git checkout 57931e0 Library/Formula/gradle.rb
1.4      git checkout 0b7303a Library/Formula/gradle.rb
1.3      git checkout c259bda Library/Formula/gradle.rb
1.2      git checkout 9b7d294 Library/Formula/gradle.rb
1.1      git checkout 7941972 Library/Formula/gradle.rb
1.0      git checkout dff67fb Library/Formula/gradle.rb
1.0-rc-3 git checkout 5f9e348 Library/Formula/gradle.rb
1.0-rc-2 git checkout f72e33f Library/Formula/gradle.rb
1.0-rc-1 git checkout e2438cf Library/Formula/gradle.rb
1.0-milestone-9 git checkout c27c667 Library/Formula/gradle.rb
1.0-milestone-8a git checkout 69eb948 Library/Formula/gradle.rb
1.0-milestone-8 git checkout 34da975 Library/Formula/gradle.rb
1.0-milestone-7 git checkout 6a8c437 Library/Formula/gradle.rb
1.0-milestone-6 git checkout dae625d Library/Formula/gradle.rb
1.0-milestone-5 git checkout baff305 Library/Formula/gradle.rb
1.0-milestone-3 git checkout d9f2e06 Library/Formula/gradle.rb
1.0-milestone-4 git checkout 4b1230c Library/Formula/gradle.rb
1.0-milestone-2 git checkout 6801464 Library/Formula/gradle.rb
1.0-milestone-1 git checkout 0476235 Library/Formula/gradle.rb
0.9.2    git checkout 38b9338 Library/Formula/gradle.rb
0.9.1    git checkout f986d7d Library/Formula/gradle.rb
0.9      git checkout 45e09d7 Library/Formula/gradle.rb
0.8      git checkout e6f608f Library/Formula/gradle.rb

可以看到,支持 1.9 版本的。

2. 进入 brew 所在的git仓库

$ cd `brew --prefix`

3.复制粘贴刚才 brew versions gradle 命令的提示,我们需要1.9 版本的,因此执行

$ git checkout 5bab5e9 Library/Formula/gradle.rb

此时,本地仓库中的gradle 就被替换成了 1.9 的链接地址信息。

4. 安装

$ sudo brew install gradle
==> Downloading http://services.gradle.org/distributions/gradle-1.9-bin.zip

可以看到输出的信息已经是 1.9 的版本了。