AndroidStudio和Gradle使用

环境搭建

首先你得先有JDK并且配置好环境变量,默认都会了。
你也得有Android SDK,默认也有了。

Android Studio

安装Android Studio

下载安装Android Studio: https://developer.android.google.cn/studio/index.html

第一次打开,向导会引导你设置JDK、SDK等必要配置,跟着向导配置即可

Gradle

Gradle是目前Android主流的构建工具,不管你是通过命令行还是通过AndroidStudio来build,最终都是通过Gradle来实现的。

使用这个工具可以完成 app 的编译打包等工作.

Gradle 环境不是必须的,但是对Gradle 的使用有一定帮助,建议安装。

安装Gradle

下载安装gradle: http://services.gradle.org/distributions/
配置环境变量

  • GRADLE_HOME = D:\Program Files\gradle\gradle-4.2.1
  • Path += %GRADLE_HOME%\bin
Groovy

Groovy 是一种动态语言。另外,它和 Java 一样,也运行于 Java 虚拟机中,你可以认为 Groovy
扩展了 Java 语言。比如,Groovy对自己的定义就是:Groovy 是在 java 平台上的、 具有像Python, Ruby 和 Smalltalk 语言特性的灵活动态语言, Groovy 保证了这些特性像 Java 语法一样被 Java 开发者使用。
同样,Groovy 环境不是必须的,因为groovy代码会最终编译成java字节码,直接在java虚拟机上运行

安装 Groovy

下载安装Groovy SDK: http://www.groovy-lang.org/download.html
配置环境变量
GROOVY_HOME = D:\Program Files\groovy-2.4.12
Path += %GROOVY_HOME%\bin

Gradle Wrapper

Gradle Wrapper其实就是一个脚本文件,它会在没有安装Gradle的情况下为我们下载Gradle,之后我们就可以使用gradlew命令,像使用gradle一样来使用Gradle了

Android Studio项目中默认使用了Gradle Wrapper,用Android Studio创建的工程已经配置好Gradle Wrapper,可以直接使用。

  1. 为什么要使用Gradle Wrapper

每一个Wrapper都会绑定到一个特定版本的Gradle,Wrapper会自动地下载并安装对应版本的Gradle。

这就带来两个好处:

  • 不必自己下载、安装、配置Gradle
  • 进行项目构建时能够确保使用正确的Gradle版本(特别是在构建历史项目时特别明显)
  1. 将Wrapper添加到Gradle项目

在命令行中运行 wrapper task 即可配置Wrapper,如下:

1
gradle wrapper –gradle-version 4.1

在配置了Wrapper的Gradle项目中,会存在以下的重要文件:

  • gradlew (Unix) 或者 gradlew.bat (Windows)
  • gradle/wrapper/gradle-wrapper.jar (Wrapper JAR)
  • gradle/wrapper/gradler-wrapper.properties (Wrapper properties)

以上文件都应该放入到版本控制系统中。
下载的Gradle发行版被存放在目录 $USER_HOME/.gradle/wrapper/dists 中

  1. 使用gradlew

当用户安装好了Wrapper后,会在项目的根目录下看到gradlew,它的使用与gradle是一样的。
只需要注意,使用的是gradlew而不是gradle命令:

1
2
./gradlew [task] (UNIX/Linux)
gradlew [task] (Windows)

例如,如果要运行clean和build这个两个task,那么可以执行:

1
gradlew clean build
Build
1
2
3
- gradlew assemble //包含了项目中的所有打包相关的任务
- gradlew assembleDebug //编译并打Debug包
- gradlew assembleRelease //编译并打Release的包

项目代码结构

Android studio 和 Eclipse ADT 使用的代码结构差异较大

  • Eclipse Android项目目录结构

    MyEclipseApp
    ​ MyEclipseApp/
    ​ ├── AndroidManifest.xml
    ​ ├── Android.mk
    ​ ├─res
    ​ │ ├─layout
    ​ │ └─values
    ​ └─src
    ​ └─com
    ​ └─android
    ​ └─myeclipseapp

  • Android Studio 项目目录结构

  • gradle编译需要的格式

一个项目有一个setting.gradle、包括一个顶层的 build.gradle文件、每个Module 都有自己的一个build.gradle文件。

那些build.gradle是哪来的。现在目录结构是/project/你的工程。用终端到/project这一级目录下直接执行gradle init命令。

但是这样生成的build.gradle是空的。

  • settings.gradle
1
include ':app'
  • 顶层的build.gradle:顶层的build.gradle文件的配置最终会被应用到所有项目中。它典型的配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 定义了 Android 编译工具的类路径。repositories中,jCenter是一个著名的 Maven 仓库。
buildscript {
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
// 定义的属性会被应用到所有 module 中,但是为了保证每个项目的独立性,我们一般不会在这里面操作太多共有的东西。
allprojects{
repositories{
google()
jcenter()
}
}
  • 每个项目单独的 build.gradle:针对每个module 的配置,如果这里的定义的选项和顶层build.gradle定义的相同,后者会被覆盖。典型的 配置内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apply plugin: 'com.android.application'

android {
compileSdkVersion 26
defaultConfig {
applicationId "com.um.myeclipseapp"
minSdkVersion 25
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.0.0-beta1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}
  • apply plugin:第一行代码应用了Android 程序的gradle插件,作为Android 的应用程序,这一步是必须的,因为plugin中提供了Android 编译、测试、打包等等的所有task。

  • android:这是编译文件中最大的代码块,关于android 的所有特殊配置都在这里。

  • defaultConfig:就是程序的默认配置,注意,如果在AndroidMainfest.xml里面定义了与这里相同的属性,会以这里的为主。

  • 这里最有必要要说明的是applicationId的选项:在我们曾经定义的AndroidManifest.xml中,那里定义的包名有两个用途:一个是作为程序的唯一识别ID,防止在同一手机装两个一样的程序;另一个就是作为我们R资源类的包名。在以前我们修改这个ID会导致所有用引用R资源类的地方都要修改。但是现在我们如果修改applicationId只会修改当前程序的ID,而不会去修改源码中资源文件的引用。

  • buildTypes:定义了编译类型,针对每个类型我们可以有不同的编译配置,不同的编译配置对应的有不同的编译命令。默认的有debug、release 的类型。

  • dependencies:是属于gradle 的依赖配置。它定义了当前项目需要依赖的其他库。

    Build

gradle init

gradle build // 编译debug和release版本应用
gradle assembleDebug // 编译debug版本应用
gradle assembleRelease // 编译release版本应用
gradle clean // 执行清理任务,和make clean类似
//想了解更多gradle命令,可通过gradle tasks查看

兼容Eclipse Android项目目录结构

由于系统自带应用采用的是Eclipse 的项目目录结构,直接用Android Studio打开不方便编辑、无法
编译。所以,我们可以对这类代码增加Gradle 构建支持,以使支持Eclipse和Android Studio 打开。

  1. 命令行进入代码根目录执行,执行 gradle init
    gradle init 会你的项目增加gradle构建所需的文件(构建脚本:build.gradle和
    settings.gradle),并且默认使用你本地的Gradle 版本创建Gradle Wrapper。
  2. 使用以下代码替换buile.gradle 的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.um.myeclipseapp"
minSdkVersion 25
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

sourceSets {
main{
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
aidl.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
dependencies {
compile fileTree(dir:'libs', include:['*.jar'])
}
}
allprojects {
repositories {
google()
jcenter()
}
}
  1. 打开项目,等待同步完即可

依赖管理

  • 依赖本地jar库
1
2
3
dependencies {
compile fileTree(dir:'libs', include:['*.jar'])
}
  • 依赖远程库
1
2
3
dependencies {
implementation "com.android.support:appcompat-v7:26.1.0"
}
  • Native libraries

配置本地 .so库。在配置文件中做如下配置,然后在对应位置建立文件夹,加入对应平台的.so文件。

1
2
3
4
5
android{
sourceSets.main{
jniLibs.srcDir 'src/main/libs'
}
}
  • 使用隐藏api
  1. 找到未压缩的framework.jar 文件
1
2
3
4
out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar
请注意,并不是:
out\target\product\Hi3798MV200\system\framework\framework.jar
第一个是 java库,第二个是编译完成的二进制文件,显然我们需要的是第一个。
  1. 把.jar文件放入你工程的lib中,如:放到项目根目录的 systemjar 目录中
  2. 在项目的 build.gradle增加provided引用:
1
2
3
dependencies {
provided fileTree(dir:'systemjar', include:['*.jar'])
}
  1. 在build.gradle中修改,在Android SDK放置框架之前部署我们需要的framework.jar:
1
2
3
4
5
6
7
8
allprojects {
...
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:systemjar/framework.jar')
}
}
}
  1. 最后,你如果需要在Android Studio里运行,还需要在app/app.iml中,把jdk的顺序调整到最后。
1
<orderEntry type="jdk" jdkName="Android API 26 Platform" jdkType="Android SDK" />

由于每次编译代码,Anndroid studio 都会修改这个文件,导致手动修改无效。可以在项目的build.gradle 增加以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
task pushDownJdkDependency {
def imlFile = file("EclipseCompatible.iml")
println 'Change EclipseCompatible.iml order'
try {
def parsedXml = (new XmlParser()).parse(imlFile)
def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
parsedXml.component[1].remove(jdkNode)
new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'j
dkName': "Android API 26 Platform", 'jdkType': 'Android SDK'])
def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(parsedXml)
imlFile.text = writer.toString()
} catch (FileNotFoundException e) {
// nop, iml not found
println 'iml not found'
}
}

应用签名

可以使用keystore为应用签名
由于系统签名不是keystore,对于需要系统签名的的应用,可以使用以下工具把系统的密钥和证书
生成keystore

keytool-importkeypair: https://github.com/getfatday/keytool-importkeypair

签名相关的信息,直接写在gradle不利于安全,我们可以把这些信息写到工程根目录下的
signing.properties文件,注意这个文件不要添加进版本控制。

1
2
3
4
5
6
7
KEYSTORE_FILE=你的keystore文件位置

KEYSTORE_PASSWORD= 你的keystore文件密码

KEY_ALIAS= 你的keystore文件用到的别名

KEY_PASSWORD= 你的keystore文件用到的别名的密码

然后在build.gradle中加载这个文件,引用其中的参数就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/加载签名配置的文件
Properties props = new Properties()props.load(new FileInputStream(file("s
igning.properties")))
android {
signingConfigs {
release{
//设置release的签名信息
keyAlias props['KEY_ALIAS']
keyPassword props['KEY_PASSWORD']
storeFile file(props['KEYSTORE_FILE'])
storePassword props['KEYSTORE_PASSWORD']
}
}
...
buildTypes {
...
release {
...
signingConfig signingConfigs.release
}
}
}

构建变体

每个构建变体都代表您可以为应用构建的一个不同版本。例如,您可能希望构建应用的免费版本
(只提供有限的内容)和付费版本(提供更多内容);又或者根据芯片、平台的差异,分别构建不
同版本,比如我们的工厂模式apk。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
android {
...
sourceSets {
...
hisi{
java.srcDirs = ['src', 'chips/hisi']
}
mstar{
java.srcDirs = ['src', 'chips/mstar']
}
}
...
flavorDimensions "chip"
productFlavors {
mstar {
dimension "chip"
applicationIdSuffix ".mstar"
versionNameSuffix "-mstar"
}
hisi {
dimension "chip"
applicationIdSuffix ".hisi"
versionNameSuffix "-hisi"
}
...
}

安装插件

本地安装:File -> Settings -> Plugins -> Install plugin from disk -> 选择打开你已经下载的
插件
在线安装:File -> Settings -> Plugins -> Browse repositories -> 搜索and选择需要的插件 ->Install

常用插件
Plugin Name Plugin link
ADB idea https://github.com/pbreault/adb-idea
ADB Wifi https://github.com/layerlre/ADBWIFI
CodeGlance https://github.com/Vektah/CodeGlance
Markdown Navigator https://github.com/vsch/idea-multimarkdown

资料

Android developer中文网站:https://developer.android.google.cn
深入理解Android之Gradle: http://blog.csdn.net/innost/article/details/48228651
Android Studio 快捷键:https://developer.android.google.cn/studio/intro/keyboardshortcuts.html