Android studio 是從哪裏得到庫的?
Android Studio是從build.gradle裏面定義的Maven 倉庫服務器上下載library的。Apache Maven是Apache開發的一個工具,提供了用於貢獻library的文件服務器。總的來說,只有兩個標準的Android library文件服務器:jcenter 和 Maven Central。
jcenter
jcenter是一個由 bintray.com維護的Maven倉庫 。你可以在這裏看到整個倉庫的內容。
我們在項目的build.gradle 文件中如下定義倉庫,就能使用jcenter了:
Maven Central
Maven Central 則是由sonatype.org維護的Maven倉庫。你可以在這裏看到整個倉庫。
注:不管是jcenter還是Maven Central ,兩者都是Maven倉庫
我們在項目的build.gradle 文件中如下定義倉庫,就能使用Maven Central了:
allprojects {
repositories {
mavenCentral()
}
}
注意,雖然jcenter和Maven Central 都是標準的 android library倉庫,但是它們維護在完全不同的服務器上,由不同的人提供內容,兩者之間毫無關係。在jcenter上有的可能 Maven Central 上沒有,反之亦然。
除了兩個標準的服務器之外,如果我們使用的library的作者是把該library放在自己的服務器上,我們還可以自己定義特有的Maven倉庫服務器。Twitter的Fabric.io 就是這種情況,它們在https://maven.fabric.io/public上維護了一個自己的Maven倉庫。如果你想使用Fabric.io的library,你必須自己如下定義倉庫的url。
repositories {
maven { url 'https://maven.fabric.io/public' }
}
然後在裏面使用相同的方法獲取一個library。
dependencies {
compile 'com.crashlytics.sdk.android:crashlytics:2.2.4@aar'
}
但是將library上傳到標準的服務器與自建服務器,哪種方法更好呢?當然是前者。如果將我們的library公開,其他開發者除了一行定義依賴名的代碼之外不需要定義任何東西。因此這篇文章中,我們將只關注對開發者更友好的jcenter 和 Maven Central 。
實際上可以在Android Studio上使用的除了Maven 倉庫之外還有另外一種倉庫:Ivy 倉庫
理解jcenter和Maven Central
爲何有兩個標準的倉庫?
事實上兩個倉庫都具有相同的使命:提供Java或者Android library服務。上傳到哪個(或者都上傳)取決於開發者。
起初,Android Studio 選擇Maven Central作爲默認倉庫。如果你使用老版本的Android Studio創建一個新項目,mavenCentral()會自動的定義在build.gradle中。
但是Maven Central的最大問題是對開發者不夠友好。上傳library異常困難。上傳上去的開發者都是某種程度的極客。同時還因爲諸如安全方面的其他原因,Android Studio團隊決定把默認的倉庫替換成jcenter。正如你看到的,一旦使用最新版本的Android Studio創建一個項目,jcenter()自動被定義,而不是mavenCentral()。
有許多將Maven Central替換成jcenter的理由,下面是幾個主要的原因。
- jcenter通過CDN發送library,開發者可以享受到更快的下載體驗。
- jcenter是全世界最大的Java倉庫,因此在Maven Central 上有的,在jcenter上也極有可能有。換句話說jcenter是Maven Central的超集。
- 上傳library到倉庫很簡單,不需要像在 Maven Central上做很多複雜的事情
-
友好的用戶界面
基於上面的原因以及我自己的經驗,可以說替換到jcenter是明智之舉。
gradle是如何從倉庫上獲取一個library的?
我們在 build.gradle輸入如下代碼的時候,這些庫是如果奇蹟般下載到我們的項目中的。
compile 'com.inthecheesefactory.thecheeselibrary:fb-like:0.9.3'
一般來說,我們需要知道library的字符串形式,包含3部分
GROUP_ID:ARTIFACT_ID:VERSION
上面的例子中,GROUP_ID是com.inthecheesefactory.thecheeselibrary ,ARTIFACT_ID是fb-like,VERSION是0.9.3。
GROUP_ID定義了library的group。有可能在同樣的上下文中存在多個不同功能的library。如果library具有相同的group,那麼它們將共享一個GROUP_ID。通常我們以開發者包名緊跟着library的group名稱來命名,比如com.squareup.picasso。然後ARTIFACT_ID中是library的真實名稱。至於VERSION,就是版本號而已,雖然可以是任意文字,但是我建議設置爲x.y.z的形式,如果喜歡還可以加上beta這樣的後綴。
下面是Square library的一個例子。你可以看到每個都可以很容易的分辨出library和開發者的名稱。
dependencies {
compile 'com.squareup:otto:1.3.7'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
}
那麼在添加了上面的依賴之後會發生什麼呢?簡單。Gradle會詢問Maven倉庫服務器這個library是否存在,如果是,gradle會獲得請求library的路徑,一般這個路徑都是這樣的形式:GROUP_ID/ARTIFACT_ID/VERSION_ID。比如可以在http://jcenter.bintray.com/com/squareup/otto/1.3.7 和 https://oss.sonatype.org/content/repositories/releases/com/squareup/otto/1.3.7/
下獲得com.squareup:otto:1.3.7的library文件。
然後Android Studio 將下載這些文件到我們的電腦上,與我們的項目一起編譯。整個過程就是這麼簡單,一點都不復雜。
我相信你應該清楚的知道從倉庫上下載的library只是存儲在倉庫服務器上的jar 或者aar文件而已。有點類似於自己去下載這些文件,拷貝然後和項目一起編譯。但是使用gradle依賴管理的最大好處是你除了添加幾行文字之外啥也不做。library一下子就可以在項目中使用了。
瞭解aar文件
我剛纔說了倉庫中存儲的有兩種類型的library:jar 和 aar。jar文件大家都知道,但是什麼是aar文件呢?
aar文件是在jar文件之上開發的。之所以有它是因爲有些Android Library需要植入一些安卓特有的文件,比如AndroidManifest.xml,資源文件,Assets或者JNI。這些都不是jar文件的標準。
因此aar文件就是發明出來包含所有這些東西的。總的來說它和jar一樣只是普通的zip文件,不過具有不同的文件結構。jar文件以classes.jar的名字被嵌入到aar文件中。其餘的文件羅列如下:
- /AndroidManifest.xml (mandatory)
- /classes.jar (mandatory)
- /res/ (mandatory)
- /R.txt (mandatory)
- /assets/ (optional)
- /libs/*.jar (optional)
- /jni//*.so (optional)
- /proguard.txt (optional)
- /lint.jar (optional)
可以看到.aar文件是專門爲安卓設計的。因此這篇文章將教你如何創建與上傳一個aar形式的library。
build.gradle與gradle-warpper 的區別和聯繫
如圖中圈出位置所示,這倆個文件在項目中的位置。
build.gradle 文件制定編譯時的一些條件和依賴關係。
gradle-warpper.properties主要用來制定當前使用的gradle版本從哪裏獲取。以及一些其他的參數。
下面來分析一下這倆文件中的內容:
- build.gradle
這個文件的內容並不是固定的,根據項目的需要會有不同的設置。這裏給出一般情況下的內容:
這是Module的gradle文件
//這裏指明這是一個android工程,也可以填com.android.library
//指明這是一個類庫
apply plugin: 'com.android.application'
android {
//使用的編譯版本SDK21
compileSdkVersion 21
//buildtool版本 指定爲21.1.1
buildToolsVersion 21.1.1
defaultConfig {
//最小SDK17
minSdkVersion 17
//目標版本19
targetSdkVersion 19
}
// 打包簽名
signingConfigs {
//指定debug模式下使用的簽名文件
debug { storeFile file("debug.keystore") }
release {
//發佈正式版本模式下的使用的簽名文件
storeFile file('release.keystore')
storePassword 'thisiskeystorepassword'
keyAlias 'nim_demo'
keyPassword 'thisiskeypassword'
}
}
//編譯時腳本運行環境
buildTypes {
debug {
signingConfig signingConfigs.debug
manifestPlaceholders = [AMAP_KEY: "09fd4efd3e28e9bf1f449ecec7d34bfe"]
}
//正式版本要混淆
release {
minifyEnabled true
zipAlignEnabled true
proguardFile('proguard.cfg')
signingConfig signingConfigs.release
manifestPlaceholders = [AMAP_KEY: "ee20324fba1c7f4ad7a4a207e7f08e8d"]
}
}
sourceSets {
main {
//指定文件映射關係
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res', 'res-avchat', 'res-chatroom']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs', 'libs-sdk']
}
}
//防止lint時報錯
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
}
//添加依賴jar,庫工程
dependencies {
//依賴文件夾下的所有文件
compile fileTree(dir: 'libs', exclude: ['android-support-*.jar'], include: '*.jar')
compile project(path: ':uikit')
compile 'com.android.support:appcompat-v7:21.0.3'
}
一個根目錄下的gradle文件,這個文件的設置對project下的所有module都是有效的
buildscript {
//指定要使用的gradle版本
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
// apply from: 'script.gradle', to: buildscript
}
//指定遠程倉庫,建議使用jcenter
allprojects {
repositories {
jcenter()
}
}
一個gradle-wrapper。properties文件。只要設置gradle的緩存地址和下載地址。
#Wed May 18 07:57:25 CST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#指定gradle的下載地址
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip