简介

Android Studio默认使用Gradle作为构建工具,不像Ant那样基于XML,取而代之的是采用基于Groovy的DSL(Domain Specific Language)。

Gradle构建工具是任务驱动型的构建工具,并且可以通过各种Plugin扩展功能以适应各种构建任务。

采用约定优于配置的原则,最简单方式是使用一个默认的目录结构。当然目录结构是可以自己修改的。

Gradle Build Files

新建一个Android Studio项目时,会默认生成以下Gradle相关文件。

Project级别的build.gradle文件

buildscript {
 
//编译Gradle脚本过程中需要的依赖关系.//
 
    repositories {
 
        jcenter()
    }
 
//选择JCenter repository.//
 
    dependencies {
 
        classpath 'com.android.tools.build:gradle:1.2.3'
 
//脚本依赖Android plugin for Gradle 1.2.3// 
 
    }
}
 
allprojects {
 
//你应用的依赖关系.//
 
    repositories {
        jcenter()
    }
}
 
//应用依赖jCenter repository.//

Module级别的build.gradle文件

apply plugin: 'com.android.application'
 
//引入Android App插件.//
 
android {
 
//下面的部分配置Android App相关的信息.//
 
    compileSdkVersion 21
 
//编译的SDK版本.// 
 
    buildToolsVersion "21.1.1"
 
//Build Tools版本,最好选择版本号大于或等于compileSdkVersion的.//
 
    defaultConfig {
 
        applicationId "com.example.jessica.myapplication"
 
//application’s ID. 旧版本是 ‘packageName’.//
 
        minSdkVersion 16
 
//需要的最小API版本.//
 
        targetSdkVersion 21
 
//应用运行的API版本.//
         
        versionCode 1
 
        versionName "1.0"
    }
 
    buildTypes {
        release {
 
//‘BuildTypes’ 控制你App如何编译打包. 如果你想创建你自己的 build variants, 添加到这里.//
 
            minifyEnabled true
 
//是否进行混淆.//
 
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
 
//混淆配置.// 
 
        }
    }
}
 
dependencies {
 
//当然Module需要的依赖关系.//
 
   compile fileTree(dir: 'libs', include: ['*.jar'])
 
//依赖编译app/libs.// 
 
   compile 'com.android.support:appcompat-v7:21.0.3'
 
//依赖编译远端库.//
 
}

Other Gradle Files

gradle-wrapper.properties (Gradle Version)

wrapper相关配置文件:当其他人编译你的项目时,即使他们没有安装gradle,使用./gradlew相关命令时,这个文件会检查正确版本的gradle是否被安装,如有必要会帮你下载正确的版本。下面会详细讲wrapper。

distributionBase=GRADLE_USER_HOME
 
//决定解压后的Gradle包是存储到工程目录下, 还是存储到Gradle user home directory. 
//(对于Unix machines, Gradle user home directory默认在 ~/.gradle/wrapper.)
//如果是PROJECT则zip会解压到该工程目录下
 
distributionPath=wrapper/dists
 
//解压后的Gradle包存放的具体路径.//
 
zipStoreBase=GRADLE_USER_HOME
 
zipStorePath=wrapper/dists

//下载的Gradle zip包所放置的目录//
 
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
 
//Gradle的下载地址.//

settings.gradle

该文件组合你所有想构建的module。

include ':app', ':ActionBar-PullToRefresh'

gradle.properties (Project Properties)

这个文件包含整个project的配置信息。默认是空文件,你可以添加各种属性值到这个文件,build.gradle中可以引用之。

local.properties (SDK Location)

这个文件告诉Android Gradle plugin你的Android SDK安装在哪:

sdk.dir=/Users/jessica/Library/Android/sdk

由于这是你本地的SDK路径,所以这个文件不应该加入版本控制中。

The Gradle Wrapper

Android Studio新建项目时都建议使用Gradle Wrapper来构建,这不是必须的,直接指定你本地的安装的Gradle也行。

用wrapper的好处是当别人参与到该项目时,无须事先本地安装Gradle或者Android Studio,当运行./gradlew相关的命令时,wrapper会检查本地相应目录下是否已经有对应版本的Gradle,如果没有会帮你下载正确的版本。还有对于一些持续集成的测试服务器,不一定是安装了Gradle的,这时候使用wrapper就能避免重新配置服务器。

如果你想将Gradle项目转换成基于Gradle Wrapper的,只需要简单的跑一下gradle wrapper即可,也可以加上--gradle-version 2.4选项来指定一个gradle的版本,--gradle-distribution-url选项指定了从哪儿下载gradle,如果没有任何选项,则会从Gradle repository下载你运行wrappertask的gradle版本。你也可以将wrapper这个task写入你的build.gradle文件:

task wrapper(type: Wrapper) {
    gradleVersion = '2.4'
}

wrappertask会在你的项目根目录下生成如下文件:

sample/
  gradlew
  gradlew.bat
  gradle/wrapper/
    gradle-wrapper.jar
    gradle-wrapper.properties

这些文件是都应该加入到版本控制中的。

如果你想更改Gradle版本,可以直接修改gradle-wrapper.properties文件:

distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip

或者再跑一下wrappertask重新生成这些文件,因为wrapper脚本可能会有更新。

使用wrapper的话会忽略你本机已经安装的gradle。

关于Build variants

Build variants是product flavors和build types的组合。

buildTypes {
    debug {
        debuggable true
    }
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
productFlavors {
    demo {
        applicationId "me.zircon.test.demo"
        versionName "1.0-demo"
    }
    full {
        applicationId "me.zircon.test.full"
        versionName "1.0-full"
    }
}

上面的片段会组合成4种variants:demoDebugdemoReleasefullDebugfullRelease

Android Studio正常左下角有一个Build Variants的面板,里面可以选择你最终想编译的版本,当选择run一个模块时,就是编译的这里选择的版本。也可以通过命令行./gradlew assemble<flavor><buildtype>来编译,编译出的apk可以在app/build/outputs/apk里找到,格式是app-<flavor>-<buildtype>.apk。 也有利用productFlavors来打渠道包的例子。可见这篇文章

Source Sets

我们可以在src下建立多个source set:

sourceSet

每一个set代表一个flavor或者build type,main set所有variants都会用到。在编译某个variants时会选择相应set中的src和res。比如assembleDemoDebug,会组合main,demo和debug set。对于res和manifest文件,内容会合并,如果有重名字段的,其合并优先级从低到高是:libraries/dependencies -> main src -> productFlavor -> buildType。对于src,组合成variants的set中不能存在重名文件,即demo和Debug中不能同时存在一个A.java,但是Debug和Release中可以同时有。 当然我们也可以通过脚本中的sourceSets{ }配置目录结构。 特别对于非约定目录结构的工程(比如Eclipse工程),通过sourceSets{ }加以配置以便Gradle识别:

sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
        demo {
        		 ...
        }
        instrumentTest.setRoot('tests')
}

关于dependencies

dependencies一般有三种形式:

  • Module Dependencies
compile project(":lib")
  • Local Dependencies
compile fileTree(dir: 'libs', include: ['*.jar'])
  • Remote Dependencies
compile 'com.android.support:appcompat-v7:19.0.1'

对于Remote Dependencies,书写的格式一般是group:name:version这个网址可以帮你在Maven Central搜索lib并生成dependencies。

jcenter 和 Maven Central

Gradle会自动从repositories{…}帮你下载编译Remote Dependencies。

旧版本的Android Studio默认生成的repositories{ }是Maven Central,而新版本已经变成jcenter。这两者都是相互独立的lib仓库,由不同的厂商托管,相较之下,jcenter有以下优势:

  • jcenter对开发者是友好的,上传自己的lib到jcenter很方便
  • jcenter利用CDN加速,所以下载lib更快
  • jcenter类库更全,可以认为是Maven Central的超类

并不是所有类库都host在jcenter或者Maven Central上,有些是host在自己的Maven仓库中,比如我们项目中所使用的twitter的crashlytics库,它host在twitter自己的仓库中:

repositories {
    maven { url 'https://maven.fabric.io/public' }
}

关于如何将自己的类库上传到jcenter可以参考这篇文章

Gradle的一些概念

我们回过头来看看Gradle的一些概念。

Gradle脚本基于Groovy。每一个Gradle脚本执行时都会配置一种类型的对象。比如执行build.gradle会建立并配置一个Project类型的对象,而settings.gradle则配置Settings对象。相应的这个类型中的属性和方法可以直接用在脚本中,如:file(...)返回路径的File对象;println name则打印该project的name。

脚本里可以使用任何Groovy/Java的语法。比如解析AndroidManifest文件取得VersionName:

def manifestVersionName() {
    def manifestFile = file(project.projectDir.absolutePath + '/src/main/AndroidManifest.xml')
    def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "android")
    def xml = new XmlParser().parse(manifestFile)
    return xml.attributes()[ns.versionName].toString()
}

Project

Gradle里面的Project的概念可以理解成Android Studio中的Module的概念,Project是指我们的构建产物(比如Jar包)或实施产物(将应用程序部署到生产环境)。一个项目可以包含一个或多个任务。

Task

Project由一个或多个Task组成,每一个Task代表了一连串原子性的操作。在Android Studio右边的Gradle面板或者输入命令./gradlew tasks都能查看当前项目所有的Task。 我们也可以用多种方式来新建一个task:

task myTask
task myTask { configure closure }
task myType << { task action }
task myTask(type: SomeType)
task myTask(type: SomeType) { configure closure }

Plugin

在Gradle中,所有有用的特性都是由Plugin来提供的。添加Plugin到Gradle中其实就是添加了一些新的task,域对象(如SourceSet),约定(如Java source默认放在src/main/java下),同时也会扩展一些已经存在的类型。 Plugin分两种:脚本插件apply from: 'other.gradle'和二进制插件apply plugin: 'java'

Refs

  1. https://docs.gradle.org/current/userguide/userguide.html
  2. http://tools.android.com/tech-docs/new-build-system
  3. http://developer.android.com/sdk/installing/studio-build.html

博客搭了好久了,前几天重新换了个响应式布局的主题,还挺清爽简洁的,顺便记录下搭建过程吧。

1. 域名

前段日子看到Godaddy .me域名做活动就心血来潮买了个域名,荒了一段时间,心想还是搭个blog吧,最后还是选择搭在GitHub Pages,折腾就折腾一些吧。

首先呢,得把NS换到DNSPOD, 可以参考官方帮助

2. GitHub Pages

不熟悉git和github?可以戳这篇史上最浅显易懂的Git教程

要在GitHub Pages搭建blog最好选择User or organization site,需要注意你的blog仓库名必须和你的github username相同,然后follow页面上剩余的步骤就算基本搭建完成,浏览器中输入username.github.io就可以看到效果。

绑定域名

下面是绑定域名到刚才搭建的pages,官方指导在这里。 简单说下步骤:

  • 在repository下新建一个CNAME文件,里面写入你的域名,如example.com
  • 到DNSPOD你域名的配置页面,如果是顶级域名example.com则配置两个A记录分别指向:

192.30.252.153

192.30.252.154

  • 配置顶级域名的话同时还要给www.example.com子域名配置一个CNAME记录,指向username.github.io ,这样别人输入www.example.com,github服务器会301重定向到example.com

  • 如果你是单个子域名,如blog.example.com只需配置一个CNAME记录即可,github推荐使用子域名,一来如果github服务器ip变了对于顶级域名你得去修改它的A记录,二来可以更有效抵御DoS和利用CDN加速。
  • 配置完成你可以dig一下查看解析情况

3. Jekyll

Jekyll 是一个静态页面生成模板引擎,GitHub Pages内置了对Jekyll的支持,所以你只要建立符合Jekyll规范的目录文件就可以被渲染成一个静态站点。

环境准备

先来搭建一下Jekyll本地环境,Mac自带了ruby,但是要装一下RubyGems,然后更改一下gem源:

gem sources --remove https://rubygems.org/
gem sources -a http://ruby.taobao.org/
gem sources -l
sudo gem update  —-system

一开始我是通过gem install jekyll单独安装jekyll等所需要的库,但是现在有更简单更易于管理的方式,官方指导在这里,首先需要安装一下bundler:

gem install bundler

Bundler通过Gemfile和Gemfile.lock来管理你整个project所依赖的RubyGems,你可以把需要的gems写到Gemfile中,然后执行bundle install,就会自动安装这些gems以及所依赖的其他库,并将所有的依赖信息保存到Gemfile.lock。别人可以通过copy你的Gemfile和Gemfile.lock来保持其环境的一致性。Gemfile看起来像这样:

source ‘http://ruby.taobao.org/’

gem ‘github-pages’

gem ‘coderay’

the GitHub Pages Gem这个项目将所有GitHub Pages所依赖的RubyGems包括插件整合成一个gem:github-pages,所以你只要在Gemfile中加上gem 'github-pages',就可以让你的本地环境保持和GitHub Pages环境一致,如果Jekyll等版本有更新,只需要简单的跑一下bundle update github-pages即可。

熟悉Jekyll

熟悉Jekyll最好就是clone一个用Jekyll搭建的站点到本地,这儿有很多,接着对照Jekyll的官方文档进行学习,列一下几个比较重要的点:

  • 目录结构
  • _config.yml,整个project的Jekyll配置文件
  • YAML头信息,Jekyll会特别处理带有这种头信息的文件
  • liquid模板语言,Jekyll对其进行了一些扩展,如使用Pygments语法高亮的tags写法:{% highlight java %}{% endhighlight %}
  • 插件,由于GitHub Pages生成sites时使用了--safe选项,所以自定义的插件无法支持,但是默认支持这些插件github-pages gem已安装这些插件

Markdown

Jekyll支持使用Markdown撰写blog,Markdown语法相当简单,若不熟悉,这儿有快速入门,Jekyll 2.0之后使用Kramdown作为默认的Markdown解析器,其他还有像Discount等,这些解析器都对标准Markdown有一些扩展与改进。Mac下较好的Markdown编辑器推荐mou,另外这个在线的编辑器感觉也不错。

4. Disqus

静态blog没有数据库,无法自己增加评论功能,好在有第三方的选择,如Disqus多说,个人更喜欢Disqus的整体风格,虽然国内速度较慢。配置也很简单,需要注意几个方面:

  • setup的时候选择Universal Code,然后它会提供给你两段code,一段是load Disqus,一段是display comment count,你可以将这两段写到一个html中然后放到_include目录下,在需要加载Disqus的页面中通过{% include xxx.html %}方式来引用,当然,要加载Disqus的页面还需要你在合适的位置加上<div id="disqus_thread"></div>,这个id就代表了Disqus的放置位置。
  • 对于显示评论数具体可参考这里,显示评论数的样式可以在Disqus的settings->general->Comment Count Link中配置,如我的配置:

count

  • settings->advanced->Trusted Domains该设置最好填上你的域名,它代表只有该域名及其子域名才能加载你的Disqus,置空则代表任何域名。

5. 其他选择

Jekyll的theme有很多选择,比如这里还有这里,你可以直接clone一个进行修改,除了Jekyll还可以选择OctopreshexoRuhoh等,GitHub上还有其他一些类似的静态blog系统。

6. TODO

  • 同时托管到gitcafe
  • 加个toc
  • Jekyll 2.0新特性
  • 保持热情写blog吧 :sunny:

Test Blog