Phần 3 - Cách thêm thư viện (module) vào Android project

Một dự án Android luôn sử dụng các thư viện ngoài để giảm thiểu thời gian coding cũng như chi phí phát triển, đảm bảo tính tái sử dụng. Việc thêm thư viện hay một module vào dự án Android hiện nay là không khó và cực kỳ dễ dàng khi Gradle được tích hợp sử dụng trong một dự án Android. Để hiểu rõ hơn, chúng ta sẽ tạo một project Android. Mặc định, chúng ta sẽ có một file app/build.gradle khi project được tạo ra

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.simple.gradle"
        minSdkVersion 14
        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.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

Trong phạm vi bài viết ngày hôm nay chúng ta sẽ chỉ quan tâm đến file app/build.gradle trên, cụ thể là khối dependencies.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

Khai báo sử dụng bằng cách chỉnh sửa trực tiếp file build.gradle

Gradle cung cấp một số cách để khai báo sử dụng thư viện bên thứ 3. Tuy nhiên cách thông thường và hay được sử dụng là dạng 'group:name:version'. Ở các phiên bản gradle trước thì chúng ta sẽ sử dụng từ khóa compile, với phiên bản mới chúng ta sử dụng từ khóa implementation. Chúng ta có thể sử dụng thay dấu nháy đơn bằng dấu nháy kép, ví dụ sau đây sẽ cho thấy sự khác biệt giữa hai loại dấu này, chúng ta tạo một task trong gradle

task demo {
    String name = 'Gradle'
    println 'Hello $name'
    println "Hello $name"
}

sau đó run

./gradlew demo

kết quả như sau

Hello $name
Hello Gradle

Như vậy đối với dấu nháy kép chúng ta có thể sử dụng biến linh hoạt hơn. Cách thông thường sử dụng thư viện chúng ta hay sử dụng, ví dụ

testImplementation 'junit:junit:4.12'

Tuy nhiên trên được coi là cú pháp rút gọn, cụ thể rõ ràng chúng ra sẽ viết như sau, cách này được gọi là cú pháp đầy đủ

testImplementation group: 'junit', name: 'junit', version: '4.12'

Ngoài ra đối với version, chúng ta có thể khai báo không cụ thể phiên bản, ví dụ

testImplementation 'junit:junit:4.+'

Cách trên sẽ cho phép gradle sử dụng bất kỳ phiên bản JUnit nào lớn hơn hoặc bằng 4.0, cách này không được khuyến khích vì sẽ gây khó tái sử dụng. Do đó chúng ta nên chỉ định rõ phiên bản của một thư viện mà chúng ta muốn sử dụng như vậy sẽ dễ dàng kiểm soát dự án của chúng ta hơn. Đối với các file thư viện .jar chúng ta có thể sử dụng dễ dàng bằng từ khóa files hoặc fileTree

implementation files('libs/a.jar', 'libs/b.jar')
implementation fileTree(dir: 'libs', include: '*.jar')

Dòng lệnh đầu tiên sẽ chỉ định chúng ta muốn sử dụng những file jar nào, còn dòng lệnh thứ 2 sẽ cho phép sử dụng bất kỳ file .jar nào trong dường dẫn libs. Một trường hợp chúng ta cần chú ý là transitive dependencies, nghĩa là khi ta sử dụng một thư viện bên thứ 3 mà thư viện đó đã thêm thư viện khác thì mặc nhiên dự án của chúng ta có thể sử dụng cả thư viện khác đó. Ví dụ, nếu chúng ta sử dụng thư viện implementation 'com.squareup.retrofit2:retrofit:2.3.0' (đã có thư viện okhttpokio) thì chúng ta không cần khai báo sử dụng thư viện okhttpokio, điều sau đây là không cần thiết

implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.okhttp3:okhttp:3.9.1' // không cần thiết
implementation 'com.squareup.okhttp3:okhttp:3.9.1' // không cần thiết

Chúng ta có thể không sử dụng transitive dependencies bằng cách

implementation group:'com.squareup.retrofit2', name:'retrofit', version:'2.3.0',  transitive:false

Ngoài ra chúng ta có thể chỉ sử dụng module jar của thư viện mà không cần các dependency khác của thư viện đó thì chúng ta sử dụng từ khóa ext hoặc ký tự @, ví dụ

implementation 'org.codehaus.groovy:groovy-all:[email protected]'

hoặc

implementation group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.4', ext: 'jar'

Ngược lại, chúng ta có thể loại trừ một hoặc một số dependency mà không cần thiết hoặc đã được khai báo ở thư viện khác bằng từ khóa exclude

androidTestImplementation('org.spockframework:spock-core:1.0-groovy-2.4') {
    exclude group: 'org.codehaus.groovy'
    exclude group: 'junit'
}

Sử dụng Android Studio Tool

Chúng ta có thể nhanh chóng thêm hoặc tìm kiếm thư viện bên thứ 3 bằng tool mà Android Studio hỗ trợ. Chúng ta chọn File/Project Structure Sau đó chọn Dependencies và chọn dấu +, chúng ta có thể chọn loại là file jar, module hoặc library Tiếp theo chọn một thư viện nào đó rồi nhấn Ok, Android Studio sẽ tự động thêm vào file build.gradle.

Cấu hình Repositories

Vì mỗi thư viện đều được lưu trữ ở một repository nào đó (kho). Mặc định Android sử dụng hai kho jcenter() (https://jcenter.bintray.com) hoặc mavenCentral() (http://repo1.maven.org/maven2)

repositories {
     jcenter()
     mavenCentral()
}

Chúng ta có thể cấu hình một repo từ maven qua url

repositories {
    maven {
        credentials { // nếu cần thiết
            username 'username'
            password 'password'
        }
        url 'http://repo.mycompany.com/maven2'
    }
}

Ngoài ra chúng ta có thể thêm file từ local bằng cách

repositories {
    flatDir {
        dirs 'lib'
    }
}

Đây cũng là một cách thay thế cho cách khai báo trong dependencies block với filesfileTree. Chúng ta sẽ thường xuyên sử dụng nhiều repository khác nhau để build. Gradle sẽ tìm kiếm trong mỗi repository đó theo thứ tự từ trên xuống cho đến khi download xong toàn bộ dependencies của chúng ta trong project. Như vậy chúng ta đã hiểu thêm một chút về Gradle trong Android. Hy vọng bài viết sẽ giúp ích cho một số bạn 😄

Cảm ơn các bạn đã đọc bài viết. Happy coding!!!