Kotlin ve Jetpack Compose ile geliştirdiğim Dolap Hafızası uygulamasını Google Play’e çıkarırken öğrendiğim 5 önemli ders.
Google Play uygulama geliştirme deneyimi, yalnızca Android Studio’da çalışan bir uygulama hazırlayıp AAB dosyasını Play Console’a yüklemekten ibaret değil. Kotlin ve Jetpack Compose ile geliştirdiğim Dolap Hafızası uygulamasını gerçek kullanıcılara ulaştırdıktan sonra bunu çok daha net gördüm.
Geliştirme sırasında kod, mimari ve kullanıcı arayüzü ön plandayken uygulama Google Play’e çıktığında işin içerisine gerçek cihazlar, Android sürümleri, cihaz uyumluluğu, bildirim izinleri, arka plan kısıtlamaları, Play Console politikaları, kullanıcı geri bildirimleri ve mağaza optimizasyonu giriyor.
Kısacası uygulamanın Android Studio’da sorunsuz çalışması ile gerçek kullanıcıların telefonlarında sorunsuz çalışması aynı şey değil.
Bu yazıda Kotlin, Jetpack Compose, MVVM, Room, Flow, WorkManager, DataStore ve Firebase gibi teknolojileri kullandığım Dolap Hafızası projesinde karşılaştığım gerçek durumları ve bu süreçten çıkardığım 5 önemli dersi paylaşacağım.
Amacım Dolap Hafızası’nı tanıtmaktan çok, gerçek bir Android uygulamasını geliştirme aşamasından Google Play’e ve oradan gerçek kullanıcılara ulaştırma sürecinde öğrendiklerimi aktarmak.
Bir mobil uygulama geliştirirken zamanın büyük bölümünü doğal olarak kod tarafında geçiriyoruz.
Ekranlar hazırlanıyor, ViewModel’ler oluşturuluyor, veriler kaydediliyor, kullanıcı akışı test ediliyor ve uygulama emülatörde başarılı şekilde çalışıyor.
Bu aşamada insanda şöyle bir düşünce oluşabiliyor:
“Uygulama çalışıyor. Artık Google Play’e yükleyebilirim.”
Teknik olarak doğru olsa da gerçek ürün geliştirme süreci aslında burada yeni başlıyor.
Dolap Hafızası’nı geliştirirken kullandığım temel yapı şu şekildeydi:
Kotlin
↓
Jetpack Compose
↓
MVVM
↓
ViewModel
↓
Flow / StateFlow
↓
Room
↓
WorkManager
↓
DataStore
↓
Firebase Cloud Messaging Buna fotoğraf işlemleri, barkod, nesne tanıma, bildirimler, kullanıcı ayarları ve Google Play tarafındaki süreçler de eklendiğinde uygulama yalnızca birkaç Compose ekranından oluşan bir proje olmaktan çıkıyor.
Gerçek bir ürüne dönüşüyor.
Dolap Hafızası, evde bulunan eşyaların nerede saklandığını hatırlamayı kolaylaştırmak için geliştirdiğim Android uygulaması.
Temel fikir oldukça basit:
“Bu eşyayı nereye koymuştum?”
sorusuna uygulama içerisinden hızlı şekilde cevap verebilmek.
Kullanıcı evdeki odaları ve saklama alanlarını oluşturabiliyor, eşyalarını kaydedebiliyor ve daha sonra arama yaparak eşyanın nerede olduğunu bulabiliyor.
Uygulamada kullandığım özelliklerden bazıları:
Uygulama ağırlıklı olarak local-first mantığıyla çalışıyor.
Bu karar projenin ilerleyen aşamalarında düşündüğümden çok daha önemli hale geldi.
Android geliştirmede ilk öğrendiğim en önemli derslerden biri bu oldu.
Android Studio emülatörü geliştirme sırasında son derece kullanışlı. Farklı ekran boyutlarını ve Android sürümlerini hızlı şekilde test etmek mümkün.
Fakat emülatör kontrollü bir ortam.
Gerçek Android ekosistemi ise oldukça parçalı.
Karşınıza:
çıkabiliyor.
Dolap Hafızası üzerinde bunun en somut örneklerinden birini cihaz uyumluluğu konusunda yaşadım.
Uygulama teknik olarak ilgili Android sürümünde çalışabilecek durumda olmasına rağmen Google Play tarafındaki cihaz bütünlüğü ve sertifikasyon filtreleri bazı cihazlarda uygulamanın mağazada uyumsuz görünmesine neden olabiliyordu.
Bu tip bir problem emülatörde kolay kolay karşınıza çıkmıyor.
Çünkü sorun doğrudan uygulamanın Kotlin kodundan kaynaklanmıyor.
Google Play dağıtım katmanında ortaya çıkıyor.
Artık yalnızca uygulamanın açılıp açılmadığını kontrol etmiyorum.
Özellikle şunlara bakıyorum:
Bu kontrollerin bir bölümü emülatörde yapılabilir.
Ancak üretime çıkmadan önce en az birkaç gerçek cihaz üzerinde test yapmak bana göre artık zorunlu.
İkinci büyük dersim Play Console tarafında oldu.
Google Play Console’u başlangıçta yalnızca uygulamanın AAB dosyasını yüklediğimiz bir yönetim paneli gibi görmek kolay.
Gerçekte ise ürün geliştirme sürecinin önemli bir parçası.
Burada yalnızca yeni sürüm göndermiyorsunuz.
Aynı zamanda:
takip ediyorsunuz.
Dolap Hafızası’nı geliştirirken Android’in güncel hedef API gereksinimlerine de uyum sağlamak gerekti.
Google’ın güncel gereksinimine göre 31 Ağustos 2026’dan itibaren Google Play’e gönderilen yeni Android uygulamaları ve uygulama güncellemelerinin Android 16, yani API düzeyi 36 veya üzerini hedeflemesi gerekiyor.
Bu nedenle target SDK yükseltmesini yalnızca Gradle içerisinde:
targetSdk = 36 yazmak olarak görmemek gerekiyor.
Yeni API seviyesini hedeflediğinizde Android’in davranış değişikliklerini de incelemek gerekiyor.
Google’ın resmi dokümantasyonuna göre hedef API seviyesi yükseldiğinde yeni güvenlik, gizlilik ve platform davranışları uygulamayı etkileyebiliyor.
Bu nedenle benim için doğru yaklaşım şu oldu:
Google’ın güncel hedef API gereksinimlerini Android Developers resmi dokümantasyonundan takip etmek mümkün.
Google Play’e gönderilen Android uygulamalarında Android App Bundle, yani AAB kullanılıyor.
Ancak doğru şekilde imzalanmış AAB oluşturmak yayın sürecinin yalnızca teknik kısmı.
Sonrasında Play Console:
gibi farklı kontroller gerçekleştiriyor.
Dolayısıyla Android geliştiricisinin yalnızca IDE tarafına değil Play Console tarafına da hakim olması gerektiğini düşünüyorum.
Dolap Hafızası projesinde aldığım önemli mimari kararlardan biri, temel özellikleri internet bağlantısına bağımlı hale getirmemek oldu.
Uygulamada kullanıcıların oluşturduğu:
yerel veritabanında tutuluyor.
Burada Room kullanıyorum.
Google’ın Android mimari rehberinde offline-first uygulama, temel fonksiyonlarının tamamını veya kritik bölümünü internet erişimi olmadan gerçekleştirebilen uygulama olarak tanımlanıyor.
Dolap Hafızası’nın yapısıyla bu yaklaşım oldukça iyi örtüşüyor.
Kullanıcı dolabındaki bir eşyanın nerede olduğunu görmek için internet bağlantısını beklemek zorunda değil.
Veri zaten cihazda.
Room, SQLite üzerinde Android Jetpack tarafından sağlanan bir abstraction layer.
Benim açımdan en önemli avantajları:
Örneğin bir DAO tarafında:
@Query("SELECT * FROM items ORDER BY name ASC")
fun getAllItems(): Flow<List<ItemEntity>> şeklindeki bir yapı ile veri değiştiğinde UI tarafına güncel liste aktarılabiliyor.
Benim kullandığım akış genel olarak şu mantığa dayanıyor:
Room Database
↓
DAO
↓
Repository
↓
Flow
↓
ViewModel
↓
StateFlow
↓
Jetpack Compose UI Veritabanında bir değişiklik olduğunda kullanıcı arayüzünü manuel şekilde tekrar yenilemek yerine reactive yapıdan yararlanıyorum.
Bu özellikle Compose ile oldukça doğal bir geliştirme deneyimi oluşturuyor.
Teknik mimariden daha önemli taraf kullanıcı deneyimi.
Kullanıcı uygulamayı açtığında:
Ev içerisindeki eşya takip uygulaması için bunun doğru yaklaşım olduğunu düşünüyorum.
Google da offline-first mimarilerde yerel veri kaynağının uygulamanın temel okuma işlemleri için merkezi kaynak olarak kullanılmasını öneriyor.
Konuyla ilgili detaylar Android Developers offline-first mimari rehberinde bulunuyor.
Android uygulamasında belirli bir zamanda kullanıcıya bir şey hatırlatmak ilk bakışta oldukça kolay görünüyor.
Bir tarih seçilir, zaman geldiğinde bildirim gösterilir.
Gerçek cihazlarda işler bu kadar basit değil.
Android:
agresif şekilde yönetebiliyor.
Dolap Hafızası’nda son kullanma tarihi gibi özellikler bulunduğu için arka plan işlerinin güvenilir çalışması önemli.
Android’in resmi mimari önerilerinde kalıcı ve ertelenebilir arka plan işleri için WorkManager önemli araçlardan biri.
Örneğin kullanıcı bir ürün için hatırlatıcı oluşturduğunda uygulamanın o anda açık olup olmayacağını bilmiyoruz.
WorkManager burada işi Android sistemine zamanlamamızı sağlıyor.
Basitleştirilmiş bir örnek:
val request =
OneTimeWorkRequestBuilder<ReminderWorker>()
.setInitialDelay(delay, TimeUnit.MILLISECONDS)
.build()
WorkManager
.getInstance(context)
.enqueue(request) Ancak gerçek uygulamada yalnızca worker oluşturmak yeterli değil.
Şunların da test edilmesi gerekiyor:
Dolap Hafızası’nda yerel hatırlatıcıların yanında Firebase Cloud Messaging üzerinden genel bildirimler de kullanılabiliyor.
Burada iki farklı ihtiyaç ortaya çıkıyor:
Yerel bildirim:
Kullanıcının kendi oluşturduğu bir son kullanma tarihi hatırlatıcısı.
FCM bildirimi:
Uygulama kullanıcılarına genel bir duyuru veya dönemsel bilgilendirme gönderilmesi.
Bu ikisini mimari olarak birbirinden ayırmak uygulamanın ilerleyen aşamalarında yönetimi kolaylaştırıyor.
Burada teknik olmayan ama ürün tarafında önemli başka bir şey öğrendim.
Bir uygulamada push notification özelliğinin olması, kullanıcıya sürekli bildirim göndermek gerektiği anlamına gelmiyor.
Gereksiz bildirim:
neden olabilir.
Bu nedenle bildirim tarafında teknik olarak “gönderebilir miyim?” sorusundan önce:
“Bu bildirim gerçekten kullanıcıya değer sağlıyor mu?”
sorusunu sormak gerektiğini düşünüyorum.
Bir uygulamanın Google Play tarafından onaylanıp production’a çıkması geliştirici açısından oldukça güzel bir an.
Uzun süredir geliştirdiğiniz ürün artık herkes tarafından indirilebilir hale geliyor.
Fakat birkaç gün sonra fark ediyorsunuz ki geliştirme sürecinin finaline değil, başka bir aşamasının başlangıcına gelmişsiniz.
Çünkü artık gerçek kullanıcılar var.
Geliştirici olarak uygulamayı nasıl kullanacağınızı biliyorsunuz.
Hangi butonun ne yaptığını biliyorsunuz.
Hangi ekrandan hangi ekrana geçileceğini de biliyorsunuz.
Kullanıcı ise bunların hiçbirini bilmek zorunda değil.
Bu nedenle gerçek kullanıcı geri bildirimi:
çok daha hızlı ortaya çıkarabiliyor.
Yayın sonrasında artık yalnızca Android Studio logcat’e bakmıyorsunuz.
Play Console içerisindeki veriler de geliştirme kararlarını etkiliyor.
Örneğin:
takip edilebiliyor.
Böylece geliştirme süreci tahminlere değil, gerçek kullanım verilerine daha fazla dayanıyor.
Dolap Hafızası üzerinde yaşadığım en öğretici durumlardan biri cihaz uyumluluğu oldu.
Bir cihazın teknik olarak gerekli Android sürümüne sahip olması, Google Play’in o cihaza uygulamayı mutlaka sunacağı anlamına gelmeyebiliyor.
Play Console tarafında:
da dağıtımı etkileyebiliyor.
Bu süreç bana Android geliştirmenin yalnızca uygulama kodundan ibaret olmadığını tekrar gösterdi.
Google’ın yeni Android geliştirici doğrulama sistemi de önümüzdeki dönemde uygulama dağıtımının daha önemli parçalarından biri olacak.
Bu konuda hazırladığım ayrıntılı yazıya Android Geliştirici Doğrulaması Nedir? 2027’de Neler Değişecek? bağlantısından ulaşabilirsiniz.
Dolap Hafızası büyüdükçe UI içerisinde bütün iş mantığını tutmanın sürdürülebilir olmayacağı açıktı.
Bu nedenle projede MVVM yaklaşımını tercih ettim.
Basitleştirilmiş yapı:
Compose UI
↓
ViewModel
↓
Repository
↓
Room / DataStore / Services Bu ayrım sayesinde:
Örneğin UI tarafında doğrudan Room sorgusu yapmak yerine ViewModel tarafından sunulan StateFlow gözlemleniyor.
Dolap Hafızası’nın kullanıcı arayüzünü Jetpack Compose ile hazırladım.
Compose’un bana göre en önemli avantajlarından biri UI’ın state ile doğal şekilde çalışması.
Örneğin:
val uiState by viewModel.uiState.collectAsState() ile ViewModel tarafından sağlanan durumu gözlemleyip ekranın buna göre yeniden oluşturulması oldukça temiz bir yapı oluşturuyor.
XML tabanlı klasik Android geliştirmeden farklı olarak UI bileşenleri Kotlin içerisinde tanımlandığı için ekran ve iş mantığı arasındaki bağlantıları takip etmek de daha kolay hale geliyor.
Ancak Compose kullanmak bütün UI problemlerini otomatik olarak çözmüyor.
Gerçek projede yine:
konularına dikkat etmek gerekiyor.
Room daha karmaşık ve ilişkisel kullanıcı verilerini saklarken küçük ayarlar için aynı yapıyı kullanmak her zaman gerekli değil.
Bu nedenle uygulama ayarlarında DataStore kullanıyorum.
Örneğin:
gibi küçük veriler için DataStore daha uygun bir çözüm.
Böylece Room ile uygulamanın ana verileri, DataStore ile ayarlar birbirinden ayrılmış oluyor.
İlk sürümde olmayan bir özellik daha sonra projeye eklendiğinde mimarinin ne kadar önemli olduğu ortaya çıkıyor.
Örneğin Dolap Hafızası’nda görüntü üzerinden nesne tanıma gibi akıllı özellikler eklendiğinde mevcut UI ve veri yapısını tamamen değiştirmek istemezsiniz.
Katmanlı yapı yeni servislerin sisteme daha kontrollü eklenmesini kolaylaştırıyor.
Bu nedenle proje küçükken:
“Buna gerek yok, zaten birkaç ekran.”
denilen mimari kararlar, uygulama büyüdüğünde ciddi zaman kazandırabiliyor.
Mobil uygulama geliştirmeden önce zamanın çoğunun kod yazmaya ayrılacağını düşünebilirsiniz.
Üretim aşamasında ise yapılacak işler hızla artıyor.
Örneğin:
Yani gerçek ürün geliştirme, kodun çok ötesinde bir süreç.
Aynı projeye bugün sıfırdan başlayacak olsaydım bazı konulara daha erken odaklanırdım.
Emülatör testleri devam ederdi ancak ilk kullanılabilir sürüm oluştuğu anda farklı fiziksel cihazlarda test etmeye başlardım.
Test kanalları, cihaz uyumluluğu ve mağaza gereksinimlerini geliştirme sırasında düzenli kontrol ederdim.
Bir özelliğin teknik olarak çalışması onun kullanıcı tarafından kullanıldığı anlamına gelmiyor.
Hangi özelliklerin gerçekten değer ürettiğini anlamak için ürün metriklerini erken planlamak önemli.
Google Play ekran görüntüsü, açıklama ve feature graphic kullanıcının uygulamayla ilk karşılaştığı alan.
Uygulama ne kadar iyi olursa olsun mağaza sayfası bunu anlatamıyorsa kullanıcı yüklemeyebilir.
Kapalı test ve internal test önemli fakat gerçek kullanıcı davranışı ancak production sonrasında tam anlamıyla görülebiliyor.
Projenin temel teknik yapısını özetlemek gerekirse:
| Alan | Kullandığım Teknoloji |
|---|---|
| Programlama dili | Kotlin |
| Kullanıcı arayüzü | Jetpack Compose |
| Mimari | MVVM |
| Yerel veritabanı | Room |
| Reactive data | Flow / StateFlow |
| Ayar saklama | DataStore |
| Arka plan görevleri | WorkManager |
| Push bildirim | Firebase Cloud Messaging |
| Görsel yükleme | Coil |
| Nesne tanıma | ML Kit |
| Minimum Android | API 23 |
| Target SDK | API 36 |
Bütün süreci beş maddede özetlemem gerekirse:
Emülatör geliştirmeyi hızlandırır ancak cihaz uyumluluğu ve gerçek Android davranışlarının tamamını temsil etmez.
Uygulama kodu kadar dağıtım, test, uyumluluk ve politika süreçlerini de takip etmek gerekir.
Özellikle uygulamanın temel işlevi internet bağlantısına ihtiyaç duymuyorsa Room gibi yerel veri kaynakları büyük avantaj sağlar.
Android’in pil ve arka plan optimizasyonları masa başında yazılan teorik koddan daha karmaşık davranabilir.
Asıl ürün geliştirme süreci kullanıcıların uygulamayı kullanmaya başlamasıyla devam eder.
Bu yazıda anlattığım yapının gerçek uygulamadaki sonucunu görmek isteyenler Dolap Hafızası’nı Google Play üzerinden inceleyebilir.
👉 Dolap Hafızası – Google Play
Uygulamanın özellikleri ve geliştirme süreci hakkında daha fazla bilgi için:
👉 Dolap Hafızası proje sayfası
Google Play uygulama geliştirme deneyimi bana bir mobil uygulamanın başarılı şekilde derlenmesinin yalnızca ilk aşama olduğunu gösterdi.
Kotlin, Jetpack Compose, MVVM, Room ve WorkManager gibi teknolojiler uygulamanın teknik temelini oluşturuyor. Ancak gerçek bir ürün ortaya çıkarmak için bunların yanında cihaz uyumluluğu, Play Console, kullanıcı geri bildirimleri, mağaza optimizasyonu ve yayın sonrası bakım süreçlerini de yönetmek gerekiyor.
Özellikle Dolap Hafızası gibi gerçek kullanıcıya ulaşan bir proje üzerinde çalışmak, eğitim projelerinden çok farklı sorunlarla karşılaşmamı sağladı.
Bazı sorunların çözümü birkaç satır Kotlin kodu olurken bazıları Play Console ayarlarında, bazıları Android’in arka plan davranışlarında, bazıları ise doğrudan kullanıcı deneyiminde ortaya çıktı.
Bugün geriye baktığımda en önemli çıkarımım şu:
Bir uygulamayı kodlamak ile bir ürünü üretime çıkarmak aynı şey değil.
Gerçek öğrenme çoğu zaman uygulama production’a çıktıktan sonra başlıyor.
İlerleyen yazılarda Dolap Hafızası’nın Jetpack Compose + MVVM + Room mimarisini, WorkManager ile hatırlatıcı sistemini ve Google Play tarafında karşılaştığım gerçek problemlerin teknik çözümlerini ayrı ayrı daha detaylı ele alacağım.
Dolap Hafızası uygulamasında Kotlin, Jetpack Compose, MVVM, Room, Flow/StateFlow, WorkManager, DataStore, Firebase Cloud Messaging, Coil ve ML Kit kullandım.
Evet. Jetpack Compose modern Android uygulamalarında production ortamında kullanılabilecek olgun bir UI toolkit’i. State tabanlı yapısı özellikle ViewModel ve Flow ile birlikte oldukça doğal bir geliştirme modeli sağlıyor.
Room, yapılandırılmış verilerin Android cihaz üzerinde saklanmasını kolaylaştıran Jetpack veritabanı kütüphanesidir. SQLite üzerinde abstraction layer sunar ve SQL sorgularını compile-time sırasında kontrol edebilir.
Offline-first uygulama, temel fonksiyonlarının tamamını veya kritik bölümünü aktif internet bağlantısı olmadan gerçekleştirebilen uygulamadır. Dolap Hafızası’nın temel eşya ve oda verileri cihaz üzerinde saklandığı için ana özellikler internet bağlantısına ihtiyaç duymaz.
WorkManager, Android’de uygulama kapalı olsa bile tamamlanması gereken ertelenebilir ve kalıcı arka plan işlerini zamanlamak için kullanılan Jetpack bileşenlerinden biridir.
31 Ağustos 2026’dan itibaren Google Play’e gönderilen yeni standart Android uygulamaları ve uygulama güncellemelerinin Android 16, yani API düzeyi 36 veya daha yüksek bir API düzeyini hedeflemesi gerekiyor.
Hayır. Emülatör geliştirme aşamasında çok kullanışlı olsa da farklı üretici cihazları, pil optimizasyonları, Google Play uyumluluğu ve gerçek kullanıcı davranışı gibi durumlar fiziksel cihazlarda ayrıca test edilmeli.
Hayır. Yayın sonrasında kullanıcı geri bildirimleri, crash ve ANR raporları, cihaz uyumluluğu, yeni Android sürümleri, mağaza optimizasyonu ve uygulama güncellemeleri nedeniyle geliştirme süreci devam eder.
Jetpack Compose MVVM Room mimarisi, Kotlin ile geliştirilen Android uygulamalarında kullanıcı arayüzünü, iş mantığını ve…
Yerel Android uygulaması geliştirme, genel amaçlı bir mobil uygulama hazırlamaktan farklı problemler ortaya çıkarabiliyor. Çünkü…
.NET 11 yenilikleri, Microsoft'un yeni nesil uygulama geliştirme platformunda C# dilinden ASP.NET Core'a, Entity Framework…
Android geliştirici doğrulaması, Google'ın Android ekosisteminde uygulama dağıtan geliştiricilerin kimliğini ve uygulama paketlerinin sahipliğini doğrulamak…
GPT-6.1 Terra, OpenAI'ın hız, yetenek ve maliyet dengesine odaklanan yeni modeli olarak 26 Ekim 2026…
OpenAI, uzun süredir birçok production uygulamasının temelinde kullanılan GPT-4o ve GPT-4.1 ailesindeki belirli API modellerini…