Gradle ve fazlası —part1

Android projelerinin build yönetim sistemi olan Gradle ile ilgili önem arz eden birçok bilgiyi bu yazımda bulabilirsiniz.

Gradle nedir?

Proje resource’larını ve kaynak kodunu derleyen, ve test edilebilen, derlenen, imzalanabilen veya yayınlanabilen APK çıktıları oluşturmamıza yarayan build sistemidir.

EK: Android Studio, build süreçlerini yönetmek ve otomatize etmek için Gradle’ı tercih etmiştir. Dolayısıyla Android uygulama geliştirmede iyi bir noktaya gelmek isteyen her uygulama geliştirici, Gradle’ı çok iyi özümsemeli ve bu konudaki bilgi birikimini arttırmalıdır.

Build Types ve Build Flavors

Android default olarak iki farklı build tipini kullanır. Bunlar debug ve release olmak üzere iki tanedir. Bu build tipleri için eğer istersek, farklı build flavor’lar ekleyebiliriz. Buna hangi durumlarda ihtiyaç duyabiliriz? Örneğin, telefon ve tabletler için ayrı ayrı iki build çeşidi tanımlayabiliriz. Veya, uygulamamızın ücretli veya ücretsiz iki farklı sürümü için yine iki farklı flavor oluşturabiliriz. Tıpkı aşağıdaki gibi:

productFlavors {
paid {
applicationId ="com.burakeraykayis.app.paid"
versionName = "1.0-paid"
}

free {
applicationId = com.burakeraykayis.app.free"
versionName = "1.0-free"
}
}

Bunları ekleyip projemizi Sync yaptıktan sonra Android Studio’da Build Variant’s sekmesine gittiğimizde variant olarak şunlar listelenecektir:

  • freeDebug
  • freeRelease
  • paidDebug
  • paidRelease

Artık, projemize sık kullanılan tabirle ortam eklemeyi anlamış olduk.

Android kod bloğu

Module düzeyindeki build.gradle dosyamıza baktığımızda şuna benzer bir kod bloğu görürüz. Burada android kod bloğu içerisinde uygulamamızla ilgili çok temel, veya diğer bir deyişle core kararlar veririz. Buraya manuel bir müdahale yapmamış olmamız, bu kararları vermediğimiz anlamına gelmez. Çünkü Android Studio, projenin build edilmesinde direkt olarak burayı referans alır, buradaki bir takım rakamsal kararları işletir. Bu konuyla ilgili önemli bir detayı da yazımın devamında sizlerle paylaşacağım.

Aşağıda standart bir android kod bloğunu görmemiz mümkün:

android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.burakeraykayis.app"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
...
}

Bu kod bloğunda bir takım tanımlamalar ve karşılıkları mevcut, bu tanımlarla ilgili daha derin bilgilere geçmenin vakti geldi.

API Level
Burada hemen API level kavramının üzerinden kısaca geçelim, çünkü Gradle’daki api level tanımlarına gelmeden önce bu konuda net bir bilgiye sahip olmamız mutlaka şart.
Api level, Android platformu tarafından sunulmuş API revizyonlarını tanımlayan, benzersiz integer değerlerdir. Her yeni sürümde, Android’i geliştiren kişiler, developer’a cihazlarla daha iyi iletişim kurması için bir takım yenilikler sunmayı hedefler.
Örneklerle gidersek, API Level 21'e geçişte Material Design ile ilgili geliştirmeler API’ye dahil edilmişken, API level 23'e geçişte Runtime Permissions geldi ve aytıca Apache HttpClient SDK’den tamamen kaldırıldı. API level kavramı geriye dönük uyumluluk konusuyla doğrudan ilişkili, önemli bir kavramdır. Bu anlamda hangi API level’da, hangi büyük değişikliklerin yapıldığını bilmek önemli bir konudur. Bu konuda daha derin bilgiye erişmek için resmi dökümantasyondaki API Level içeriğini okumanızı mutlaka öneririm.

Biraz yukarıda paylaştığım kod bloğu üzerinde sırayla ilerleyelim:

compileSdkVersion: Bu değer, hangi API’ye kadar getirilmiş özellikleri projemizde kullanabileceğimizi belirler. Örneğin , bu değer 18 olarak belirlenmişken, API 19 veya üstü bir level’da SDK’e eklenmiş bir özelliği kullanmamız mümkün olmayacaktır. ancak 18 de dahil olmak üzere Android’in doğuşundan bugüne, yani API 1'den itibaren var olan tüm özellikleri kullanabiliriz, tam anlamıyla geriye dönük uyumluluk söz konusudur. Bunlardan birçoğu deprecated, yani miadı dolmuş olabilir ancak bunları kullanmamız uygulamamızın derlenmesi veya çalışmasında herhangi bir problem teşkil etmeyecektir.

Not: Her şekilde, mevcut en üst compileSdkVersion’un kullanılmasını öneririm. Neden Android SDK’ine eklenmiş bir özelliği kullanmaktan kendimizi aciz bırakalım ki? (Çok istisnai durumlarda önermem geçersizdir ancak detaylarını bir başka yazıda inceleyelim.)

buildsToolsVersion: Uygulamamızın, derleyicisinin sürümünü belirlemek için kullanılan tanımlamadır. Build Tool’ların geliştirme ortamımıza kurulması Android Studio SDK Manager üzerinden yapılmakta ve buraya yazdığımız versiyon, mutlaka bilgisayarımıza önceden indirilmiş bir versiyon olmalıdır. Eğer indirilmemişse, projemizin derlenmesi sırasında Android Studio, bize bir uyarı verecek ve buradan ulaştığımız bir link yardımıyla, doğrudan bu versiyona ait build tool’u uzak sunucudan indirip kurmamızı sağlayacaktır.

minSdkVersion

Uygulamamızın hangi API level ve üstü cihazlarda çalışabileceğini belirlediğimiz tanımlamadır.

Ayrıca kodumuzu yazarken bize yanlış bir şey yaptığımızda uyarı veren LINT, minSdkVersion tanımında kullandığımız değerin üzerinde bir API level gerektiren bir kullanım yaptığımızda, bizi hemen uyaracak ve minSdkVersion’u gerekli değere yükseltmemizi söyleyecektir.

targetSdkVersion

Bu tanımlamada verdiğimiz değer ile şunu söylemiş oluruz, benim uygulamam bu API level’da sağlıklı bir şekilde çalışıyor.

Şimdi neden kullanırız, buna bakalım:

Biliyoruz ki Android’de API’ler değiştikçe component’lerin davranışları veya görünümlerinde değişiklikler olabiliyor. Örneğin TimePickerDialog üzerinden gidersek, standart kütüphanede eskiden saat ve dakikayı wheel picker’lar ile seçtirirken yenilenen API’lerle birlikte saat kadranı üzerinde, kullanıcının akrep ve yelkovanı hareket ettirmesiyle seçtiriyor.

İşte bu tarz gelebilecek değişiklikler için, ileriye dönük uyumluluk adına, hem eski api level’larda eski görünümüyle ve davranışlarıyla çalışması, hem de yeni api level cihazlarda güncel haliyle çalışması için targetSdkVersion tanımlamasını kullanırız.

En önemli dikkat edilmesi gereken husus, targetSdkVersion değerine yazdığımız API Level’da mutlaka uygulamamızı test etmeli, ve doğru ve sağlıklı çalıştığını görmeliyiz. Aksi taktirde, kullanıcılar bu değerin olması gerekenden daha yüksek bir değer yazılmış olmasından olumsuz etkilenebilir ve çalışma zamanında hata alabilirler.

EK: Bu değere bir şey yazmaz isek, default olarak minSdkVersion’a eşit olarak kabul edilir.

İdeal olan hangisi?

Gradle’daki version tanımlamalarını anladık, ne olduğunu öğrendik. Peki tüm bu bilgiler ışığında, nasıl bir değer tanımlaması ideal olacaktır, bu konudaki kendi önermem şu olacaktır:

minSdkVersion (olabildiğince düşük) <= 
targetSdkVersion == compileSdkVersion (var olan en son SDK)

Burada minSdkVersion için olabildiğine düşük ibaresini kullanma sebebim, ne kadar düşük olursa, o kadar çok kullanıcıya hitap etmiş oluyoruz. Ancak günümüzde API level 15 ve üstü şeklinde yapılacak bir tercih, tüm dünyadaki Android işletim sistemli telefon ve tabletlerin %97'si gibi bir oranını kapsayabildiğini de unutmayalım.

Dipnot: Biliyoruz ki sdkVersion tanımları Android Manifest’te de yapılmaktadır. Buradaki kilit bilgi, gradle’da yapılan tanımlamalar manifest’teki tanımlamaları ezer, override eder. Dolayısıyla, gradle’da tanımlandıysa, manifest’teki tanımlamaların bir hükmü yoktur.

Gradle ile ilgili yazı dizimin ilk bölümüne burada son veriyorum. Umarım açıklayıcı ve maksadını yerine getirebilen bir yazı olmuştur.

Burak Eray KAYIŞ