Gradle Android最新自动化编译脚本教程(提供demo源码)


目录(?) [-]
  1. 一前言
  2. 二Demo描述
  3. 三编译执行
    1. 下面我们打开cmd命令窗口进行编译操作
  4. 四参考资料

一、前言

Gradle 是以 Groovy 语言为基础,面向Java应用为主。基于DSL(领域特定语言)语法的自动化构建工具。

上面这句话我觉得写得很官方,大家只需知道Gradle可以用来android开发中进行多个项目依赖的自动化编译脚本,知道这点也就知道我们使用它的目的;

为什么不使用Ant做自动化编译脚本,因为ant上手快,但是维护起来太不方便了,有了Gradle你可以跟项目组的同事说,用Ant的孩子们别苦逼的维护了,赶紧换成gradle吧。


本文面向gradle新手或者以前使用过gradle低版本的朋友,因为我感觉每次gradle升级那个脚本也有些坑爹,有些api就废弃掉了,不过总体感觉每次升级都让这个工具更加严谨话,易用话了。


二、Demo描述

下面我就简单写一个demo,通过这个demo程序让大家如何快速上手,比较实用的一个实例:

demo程序分为2个工程,你可以直接实用eclipse新建一个android工程,其实我也是这么干的,这样一来大家仔细看下图



这里顺便强调一下demo工程的环境配置:(很重要,否则下面被我坑了别怪我提起没跟你说)

jdk:C:\Program Files\Java\jdk1.8.0_20(注意:不要使用jre,gradle会提示你使用jdk的)

否则脚本会提示以下错误:

  1. * What went wrong:  
  2. Execution failed for task ':appcompat_v7:compileReleaseJava'.  
  3. > Cannot find System Java Compiler. Ensure that you have installed a JDK (not just a JRE) and configured your JAVA_HOME  
  4. system variable to point to the according directory.  
* What went wrong:
Execution failed for task ':appcompat_v7:compileReleaseJava'.
> Cannot find System Java Compiler. Ensure that you have installed a JDK (not just a JRE) and configured your JAVA_HOME
system variable to point to the according directory.
android-sdk:D:\dev\adt-bundle-windows-x86-20140702 

android-api: 20, android4.4W(注意:做android开发你每次都是用最新的api编译是一个好习惯

gradle:2.1,(使用最新的版本2.2,no zuo no die,被坑不断,欢乐不断)

  gradle的下载地址:http://www.gradle.org/documentation ,大家可以看看文档,当然你的E文好的话,会容易上手,不过没关系,看了我写的文章你gradle的文档你可以不看了,因为很多东西你用不上,除非你项目中使用了特别复杂的功能

  gradle2.1的api文档:http://www.gradle.org/docs/current/javadoc/org/gradle/api/Project.html ,这个需要你偶尔翻翻,因为简单功能会用上的


环境变量配置

JAVA_HOME,GRADLE_HOME都要添加到环境变量里

当然了path变量里你也要加上 JAVA_HOME/bin,和GRADLE_HOME/bin,这样下面你开一个CMD命令行,才可以方面使用gradle build命令


好了准备工作完成后,我们就开始正式讲讲这个demo工程了


TestDemo工程就写了一个activity,显示hello world!

Appcompatv7工程大家懂得一个library,很有代表性,我们实际项目中会用到多个library,你可以举一反三了。


下面看看目录文件:


你想运行编译脚本,需要2个配置文件,local.properties和settings.gradle

settings.gradle里的代码内容:

  1. include ':appcompat_v7', ':TestDemo'  
include ':appcompat_v7', ':TestDemo'
这里面可以看到是project的描述,如果你有多个工程如论主工程还是引用的库工程,都需要在这里面声明,否则gradle找不到


local.properties里的代码内容:

  1. sdk.dir=D:\\dev\\adt-bundle-windows-x86-20140702\\sdk  
sdk.dir=D:\\dev\\adt-bundle-windows-x86-20140702\\sdk
这里面可以看到是android sdk的目录,自己填好,否则也会报错。

      好了下面讲讲每个工程里面都需要配置一个build.gradle 文件

appcompat_v7工程的build.gradle:

  1.   
</pre><p style="text-indent: 28px;"><span style="color: rgb(51, 51, 51); font-family: arial, 宋体, sans-serif;"><span style="line-height: 24px; font-size: 14px;"></span></span></p><p style="text-indent: 28px;"><span style="color: rgb(51, 51, 51); font-family: arial, 宋体, sans-serif;"><span style="line-height: 24px; font-size: 14px;"></span></span></p><div class="dp-highlighter bg_html"><div class="bar"><div class="tools"><strong>[html]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.csdn.net/changemyself/article/details/39927381#">view plain</a><a target=_blank title="copy" class="CopyToClipboard" href="http://blog.csdn.net/changemyself/article/details/39927381#">copy</a><a target=_blank title="print" class="PrintSource" href="http://blog.csdn.net/changemyself/article/details/39927381#">print</a><a target=_blank title="?" class="About" href="http://blog.csdn.net/changemyself/article/details/39927381#">?</a><a target=_blank title="在CODE上查看代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/481062" target="_blank"><img width="12" height="12" style="left: 2px; top: 1px; position: relative;" alt="在CODE上查看代码片" src="https://code.csdn.net/assets/CODE_ico.png" /></a><a target=_blank title="派生到我的代码片" style="text-indent: 0px;" href="https://code.csdn.net/snippets/481062/fork" target="_blank"><img width="12" height="12" style="left: 2px; top: 2px; position: relative;" alt="派生到我的代码片" src="https://code.csdn.net/assets/ico_fork.svg" /></a></div></div><ol class="dp-xml"><li class="alt"><span><span>buildscript{  </span></span></li><li><span>    repositories{  </span></li><li class="alt"><span>        mavenCentral();  </span></li><li><span>    }  </span></li><li class="alt"><span>      </span></li><li><span>    dependencies{  </span></li><li class="alt"><span>        classpath 'com.android.tools.build:gradle:0.13.+' //如果使用gradle2.2版本,请改为gradle:0.14.+  </span></li><li><span>    }  </span></li><li class="alt"><span>      </span></li><li><span>    tasks.withType(JavaCompile) { <span class="attribute">options.encoding</span><span> = </span><span class="attribute-value">"UTF-8"</span><span> }  </span></span></li><li class="alt"><span>}  </span></li><li><span>  </span></li><li class="alt"><span>  </span></li><li><span>apply plugin:'android-library'  </span></li><li class="alt"><span>  </span></li><li><span>  </span></li><li class="alt"><span>dependencies{  </span></li><li><span>    compile fileTree(dir:'libs',include:"*.jar")  </span></li><li class="alt"><span>}  </span></li><li><span>  </span></li><li class="alt"><span>  </span></li><li><span>android{  </span></li><li class="alt"><span>    compileSdkVersion 20  </span></li><li><span>    buildToolsVersion "20"  </span></li><li class="alt"><span>    <span class="attribute">enforceUniquePackageName</span><span>=</span><span class="attribute-value">false</span><span>  </span></span></li><li><span>      </span></li><li class="alt"><span>    lintOptions{  </span></li><li><span>        abortOnError false  </span></li><li class="alt"><span>    }  </span></li><li><span>      </span></li><li class="alt"><span>    sourceSets{  </span></li><li><span>        main{  </span></li><li class="alt"><span>            manifest.srcFile 'AndroidManifest.xml'  </span></li><li><span>            <span class="attribute">java.srcDirs</span><span> = ['src']  </span></span></li><li class="alt"><span>            <span class="attribute">resources.srcDirs</span><span>  = ['src']  </span></span></li><li><span>            <span class="attribute">aidl.srcDirs</span><span> = ['src']  </span></span></li><li class="alt"><span>            <span class="attribute">renderscript.srcDirs</span><span> = ['src']  </span></span></li><li><span>            <span class="attribute">res.srcDirs</span><span> = ['res']  </span></span></li><li class="alt"><span>            <span class="attribute">assets.srcDirs</span><span> = ['assets']  </span></span></li><li><span>        }  </span></li><li class="alt"><span>    }  </span></li><li><span>      </span></li><li class="alt"><span>    lintOptions{  </span></li><li><span>        abortOnError false  </span></li><li class="alt"><span>    }  </span></li><li><span>}  </span></li></ol></div><pre class="html" style="display: none;" name="code" code_snippet_id="481062" snippet_file_name="blog_20141009_4_910552">buildscript{
	repositories{
		mavenCentral();
	}
	
	dependencies{
		classpath 'com.android.tools.build:gradle:0.13.+' //如果使用gradle2.2版本,请改为gradle:0.14.+
	}
	
	tasks.withType(JavaCompile) { options.encoding = "UTF-8" }
}


apply plugin:'android-library'


dependencies{
	compile fileTree(dir:'libs',include:"*.jar")
}


android{
	compileSdkVersion 20
	buildToolsVersion "20"
	enforceUniquePackageName=false
	
	lintOptions{
		abortOnError false
	}
	
	sourceSets{
		main{
			manifest.srcFile 'AndroidManifest.xml'
			java.srcDirs = ['src']
			resources.srcDirs  = ['src']
			aidl.srcDirs = ['src']
			renderscript.srcDirs = ['src']
			res.srcDirs = ['res']
			assets.srcDirs = ['assets']
		}
	}
	
	lintOptions{
		abortOnError false
	}
}



对于这个文件我需要强调几点:

1、classpath 'com.android.tools.build:gradle:0.13.+'  ,很多人用了低版本出了问题写什么0.11+,我不管,你要使用gradle2.1版本,这里就写成0.13.+包你没错。如果使用gradle2.2版本,这里就要写成0.14.+

2、apply plugin:'android-library',说明这个一个库工程,详细自己找资料脑补

3、tasks.withType(JavaCompile) { options.encoding = "UTF-8" }   ,task是个啥自己查去,这里编译encoding配成UTF-8,还有一点在低版本脚本有的人写成tasks.withType(Compile) ,这样子报错了,改成JavaCompile吧,我是一点一点排错的

4、android{
compileSdkVersion 20
buildToolsVersion "20"

这里面version写20,为啥?上面你看看我的android-sdk api的版本就知道了,写成别的也可以,你要保证你本地androidsdk都有。





TestDemo工程里的几个文件:


build目录:是gradle执行编译时候生成的,里面好多内容,有兴趣自己翻翻看

output目录:我写得脚本,最后把build里的apk自动copy到这个目录,这个可以具体看脚本

blue_key:apk签名文件

build.gradle:你懂得

TestDemo工程里面的build.gradle



  1. import java.util.regex.Pattern  
  2. //import com.android.builder.DefaultManifestParser  
  3. import com.android.builder.core.DefaultManifestParser  
  4.   
  5.   
  6. buildscript{  
  7.     repositories{  
  8.         mavenCentral()  
  9.     }  
  10.     dependencies{  
  11.         classpath 'com.android.tools.build:gradle:0.13.+'  
  12.   
  13.     }  
  14.   
  15.     /***  
  16.     tasks.withType(Compile){  
  17.         options.encoding = "UTF-8"  
  18.     }  
  19.     **/  
  20.   
  21.     tasks.withType(JavaCompile) { options.encoding = "UTF-8" }  
  22. }  
  23.   
  24. apply plugin:'android'  
  25.   
  26. dependencies{  
  27.     compile fileTree(dir:"libs",include:'*.jar')  
  28.     compile project(':appcompat_v7')  
  29. }  
  30.   
  31. android{  
  32.     compileSdkVersion 20  
  33.     buildToolsVersion "20"  
  34.     enforceUniquePackageName=false  
  35.       
  36.     defaultConfig{  
  37.         targetSdkVersion 17;  
  38.     }  
  39.       
  40.     lintOptions{  
  41.         abortOnError false  
  42.     }  
  43.   
  44.     dexOptions {  
  45.         preDexLibraries = false  
  46.     }  
  47.   
  48.     packagingOptions {  
  49.         exclude 'META-INF/DEPENDENCIES.txt'  
  50.         exclude 'META-INF/LICENSE.txt'  
  51.         exclude 'META-INF/NOTICE.txt'  
  52.         exclude 'META-INF/NOTICE'  
  53.         exclude 'META-INF/LICENSE'  
  54.         exclude 'META-INF/DEPENDENCIES'  
  55.         exclude 'META-INF/notice.txt'  
  56.         exclude 'META-INF/license.txt'  
  57.         exclude 'META-INF/dependencies.txt'  
  58.         exclude 'META-INF/LGPL2.1'  
  59.         exclude 'META-INF/ASL2.0'  
  60.     }  
  61.   
  62.     signingConfigs{  
  63.         myConfig{  
  64.             storeFile file("bluekey")  
  65.             storePassword "blue"  
  66.             keyAlias "blue"  
  67.             keyPassword "blue"  
  68.         }  
  69.     }  
  70.   
  71.     buildTypes{  
  72.         release{  
  73.               
  74.   
  75.             //runProguard true  //打开混淆开关 这种写法不可以了  
  76.             //proguardFile 'proguard.txt.txt'  //配置单个文件这样,这种写法不可以了  
import java.util.regex.Pattern
//import com.android.builder.DefaultManifestParser
import com.android.builder.core.DefaultManifestParser


buildscript{
	repositories{
		mavenCentral()
	}
	dependencies{
		classpath 'com.android.tools.build:gradle:0.13.+'

	}

	/***
	tasks.withType(Compile){
		options.encoding = "UTF-8"
	}
	**/

	tasks.withType(JavaCompile) { options.encoding = "UTF-8" }
}

apply plugin:'android'

dependencies{
	compile fileTree(dir:"libs",include:'*.jar')
	compile project(':appcompat_v7')
}

android{
	compileSdkVersion 20
	buildToolsVersion "20"
	enforceUniquePackageName=false
	
	defaultConfig{
		targetSdkVersion 17;
	}
	
	lintOptions{
		abortOnError false
	}

	dexOptions {
		preDexLibraries = false
	}

	packagingOptions {
		exclude 'META-INF/DEPENDENCIES.txt'
		exclude 'META-INF/LICENSE.txt'
		exclude 'META-INF/NOTICE.txt'
		exclude 'META-INF/NOTICE'
		exclude 'META-INF/LICENSE'
		exclude 'META-INF/DEPENDENCIES'
		exclude 'META-INF/notice.txt'
		exclude 'META-INF/license.txt'
		exclude 'META-INF/dependencies.txt'
		exclude 'META-INF/LGPL2.1'
		exclude 'META-INF/ASL2.0'
	}

	signingConfigs{
		myConfig{
			storeFile file("bluekey")
			storePassword "blue"
			keyAlias "blue"
			keyPassword "blue"
		}
	}

	buildTypes{
		release{
			

			//runProguard true  //打开混淆开关 这种写法不可以了
			//proguardFile 'proguard.txt.txt'  //配置单个文件这样,这种写法不可以了
  1. <span style="white-space: pre;">            </span>minifyEnabled true  
  2.                         proguardFile getDefaultProguardFile('proguard-android.txt')//指定混淆文件  
  3.   
  4.             signingConfigs.myConfig  
  5.         }  
  6.     }  
  7.   
  8.     sourceSets{  
  9.         main{  
  10.             manifest.srcFile 'AndroidManifest.xml'  
  11.             java.srcDirs = ['src']  
  12.             resources.srcDirs = ['src']  
  13.             aidl.srcDirs = ['src']  
  14.             //rendersrcDirs = ['src']  
  15.             res.srcDirs = ['res']  
  16.             assets.srcDirs = ['assets']  
  17.         }  
  18.     }  
  19.   
  20.     task copyNativeLibs(type: Copy) {  
  21.         from(new File(project(':appcompat_v7').getProjectDir(), 'libs')) { include '**/*.so' }  
  22.         into new File(buildDir, 'native-libs')  
  23.     }  
  24.   
  25.       
  26.     tasks.withType(JavaCompile){  
  27.         compileTask -> compileTask.dependsOn copyNativeLibs  
  28.     }  
  29.   
  30.     clean.dependsOn 'cleanCopyNativeLibs'  
  31.   
  32.     tasks.withType( com.android.build.gradle.tasks.PackageApplication){  
  33.         pkgTask -> pkgTask.jniFolders = new HashSet<File>()  
  34.         pkgTask.jniFolders.add(new File(buildDir,'native-libs'))  
  35.     }  
  36.       
  37.       
  38.       
  39. }  
  40.   
  41. build.doLast {  
  42.         def today = new Date().format('yyMMdd');  
  43.         copy{  
  44.             //from('build/apk')  
  45.             from('build/outputs/apk')  
  46.             into('output')  
  47.             include('TestDemo-debug.apk')  
  48.             rename('TestDemo-debug.apk','blue-'+today+'-'+readVersion()+'-demo.apk')  
  49.         }  
  50. }  
  51.       
  52. /**  
  53.     *从Manifest.xml中读取版本号  
  54.     **/  
  55.     def readVersion(){  
  56.         def manifestParser = new DefaultManifestParser()  
  57.         return manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile);  
  58.     }  
<span style="white-space: pre;">			</span>minifyEnabled true
                        proguardFile getDefaultProguardFile('proguard-android.txt')//指定混淆文件

			signingConfigs.myConfig
		}
	}

	sourceSets{
		main{
			manifest.srcFile 'AndroidManifest.xml'
			java.srcDirs = ['src']
			resources.srcDirs = ['src']
			aidl.srcDirs = ['src']
			//rendersrcDirs = ['src']
			res.srcDirs = ['res']
			assets.srcDirs = ['assets']
		}
	}

	task copyNativeLibs(type: Copy) {
        from(new File(project(':appcompat_v7').getProjectDir(), 'libs')) { include '**/*.so' }
        into new File(buildDir, 'native-libs')
    }

	
	tasks.withType(JavaCompile){
		compileTask -> compileTask.dependsOn copyNativeLibs
	}

	clean.dependsOn 'cleanCopyNativeLibs'

	tasks.withType( com.android.build.gradle.tasks.PackageApplication){
		pkgTask -> pkgTask.jniFolders = new HashSet<File>()
		pkgTask.jniFolders.add(new File(buildDir,'native-libs'))
	}
	
	
	
}

build.doLast {
		def today = new Date().format('yyMMdd');
		copy{
			//from('build/apk')
			from('build/outputs/apk')
			into('output')
			include('TestDemo-debug.apk')
			rename('TestDemo-debug.apk','blue-'+today+'-'+readVersion()+'-demo.apk')
		}
}
	
/**
	*从Manifest.xml中读取版本号
	**/
	def readVersion(){
		def manifestParser = new DefaultManifestParser()
		return manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile);
	}





对于这个文件我需要强调几点(很重要):

1、//import com.android.builder.DefaultManifestParser
import com.android.builder.core.DefaultManifestParser

//注释掉的代码是低版本的写法,目前使用最新api

2、 /***
tasks.withType(Compile){
options.encoding = "UTF-8"
}
**/

tasks.withType(JavaCompile) { options.encoding = "UTF-8" }

//注释掉的代码是低版本的写法,目前使用最新api

3、

dependencies{
compile fileTree(dir:"libs",include:'*.jar')
compile project(':appcompat_v7')
}

编译依赖,我们可以看到依赖的库 appcompat_v7要写在这里,注意":"(冒号一定要写)


4、

signingConfigs{
myConfig{
storeFile file("bluekey")
storePassword "blue"
keyAlias "blue"
keyPassword "blue"
}
}


buildTypes{
release{
signingConfigs.myConfig
}
}

编译时候签名文件配置,当然你也可以编译出debug和没有签名的apk,自行查资料去

5、

task copyNativeLibs(type: Copy) {
        from(new File(project(':appcompat_v7').getProjectDir(), 'libs')) { include '**/*.so' }
        into new File(buildDir, 'native-libs')
    }



tasks.withType(JavaCompile){
compileTask -> compileTask.dependsOn copyNativeLibs
}

关于依赖的so文件和jar文件,在编译之前copy依赖到主工程的native-libs目录

6、build.doLast {
def today = new Date().format('yyMMdd');
copy{
//from('build/apk')
from('build/outputs/apk')
into('output')
include('TestDemo-debug.apk')
rename('TestDemo-debug.apk','blue-'+today+'-'+readVersion()+'-demo.apk')
}
}

/**
*从Manifest.xml中读取版本号
**/
def readVersion(){
def manifestParser = new DefaultManifestParser()
return manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile);
}

build.doLast,就是最后执行的意思,关于gradle task大家需要简单查资料掌握即可。


这里面需要注意的:

  def today = new Date().format('yyMMdd');

def manifestParser = new DefaultManifestParser()

都需要def声明变量,低版本不用写的,但是目前不写就要报错了。

这个代码的功能:就是从Manifest文件里读出versioncode然后结合当前日期重新命名output里的apk文件。



方便吧,很实用的一点。

7、apply plugin:'android'

这说明这个脚本需要编译的是一个 android工程,跟上面的library是不是有所不同呢? gradle还支持java project的编译,大家自行查资料。


三、编译执行:

下面我们打开cmd命令窗口进行编译操作



在TestDemo目录执行gradle build,因为这里是local.properties和settings.gradle 所在的根目录。

第一次执行时候,gradle根据依赖去下载所需要的jar包,会在你每个工程里创建一个.gradle目录

dependencies{
classpath 'com.android.tools.build:gradle:0.13.+'
}

下载成功后



ok,那我们开始执行编译操作了,gradle build



编译正常的话会提示 BUILD SUCCESSFUL,然后自己去output目录找apk去。


这里提醒大家一个jar冲突会引起编译中断的问题:


因为很多朋友的project的libs目录有多个android-support-v4.jar导致的。


最后啰嗦

今天先写到这,我们实际运用中有很多需求,例如:自动根据多渠道打包,根据不同的资源和不同的pkg进行apk打包,gradle都能帮你搞定,这块demo后续有时间我贴上来。
有什么问题,大家可以跟我交流(QQ群: 221057495)。


四、参考资料:

After upgrading to Gradle 2.0: Could not find property 'Compile' on root project
Unable to resolve class in build.gradle using Android Studio 0.60/Gradle 0.11
       
How to configure build.gradle files of an existing project with actionbarsherlock lib?
Multiple settings gradle files for multiple projects building

Android Tools Project Site


五、扩展阅读:

引用配置文件里的变量,例如:我们可以引用gradle.properties

sdk.dir=C:\\haha\\dev\\adt-bundle-windows-x86_64-20140702\\sdk

在我们的build.gradle文件中如果要想引用sdk.dir

可以如下操作:

        使用 project.hasProperty('sdk.dir') 判断key值是否存在
 使用project.properties['sdk.dir']进行key值的value引用


demo下载地址:

gradle2.1demo教程(多评论哈)


原文:http://blog.csdn.net/changemyself/article/details/39927381

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值