Firebase ve Jetpack Compose ile Android uygulaması geliştirme

1. Giriş

Son Güncelleme: 16.11.2022

Firebase ve Jetpack Compose ile Android uygulaması geliştirme

Bu codelab'de Make It So adlı bir Android uygulaması geliştireceksiniz. Bu uygulamanın kullanıcı arayüzü tamamen Jetpack Compose ile oluşturulmuştur. Android'in yerel kullanıcı arayüzü oluşturmaya yönelik modern araç seti olan bu uygulama sezgiseldir ve .xml dosyaları yazıp Etkinliklere, Parçalara veya Görünümlere bağlamaktan daha az kod gerektirir.

Firebase ve Jetpack Compose'un birlikte ne kadar iyi çalıştığını anlamanın ilk adımı, modern Android mimarisini anlamaktır. İyi bir mimari, bileşenlerin nasıl düzenlendiğini ve birbirleriyle iletişim kurduklarını çok açık hale getirdiği için sistemin anlaşılmasını, geliştirilmesini ve bakımını kolaylaştırır. Android dünyasında, önerilen mimari Model - View - ViewModel olarak adlandırılır. Model, uygulamadaki Verilere erişen katmanı temsil eder. Görünüm, kullanıcı arayüzü katmanıdır ve iş mantığı hakkında hiçbir şey bilmemelidir. ViewModel, iş mantığının uygulandığı yerdir. Bu da bazen ViewModel'in Model katmanını çağırmasını gerektirir.

Kod tabanının anlaşılmasını ve sonraki adımların tamamlanmasını kolaylaştıracağı için Model - View - ViewModel'in Jetpack Compose ile oluşturulan bir Android uygulamasına nasıl uygulandığını anlamak için bu makaleyi okumanızı önemle tavsiye ederiz.

Oluşturacaklarınız

Yapılacaklar Listesi, kullanıcının görev ekleyip düzenlemesine, bayraklar, öncelikler ve son tarihler eklemesine ve görevleri tamamlandı olarak işaretlemesine olanak tanıyan basit bir yapılacaklar listesi uygulamasıdır. Aşağıdaki resimlerde bu uygulamanın iki ana sayfası gösterilmektedir: Görev oluşturma sayfası ve oluşturulan görevlerin listesinin yer aldığı ana sayfa.

Görev Ekle ekranı Ana ekran olarak ayarla

Bu uygulamada bulunmayan bazı özellikleri ekleyeceksiniz:

  • Kullanıcıların kimliğini e-posta ve şifreyle doğrulama
  • Firestore koleksiyonuna işleyici ekleme ve kullanıcı arayüzünün değişikliklere tepki vermesini sağlama
  • Uygulamadaki belirli bir kodun performansını izlemek için özel izler ekleyin.
  • Remote Config'i kullanarak bir özellik açma/kapatma düğmesi oluşturun ve özelliği başlatmak için aşamalı sunumu kullanın

Neler öğreneceksiniz?

  • Modern Android uygulamasında Firebase Authentication, Performance Monitoring, Remote Config ve Cloud Firestore'u kullanma
  • Firebase API'lerini MVVM mimarisine uygun hâle getirme
  • Firebase API'leriyle yapılan değişiklikleri Compose kullanıcı arayüzünde yansıtma

Gerekenler

2. Örnek uygulamayı indirin ve Firebase'i kurun

Örnek uygulamanın kodunu alma

GitHub deposunu komut satırından klonlayın:

git clone https://github.com/FirebaseExtended/make-it-so-android.git

Firebase'i ayarlama

İlk yapmanız gereken, Firebase konsoluna gitmek ve "+ Proje ekle"yi tıklayarak bir Firebase projesi oluşturmaktır. aşağıdaki gibi düğmeyi tıklayın:

Firebase konsolu

Proje oluşturma işlemini tamamlamak için ekrandaki adımları uygulayın.

Her Firebase projesinde Android, iOS, Web, Flutter ve Unity için farklı uygulamalar oluşturabilirsiniz. Burada gördüğünüz gibi Android seçeneğini belirleyin:

Firebase Projesine Genel Bakış

Ardından aşağıdaki adımları uygulayın:

  1. Paket adı olarak com.example.makeitso yazın ve isteğe bağlı olarak bir takma ad girin. Bu codelab için hata ayıklama imzalama sertifikasını eklemeniz gerekmez.
  2. Uygulamanızı kaydetmek ve Firebase yapılandırma dosyasına erişmek için Sonraki'yi tıklayın.
  3. Yapılandırma dosyanızı indirmek ve make-it-so-android/app dizinine kaydetmek için Google-services.json dosyasını indir'i tıklayın.
  4. İleri'yi tıklayın. Firebase SDK'ları örnek projedeki build.gradle dosyasına zaten dahil edildiğinden Sonraki'yi tıklayarak Sonraki adımlar'a geçin.
  5. İşlemi tamamlamak için Konsola devam et'i tıklayın.

Make it So uygulamasının düzgün çalışması için, koda geçmeden önce Console'da iki şey yapmanız gerekir: Kimlik doğrulama sağlayıcılarını etkinleştirin ve Firestore veritabanını oluşturun. Öncelikle, kullanıcıların uygulamaya giriş yapabilmesi için Kimlik doğrulamayı etkinleştirelim:

  1. Build (Derleme) menüsünde, Authentication'ı (Kimlik Doğrulama) seçin ve Get Started (Başlayın) seçeneğini tıklayın.
  2. Oturum açma yöntemi kartında E-posta/Şifre'yi seçin ve etkinleştirin.
  3. Ardından Yeni sağlayıcı ekle'yi tıklayın ve Anonim'i seçip etkinleştirin.

Sonra, Firestore'u kurun. Oturum açmış kullanıcıların görevlerini depolamak için Firestore kullanılır. Her kullanıcı, veritabanının bir koleksiyonunda kendi dokümanını alır.

  1. Derleme menüsünden Firestore'u seçip Veritabanı oluştur'u tıklayın.
  2. Üretim modunda başlat'ı etkin durumda tutun ve İleri'yi tıklayın.
  3. İstendiğinde Cloud Firestore verilerinizin depolanacağı konumu seçin. Bir üretim uygulaması geliştirirken bunun, kullanıcılarınızın çoğuna yakın bir bölgede ve Functions gibi diğer Firebase hizmetlerinde ortak bir yerde olmasını istersiniz. Bu codelab için varsayılan bölgeyi koruyabilir veya size en yakın bölgeyi seçebilirsiniz.
  4. Firestore veritabanınızı sağlamak için Etkinleştir'i tıklayın.

Şimdi de Firestore veritabanı için sağlam Güvenlik Kuralları oluşturalım. Firestore kontrol panelini açıp Kurallar sekmesine gidin. Ardından, Güvenlik Kurallarını aşağıdaki gibi güncelleyin:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

Bu kurallar temel olarak, uygulamada oturum açan her kullanıcının herhangi bir koleksiyonda kendisi için doküman oluşturabilmesini sağlar. Doküman oluşturulduktan sonra yalnızca söz konusu dokümanı oluşturan kullanıcı dokümanı görüntüleyebilir, güncelleyebilir veya silebilir.

Uygulamayı çalıştırma

Artık uygulamayı çalıştırmaya hazırsınız. Android Studio'da make-it-so-android/start klasörünü açın ve uygulamayı çalıştırın (Android Emülatör veya gerçek bir Android cihaz kullanarak yapılabilir).

3. Firebase Authentication

Hangi özelliği ekleyeceksiniz?

Make It So örnek uygulamasının mevcut durumunda, kullanıcı oturum açmak zorunda kalmadan uygulamayı kullanmaya başlayabilir. Bunun için anonim kimlik doğrulama kullanır. Ancak anonim hesaplar, kullanıcının başka cihazlarda veya gelecekteki oturumlarda verilerine erişmesine izin vermez. Anonim kimlik doğrulama, hazır durumda ilk katılım için kullanışlı olsa da kullanıcılara her zaman farklı bir oturum açma formuna dönüştürme seçeneği sunmalısınız. Bu doğrultuda, bu codelab'de Make It So uygulamasına e-posta ve şifreyle kimlik doğrulaması ekleyeceksiniz.

Kodlama zamanı!

Kullanıcı bir hesap oluşturur oluşturmaz, e-posta ve şifre yazarak Firebase Authentication API'den e-posta kimlik bilgilerini istemeniz ve yeni kimlik bilgisini anonim hesaba bağlamanız gerekir. AccountServiceImpl.kt dosyasını Android Studio'da açın ve linkAccount işlevini aşağıdaki gibi güncelleyin:

model/service/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

Şimdi SignUpViewModel.kt öğesini açın ve onSignUpClick işlevinin launchCatching bloğundaki linkAccount hizmetini çağırın:

screen/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

Öncelikle kimlik doğrulamasını yapmaya çalışır ve arama başarılı olursa sonraki ekrana (SettingsScreen) geçer. Bu çağrıları bir launchCatching bloğu içinde yürütürken, ilk satırda bir hata oluşursa istisna yakalanıp işlenir ve ikinci satıra hiçbir şekilde ulaşılmaz.

SettingsScreen tekrar açılır açılmaz, kullanıcının kimliği zaten doğrulandığından Oturum aç ve Hesap oluştur seçeneklerinin kaybolduğundan emin olmanız gerekir. Bunu yapmak için hesabın anonim olup olmadığını kontrol etmek üzere SettingsViewModel öğesinin, geçerli kullanıcının durumunu dinlemesini (AccountService.kt ürününde mevcuttur) sağlayalım. Bunun için SettingsViewModel.kt içindeki uiState öğesini aşağıdaki gibi güncelleyin:

screen/settings/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

Yapmanız gereken son işlem, SettingsViewModel tarafından yayınlanan durumları toplamak için SettingsScreen.kt içindeki uiState öğesini güncellemektir.

screen/settings/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

Artık kullanıcı her değiştiğinde SettingsScreen, seçenekleri kullanıcının yeni kimlik doğrulama durumuna göre görüntülemek için kendini yeniden oluşturacak.

Test etme zamanı

Make it so'yu (Öyleyse yap) çalıştırın ve ekranın sağ üst köşesindeki dişli simgesini tıklayarak ayarlara gidin. Buradan hesap oluştur seçeneğini tıklayın:

İzin modu ayarları ekranı Öyle olsun kayıt ekranı

Hesabınızı oluşturmak için geçerli bir e-posta ve güçlü bir şifre yazın. Bağlantı işlemi çalışır. Oturumu kapatma ve hesabınızı silme olmak üzere iki yeni seçenek göreceğiniz ayarlar sayfasına yönlendirilirsiniz. Firebase konsolundaki Authentication kontrol panelinde oluşturulan yeni hesabı Kullanıcılar sekmesini tıklayarak kontrol edebilirsiniz.

4. Cloud Firestore

Hangi özelliği ekleyeceksiniz?

Cloud Firestore için Firestore koleksiyonuna, Yapılacak İş bölümünde gösterilen görevleri temsil eden belgelerin depolandığı bir işleyici eklemeniz gerekir. Bu işleyiciyi eklediğinizde koleksiyonda yapılan tüm güncellemeleri alırsınız.

Kodlama zamanı!

StorageServiceImpl.kt uygulamasında bulunan Flow öğesini aşağıdaki gibi güncelleyin:

model/service/impl/StorageServiceImpl.kt

override val tasks: Flow<List<Task>>
    get() =
      auth.currentUser.flatMapLatest { user ->
        firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
      }

Bu kod, user.id temel alınarak görev koleksiyonuna bir işleyici ekliyor. Her görev, tasks adlı bir koleksiyondaki dokümanla temsil edilir ve her görevin userId adlı alanı vardır. currentUser durumu değişirse (örneğin, çıkış yaparak) yeni bir Flow gönderileceğini unutmayın.

Şimdi TasksViewModel.kt içindeki Flow öğesinin hizmettekilerle aynı olmasını sağlamanız gerekiyor:

ekranlar/görevler/GörevlerViewModel.kt

val tasks = storageService.tasks

Son olarak, kullanıcı arayüzünü temsil eden TasksScreens.kt içinde composable function öğesini yapmak, bu akıştan haberdar olmak ve bir durum olarak toplamaktır. Durum her değiştiğinde, composable işlevi otomatik olarak kendini yeniden oluşturur ve kullanıcıya en son durumu gösterir. Bunu TasksScreen composable function bölümüne ekleyin:

ekranlar/görevler/GörevlerEkranı.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

composable işlevi bu durumlara erişim elde ettikten sonra, LazyColumn öğesini (listeyi ekranda görüntülemek için kullandığınız yapı) şu şekilde güncelleyebilirsiniz:

ekranlar/görevler/GörevlerEkranı.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

Test etme zamanı

İşe yarayıp yaramadığını test etmek için uygulamayı kullanarak (ekranın sağ alt köşesindeki ekle düğmesini tıklayarak) yeni bir görev ekleyin. Görev, oluşturulduktan sonra Firestore Konsolu'ndaki Firestore koleksiyonunda görünür. Aynı hesapla diğer cihazlarda Yapılacak İş'e giriş yaparsanız yapılacak işlerinizi düzenleyebilir ve tüm cihazlarda gerçek zamanlı olarak güncellenmelerini izleyebilirsiniz.

5. Performance Monitoring

Hangi özelliği ekleyeceksiniz?

Performansın iyi olmaması ve kullanıcıların uygulamanızı kullanarak basit bir işi tamamlamaları çok fazla zaman gerektirmesi nedeniyle, kullanıcıların uygulamanızı kullanmaktan vazgeçme olasılıkları yüksektir. Bu nedenle performansa dikkat etmek önemlidir. Bu nedenle bazen bir kullanıcının uygulamanızda izlediği belirli bir yolculukla ilgili bazı metrikleri toplamak yararlı olabilir. Firebase Performance Monitoring, size bu konuda yardımcı olmak için özel izler sunar. Yapılacak İş bölümünde özel izler eklemek ve performansı farklı kod parçalarında ölçmek için sonraki adımları uygulayın.

Kodlama zamanı!

Performance.kt dosyasını açarsanız trace adlı bir satır içi işlev görürsünüz. Bu işlev, iz adını parametre olarak ileterek özel bir iz oluşturmak için Performance Monitoring API'yi çağırır. Gördüğünüz diğer parametre, izlemek istediğiniz kod bloğudur. Her iz için toplanan varsayılan metrik, tamamen çalıştırılma süresidir:

model/service/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

Kod tabanının ölçülmesinin önemli olduğunu düşündüğünüz hangi bölümlerini seçebilir ve bu bölümlere özel izler ekleyebilirsiniz. Bu codelab'de daha önce (AccountServiceImpl.kt ürününde) gördüğünüz linkAccount işlevine özel iz eklemeye dair bir örneği aşağıda bulabilirsiniz:

model/service/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String): Unit =
  trace(LINK_ACCOUNT_TRACE) {
      val credential = EmailAuthProvider.getCredential(email, password)
      auth.currentUser!!.linkWithCredential(credential).await()
  }

Şimdi sıra sizde! Make it So (Öyleyse Yap) uygulamasına birkaç özel izler ekleyin ve beklendiği gibi çalışıp çalışmadığını test etmek için bir sonraki bölüme geçin.

Test etme zamanı

Özel izleri eklemeyi bitirdikten sonra uygulamayı çalıştırın ve ölçmek istediğiniz özellikleri birkaç kez kullandığınızdan emin olun. Ardından, Firebase konsoluna ve Performans kontrol paneli'ne gidin. Ekranın altında üç sekme görürsünüz: Ağ istekleri, Özel izler ve Ekran oluşturma.

Özel izler sekmesine giderek kod tabanına eklediğiniz izlerin burada gösterildiğinden ve bu kod parçalarını yürütmek için genellikle ne kadar zaman gerektiğini kontrol edin.

6. Remote Config

Hangi özelliği ekleyeceksiniz?

Remote Config'in, uygulamanızın görünümünü uzaktan değiştirmekten farklı kullanıcı segmentleri için farklı davranışlar yapılandırmaya kadar çok çeşitli kullanım alanları vardır. Bu codelab'de, Yapılacak İş uygulamasındaki yeni görev düzenleme özelliğini gösterecek veya gizleyecek bir özellik açma/kapatma düğmesi oluşturmak için Remote Config'i kullanacaksınız.

Kodlama zamanı!

İlk yapmanız gereken, Firebase konsolunda yapılandırmayı oluşturmaktır. Bunu yapmak için Remote Config kontrol paneline giderek Parametre ekle düğmesini tıklamanız gerekir. Alanları aşağıdaki resme göre doldurun:

Remote Config Parametre Oluşturma iletişim kutusu

Tüm alanlar doldurulduktan sonra Save (Kaydet) düğmesini ve ardından Publish'i (Yayınla) tıklayabilirsiniz. Parametre oluşturulduğuna ve kod tabanınızda kullanılabildiğine göre, yeni değerleri uygulamanıza getirecek kodu eklemeniz gerekir. ConfigurationServiceImpl.kt dosyasını açın ve şu iki işlevin uygulama ayarlarını güncelleyin:

model/service/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

İlk işlev, değerleri sunucudan getirir ve uygulama başlar başlamaz SplashViewModel.kt işlevinde çağrılır. En güncel değerlerin en başından itibaren tüm ekranlarda bulunmasını sağlamanın en iyi yoludur. Daha sonra kullanıcı bir şeyler yaparken uygulamanın arayüzünü veya davranışını değiştirirseniz iyi bir kullanıcı deneyimi olmaz.

İkinci işlev, Console'da az önce oluşturduğunuz parametre için yayınlanan boole değerini döndürür. Ayrıca loadTaskOptions işlevine aşağıdakini ekleyerek bu bilgileri TasksViewModel.kt biçiminde almanız gerekir:

ekranlar/görevler/GörevlerViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

İlk satırdaki değeri alıyor ve ikinci satırdaki görev öğelerine ilişkin menü seçeneklerini yüklemek için bu değeri kullanıyorsunuz. Değer false ise menüde düzenleme seçeneği bulunmaz. Artık seçenekler listeniz olduğuna göre, kullanıcı arayüzünün bu listeyi doğru bir şekilde görüntülemesi gerekir. Jetpack Compose ile uygulama oluştururken TasksScreen kullanıcı arayüzünün nasıl görünmesi gerektiğini açıklayan composable function öğesini bulmanız gerekir. TasksScreen.kt dosyasını açın ve LazyColum dosyasını, TasksViewModel.kt içinde sunulan seçeneklere işaret edecek şekilde güncelleyin:

ekranlar/görevler/GörevlerEkranı.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

TaskItem, tek bir görevin kullanıcı arayüzünün nasıl görünmesi gerektiğini açıklayan bir diğer composable function öğesidir. Her görevde, kullanıcı görevin sonundaki üç nokta simgesini tıkladığında görüntülenen seçeneklerin bulunduğu bir menü vardır.

Test etme zamanı

Artık uygulamayı çalıştırmaya hazırsınız. Firebase konsolunu kullanarak yayınladığınız değerin, uygulamanın davranışıyla eşleştiğinden emin olun:

  • Adresiniz false ise üç nokta simgesini tıkladığınızda yalnızca iki seçenek görürsünüz;
  • Adresiniz true ise üç nokta simgesini tıkladığınızda üç seçenek görürsünüz;

Değeri Console'da birkaç kez değiştirip uygulamayı yeniden başlatmayı deneyin. Remote Config'i kullanarak uygulamanızda yeni özellikleri başlatmak işte bu kadar kolay!

7. Tebrikler

Tebrikler, Firebase ve Jetpack Compose ile başarıyla bir Android uygulaması oluşturdunuz.

Kullanıcı arayüzü için tamamen Jetpack Compose ile oluşturulmuş bir Android uygulamasına Firebase Authentication, Performance Monitoring, Remote Config ve Cloud Firestore'u eklediniz ve bunu önerilen MVVM mimarisine uygun hale getirdiniz.

Daha fazla bilgi

Referans belgeler