İlk Android Uygulamam: Çevrimdışı ML Galeri Düzenleyici Geliştirirken Öğrendiklerim (ve Copilot’un Katkısı)
Her yazılımcının ilk mobil uygulama deneyimi unutulmazdır. Bu makalede, başlangıç seviyesi bir Android geliştiricisi olarak, çevrimdışı çalışan, makine öğrenimi (ML) destekli bir galeri düzenleyici uygulaması geliştirme serüvenimi aktaracağım. Proje fikrinden uygulamaya, karşılaşılan zorluklardan edindiğim derslere kadar tüm süreci ele alırken, yapay zeka destekli Copilot’un bu süreçteki önemli katkısını da vurgulayacağım. Amacım, benzer bir yola çıkmak isteyenlere ilham vermektir.
1. Proje Fikri ve Neden Çevrimdışı ML?
Her şey, telefonumdaki binlerce fotoğrafı düzenlemenin zorluğundan başladı. Benzer fotoğrafları bulmak, belirli nesneleri içerenleri ayıklamak veya metin içeren görselleri hızlıca bulmak manuel olarak imkansızdı. Mevcut galeri uygulamaları genellikle bulut tabanlı çözümler sunsa da, gizlilik endişeleri ve internet bağlantısına bağımlılık beni çevrimdışı bir çözüme itti.
1.1. Fikir Nasıl Ortaya Çıktı?
Birçok kullanıcının kişisel verilerinin bulutta saklanması konusunda çekinceleri olduğunu biliyordum. Ayrıca, internet bağlantısının olmadığı durumlarda bile fotoğrafları düzenleyebilme ihtiyacı vardı. Bu iki temel motivasyon, “cihaz üzerinde” (on-device) makine öğrenimi kullanarak çalışan bir galeri uygulamasını hayal etmeme neden oldu. Uygulama, fotoğrafları analiz edecek, etiketleyecek ve bu etiketlere göre düzenleme imkanı sunacaktı.
1.2. Çevrimdışı ML’in Avantajları
Çevrimdışı makine öğrenimi, verilerin cihazdan ayrılmaması sayesinde üst düzey gizlilik sunar. İnternet bağlantısına ihtiyaç duymadığı için her yerde ve her zaman çalışabilir. Ayrıca, sunucu maliyetleri olmadığı için geliştirici açısından da avantajlıdır. Kullanıcılar için daha hızlı ve kesintisiz bir deneyim anlamına gelirken, hassas verilerin güvenliğini de garanti altına alır.
1.3. Hedef Kitle ve Kullanım Senaryoları
Uygulama, özellikle fotoğraf çekmeyi seven, ancak bunları düzenlemekte zorlanan herkesi hedefliyordu. Kullanım senaryoları arasında şunlar vardı: “köpek” içeren tüm fotoğrafları bulma, ekran görüntülerindeki metinleri tanıma, belirli nesneleri (örneğin “araba” veya “yemek”) içeren görselleri filtreleme ve hatta benzer görselleri gruplandırma.
2. Geliştirme Ortamının Hazırlanması ve İlk Adımlar
Her yeni projede olduğu gibi, ilk adım geliştirme ortamını kurmaktı. Android Studio, Android uygulamaları geliştirmek için standart ve en kapsamlı IDE’dir. Kurulum süreci oldukça basittir, ancak bazı detaylara dikkat etmek gerekir.
2.1. Android Studio Kurulumu
Android Studio’yu resmi web sitesinden indirip kurdum. Kurulum sırasında SDK (Software Development Kit) bileşenlerini seçerken, hedefleyeceğim Android sürümünü ve emülatör için gerekli araçları dahil etmeye özen gösterdim. Sanal cihaz (AVD) oluşturmak, fiziksel bir cihaza ihtiyaç duymadan uygulamayı test etmemi sağladı.
- Android Studio’yu indirme ve kurma
- Gerekli SDK platformlarını ve araçlarını seçme
- Bir sanal cihaz (AVD) yapılandırma
- Gradle ayarlarını kontrol etme
2.2. İlk “Hello World” ve Proje Yapısı
Yeni bir proje oluşturduktan sonra, Android Studio’nun otomatik olarak oluşturduğu “Hello World” uygulamasını çalıştırdım. Bu, her şeyin doğru çalıştığını doğrulamanın ilk adımıydı. Ardından, projenin temel yapısını inceledim: AndroidManifest.xml, res klasörü (layout, drawable, values), Java/Kotlin kaynak kodları ve Gradle dosyaları.
// MainActivity.kt
package com.example.mlgalleryorganizer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
2.3. Kotlin'e Giriş
Android geliştirmede Kotlin, modern ve daha güvenli bir dil olarak öne çıkıyor. Java'ya kıyasla daha az kodla daha fazlasını yapma imkanı sunması ve null-safety gibi özellikleriyle tercih sebebim oldu. Temel Kotlin sözdizimini ve Android'e özgü uzantıları öğrenmek, başlangıçta biraz zaman alsa da, uzun vadede verimliliğimi artırdı.
3. Uygulamanın Temel Mimarisi ve Kullanıcı Arayüzü
Uygulamanın temelini oluştururken, modüler bir yapı ve kullanıcı dostu bir arayüz hedefledim. Android'in temel bileşenlerini kullanarak, galeri uygulamasının iskeletini inşa ettim.
3.1. Aktivite ve Fragment Yapısı
Uygulamanın ana ekranı için bir MainActivity kullandım. Galeri görünümü, detay ekranları ve ayarlar gibi farklı bölümler için Fragment'lar tercih ettim. Fragment'lar, kullanıcı arayüzü bileşenlerini daha yönetilebilir hale getirerek, tek bir aktivite içinde farklı ekranlar arasında geçiş yapmayı kolaylaştırır. Bu, özellikle tablet gibi büyük ekranlı cihazlarda daha esnek bir tasarım sunar.
3.2. RecyclerView ile Galeri Görünümü
Telefon galerisindeki binlerce fotoğrafı verimli bir şekilde göstermek için RecyclerView vazgeçilmezdi. ImageView'lardan oluşan bir ızgara görünümü (Grid Layout Manager) kullanarak fotoğrafları sergiledim. Glide kütüphanesi gibi bir resim yükleme kütüphanesi kullanarak, görsellerin hızlı ve sorunsuz bir şekilde yüklenmesini ve önbelleğe alınmasını sağladım, bu da uygulamanın performansını önemli ölçüde artırdı.
// PhotoAdapter.kt (Basit bir RecyclerView adaptörü örneği)
class PhotoAdapter(private val photos: List) :
RecyclerView.Adapter() {
class PhotoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.imageView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_photo, parent, false)
return PhotoViewHolder(view)
}
override fun onBindViewHolder(holder: PhotoViewHolder, position: Int) {
val photo = photos[position]
Glide.with(holder.imageView.context)
.load(photo.uri)
.into(holder.imageView)
}
override fun getItemCount() = photos.size
}
3.3. Materyal Tasarım İlkeleri
Kullanıcı deneyimini iyileştirmek için Google'ın Materyal Tasarım yönergelerini takip ettim. Tutarlı renk paletleri, tipografi ve animasyonlar kullanarak modern ve sezgisel bir arayüz oluşturdum. FloatingActionButton (FAB) gibi bileşenler, temel eylemleri vurgulamak için kullanıldı.
4. Makine Öğrenimi Entegrasyonu: Cihaz Üzerinde Analiz
Uygulamanın kalbi, fotoğrafları analiz eden makine öğrenimi yetenekleriydi. Google'ın ML Kit'i, bu entegrasyonu başlangıç seviyesindeki bir geliştirici için bile oldukça erişilebilir hale getirdi.
4.1. ML Kit'i Keşfetmek
ML Kit, Android uygulamalarına makine öğrenimi özelliklerini entegre etmek için hazır API'ler sunar. Cihaz üzerinde çalışan modeller (on-device models) sayesinde internet bağlantısı olmadan da çalışabilir. Resim etiketleme, metin tanıma, yüz algılama gibi birçok farklı özelliği destekler. Benim için en önemli olanlar resim etiketleme ve metin tanımaydı.
4.2. Resim Etiketleme (Image Labeling) Modeli
Resim etiketleme, bir fotoğraftaki nesneleri, kavramları ve eylemleri tanımlayarak etiketler atar. Örneğin, bir fotoğrafta "köpek", "ağaç", "gökyüzü" gibi etiketler döndürebilir. Bu etiketleri veritabanımda saklayarak, kullanıcıların belirli etiketlere göre arama yapmasını sağladım.
// build.gradle (app seviyesi)
dependencies {
// ...
implementation 'com.google.mlkit:image-labeling:17.0.7'
// İsteğe bağlı: Özel model kullanmak isterseniz
// implementation 'com.google.mlkit:image-labeling-custom:17.0.7'
}
4.3. Metin Tanıma (Text Recognition) ve Nesne Tespiti (Object Detection)
Ekran görüntüleri veya belge fotoğraflarındaki metinleri tanımak için metin tanıma özelliğini kullandım. Bu sayede, kullanıcılar bir ekran görüntüsündeki kelimeleri arayarak ilgili görsele ulaşabildiler. Nesne tespiti ise, fotoğraftaki belirli nesnelerin konumunu ve türünü belirlemeye yardımcı oldu, bu da daha hassas filtreleme imkanları sundu.
4.4. Model Entegrasyonu ve Veri İşleme
ML Kit'i kullanmak oldukça basitti. Fotoğrafın URI'sinden bir InputImage nesnesi oluşturup, ilgili ML Kit dedektörüne gönderdim. Dedektör, sonuçları bir geri çağırım (callback) mekanizmasıyla döndürdü. Bu sonuçları (etiketler, tanınan metinler) işleyip, her bir fotoğraf için veritabanıma kaydettim. Bu işlem, uygulamanın arka planında, kullanıcı arayüzünü engellemeyecek şekilde (örneğin Coroutines kullanarak) yapıldı.
5. Veri Yönetimi ve Kalıcılık: Resimler ve Etiketler
Uygulamanın çevrimdışı çalışabilmesi ve verileri kalıcı olarak saklayabilmesi için sağlam bir veri yönetim sistemine ihtiyacı vardı. Android'in yerel depolama seçenekleri bu noktada devreye girdi.
5.1. Room Veritabanı ile Yerel Depolama
Android'de yerel veritabanı çözümü olarak Room Persistence Library'yi tercih ettim. SQLite üzerine kurulu olan Room, Kotlin Coroutines ile uyumlu çalışması ve daha güvenli, daha okunabilir kod yazma imkanı sunması nedeniyle idealdi. Fotoğrafların meta verilerini (dosya yolu, etiketler, tanınan metinler vb.) ve kullanıcı tarafından oluşturulan albümleri Room veritabanında sakladım.
// PhotoEntity.kt (Room veritabanı için örnek bir varlık)
@Entity(tableName = "photos")
data class PhotoEntity(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val uri: String,
val path: String,
val timestamp: Long,
val labels: String, // Etiketler virgülle ayrılmış string olarak saklanabilir
val recognizedText: String?
)
5.2. Veri Modelleri ve İlişkiler
Veritabanı şemasını tasarlarken, fotoğraflar, etiketler ve albümler arasındaki ilişkileri dikkatlice belirledim. Bir fotoğrafın birden fazla etiketi olabilirken, bir etiket de birden fazla fotoğrafa ait olabilirdi (many-to-many ilişkisi). Room'un ilişki yönetimi yeteneklerini kullanarak bu karmaşık yapıları modelledim.
5.3. Dosya Sistemi Yönetimi
Uygulama, kullanıcının cihazındaki mevcut fotoğrafları okumak ve ML analizi için erişmek zorundaydı. Bu, Android'in depolama izinlerini (READ_EXTERNAL_STORAGE) doğru bir şekilde yönetmeyi gerektiriyordu. Ayrıca, analiz edilen fotoğrafların URI'lerini ve yollarını veritabanında saklayarak, orijinal dosyalara kolayca erişebilme imkanı sağladım.
6. Copilot: Geliştirme Sürecindeki Akıllı Yardımcım
Başlangıç seviyesindeki bir geliştirici olarak, Copilot benim için paha biçilmez bir asistan oldu. Özellikle bilmediğim API'leri kullanırken veya karmaşık algoritmalar yazarken sağladığı önerilerle süreci hızlandırdı ve öğrenme eğrimi düşürdü.
6.1. Kod Tamamlama ve Öneriler
Copilot, yazdığım kod bağlamına göre anında kod tamamlama ve öneriler sundu. Örneğin, bir RecyclerView adaptörü yazarken, onCreateViewHolder veya onBindViewHolder metodlarının iskeletini otomatik olarak tamamladı. Veritabanı sorguları yazarken SQL benzeri ifadeleri Kotlin koduna çevirme konusunda da çok yardımcı oldu. Bu, özellikle tekrar eden veya kalıp halindeki kodları yazarken büyük zaman kazandırdı.
6.2. Hata Ayıklama ve Çözüm Bulma
Bazen karşılaştığım hatalarda veya beklediğim gibi çalışmayan kod parçalarında Copilot'tan yardım istedim. Yorum satırlarıyla sorunu açıklayarak veya hatalı kodu göstererek, olası düzeltmeler veya alternatif yaklaşımlar konusunda öneriler aldım. Bu, özellikle Stack Overflow'da saatlerce arama yapma ihtiyacını azalttı ve sorun giderme sürecini hızlandırdı.
6.3. Bilinmeyen API'leri Keşfetme
Android ekosistemi geniş ve birçok farklı API içeriyor. Örneğin, medya dosyalarına erişim için ContentResolver kullanmam gerektiğinde veya ML Kit'in belirli bir özelliğini entegre ederken, Copilot ilgili fonksiyon çağrılarını ve parametrelerini önererek yol gösterdi. Bu, dokümantasyon okuma süresini kısalttı ve yeni teknolojilere adaptasyonumu kolaylaştırdı.
7. Karşılaşılan Zorluklar, Çözümler ve Öğrenilenler
Hiçbir geliştirme süreci sorunsuz ilerlemez. Bu projede de birçok zorlukla karşılaştım, ancak her biri değerli dersler edinmemi sağladı.
7.1. Performans Optimizasyonu
Binlerce fotoğrafı işlemek ve aynı anda kullanıcı arayüzünü akıcı tutmak önemli bir performans zorluğuydu. Çözüm olarak, ML analizini arka plan iş parçacıklarında (background threads) ve Coroutines kullanarak yaptım. Ayrıca, Glide gibi kütüphanelerle resim yüklemeyi optimize ettim ve RecyclerView'ın verimli çalışmasını sağladım.
7.2. Kullanıcı İzinleri Yönetimi
Android 6.0 (Marshmallow) ve sonrası için çalışma zamanı izinleri (runtime permissions) önemli bir konuydu. Kullanıcılardan depolama iznini doğru zamanda ve anlaşılır bir şekilde istemek, uygulamanın çökmesini önlemek ve kullanıcı deneyimini bozmamak için kritikti. İzin isteme akışını dikkatlice tasarladım ve izin verilmediğinde alternatif senaryoları ele aldım.
7.3. ML Model Doğruluğu ve İyileştirme
ML Kit'in hazır modelleri genellikle iyi sonuçlar verse de, bazen etiketleme doğruluğu beklentimin altında kalabiliyordu. Özellikle çok spesifik nesneleri tanımakta zorlanabiliyordu. Bu durumda, kullanıcıya etiketleri manuel olarak düzenleme veya ekleme imkanı sunarak modelin eksiklerini telafi ettim. Gelecekte özel ML modelleri eğitmeyi de düşündüm.
7.4. Zaman Yönetimi ve Proje Planlama
Bir başlangıç seviyesi geliştirici olarak, projenin kapsamını ve tamamlanma süresini doğru tahmin etmek zordu. Küçük, yönetilebilir görevlere bölmek ve her adımı planlamak, projenin kontrol altında kalmasına yardımcı oldu. Esnek olmak ve beklenmedik sorunlar karşısında planları adapte edebilmek de önemliydi.
8. Sonuç ve Gelecek Adımlar
Bu proje, benim için sadece bir uygulama geliştirmekten çok daha fazlasıydı; Android geliştirme dünyasına attığım ilk sağlam adımdı. Makine öğreniminin mobil uygulamalara nasıl entegre edilebileceğini, kullanıcı deneyiminin önemini ve yapay zeka destekli araçların geliştirme sürecini nasıl hızlandırabileceğini öğrendim.
8.1. Projenin Özeti ve Kazanımlar
Çevrimdışı ML destekli galeri düzenleyici uygulaması, fotoğrafları otomatik olarak etiketleyerek ve aranabilir hale getirerek kullanıcıların dijital anılarını daha iyi yönetmelerini sağladı. Bu süreçte Kotlin, Android UI bileşenleri, Room veritabanı, ML Kit ve Copilot gibi modern araçları kullanarak pratik deneyim kazandım. En büyük kazanımım, karmaşık bir fikri baştan sona hayata geçirme yeteneğimi geliştirmek oldu.
8.2. Gelecek Özellikler ve Geliştirme Planları
Uygulama için aklımda birçok gelecek özellik var. Bunlardan bazıları: yüz tanıma ile kişileri etiketleme, benzer fotoğrafları otomatik olarak gruplandırma ve silme önerileri sunma, video analizi entegrasyonu ve kullanıcıların kendi özel etiketlerini veya kategorilerini oluşturmasına izin verme. Ayrıca, uygulamanın performansını daha da optimize etmek ve daha sezgisel bir kullanıcı arayüzü sunmak için sürekli iyileştirmeler yapmayı planlıyorum.
Sık Sorulan Sorular (SSS)
Neden offline ML'i tercih ettiniz?
Gizlilik endişeleri ve internet bağlantısı olmadan da uygulamanın çalışabilmesi ihtiyacı nedeniyle offline (cihaz üzerinde) makine öğrenimini tercih ettim. Bu, kullanıcı verilerinin cihazdan ayrılmamasını garanti eder ve her koşulda erişilebilirlik sağlar.
Hangi ML Kit özelliklerini kullandınız?
Başlangıçta ağırlıklı olarak Resim Etiketleme (Image Labeling) ve Metin Tanıma (Text Recognition) özelliklerini kullandım. Gelecekte Nesne Tespiti (Object Detection) ve Yüz Algılama (Face Detection) gibi diğer özellikleri de entegre etmeyi planlıyorum.
Copilot gerçekten bu kadar yardımcı oldu mu?
Kesinlikle evet. Başlangıç seviyesi bir geliştirici olarak, bilmediğim API'ler, karmaşık kod yapıları veya hata ayıklama süreçlerinde Copilot'un sunduğu anlık kod önerileri ve çözümlemeler sayesinde çok zaman kazandım ve öğrenme sürecim hızlandı. Sanki yanımda sürekli bir kıdemli geliştirici varmış gibiydi.
Başlangıç seviyesi için hangi kaynakları önerirsiniz?
Android geliştirme için Google'ın resmi Android Developers web sitesi ve Kotlin kursları harika bir başlangıç noktasıdır. Ayrıca, Udemy, Coursera gibi platformlardaki kurslar ve Stack Overflow gibi topluluklar da sorun çözmede çok yardımcı olacaktır. Pratik yaparak ve küçük projeler geliştirerek öğrenmek en etkili yoldur.
Bu projeyi geliştirmek ne kadar sürdü?
Temel özelliklere sahip ilk sürümü geliştirmek yaklaşık 3 ayımı aldı. Bu süreye öğrenme, deneme-yanılma ve hata ayıklama da dahildi. Daha sonraki iyileştirmeler ve yeni özellikler ekleme süreci ise devam etmektedir.
