---
title: 'Kamera ve Medya'
source: 'https://academia.sh/tr/kurslar/android-servisler/kamera-ve-medya'
course: 'Platform Servisleri ve Tümleştirmeler'
language: tr
updated: '2026-10-21T05:02:41+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Kamera izninin ve kamera kitaplığının çekim isteği ile sonuç geri çağrısını tanır'
    - 'Her çekim isteğinin tek bir sonuçla birebir teslim edildiğini ölçer'
    - 'Depolama dolduğunda sonraki çekimlerin kayıp olduğunu gösterir'
    - 'Deklanşöre iki dokunuşun iki ayrı sıra olduğunu ve ikisinin de birebir ulaştığını gösterir'
---

# Kamera ve Medya

Kamera kitaplığı her çekim isteği için tek bir sonuç döndürür; depolama dolu olduğunda sonuç gelmez. Ders çekim isteklerinin teslimini ölçer ve deklanşöre art arda iki kez dokunulduğunda iki ayrı sonucun ulaştığını gösterir.

Önceki derste konum güncellemeleri sürekli bir akıştı ve kural arada kalanları düşürdü. Kamerada olay bir kullanıcı eyleminden doğar: kullanıcı deklanşöre dokunur ve uygulama bir fotoğraf bekler. Bir dokunuşun bir sonuç vermesi beklenir. Bu derste de aynı soruyu soruyoruz: **gönderilen bu olay alıcıya kaç kopya olarak ulaştı?**

```kotlin
// Arrival.kt — gonderilen bir olayin aliciya kac kopya olarak ulastigini siniflandirir
class Signal(val key: String, val seq: Int)

class Arrival(val label: String, val sent: Signal, received: List<Signal>) {
    val copies: Int = received.count { it.seq == sent.seq }
    val verdict: String = when {
        copies > 1 -> "yinelenen"
        copies == 1 -> "birebir"
        received.any { it.key == sent.key && it.seq > sent.seq } -> "ezilen"
        else -> "kayip"
    }

    fun line() {
        println("$label: anahtar=${sent.key} | kopya=$copies -> $verdict")
    }
}

fun countArrivals(arrivals: List<Arrival>) {
    for (name in listOf("birebir", "yinelenen", "ezilen", "kayip")) {
        println("$name: ${arrivals.count { it.verdict == name }}")
    }
}
```

Sınıflandırma önceki derslerdekiyle aynıdır. Kural alıcının listesinde aynı sırayı taşıyan kopyaları sayar; hiç kopya yoksa aynı anahtarla daha sonraki bir olayın ulaşıp ulaşmadığına bakar. İçeriği ve nedeni görmez.

## İzin ve Çekim İsteği

Kamera da çalışma zamanı izni isteyen bir yetenektir. Bildirim dosyasında tanımlanır ve kullanıcı ilk kullanımda onaylar.

```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
```

Kamera kitaplığı çekimi iki parçaya böler. Uygulama bir çekim isteği verir; kitaplık sonucu bir geri çağrıyla geri döndürür. Başarıyla biten çekim için dosyanın kaydedildiğini, başarısız olan için bir hata nesnesi bildirir.

```kotlin
// Platform kodu: ShutterController
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException

class ShutterController(private val capture: ImageCapture) {
    fun onShutterTap(options: ImageCapture.OutputFileOptions) {
        capture.takePicture(options, executor, object : ImageCapture.OnImageSavedCallback {
            override fun onImageSaved(result: ImageCapture.OutputFileResults) = openPreview(result)
            override fun onError(error: ImageCaptureException) = logFailure(error)
        })
    }
}
```

Her `takePicture` çağrısı bir sonuç ya da bir hata doğurur. Model, platformun bu kuralını kurar; model platformun kendisi değildir. Bu parça çıktı ya da süre iddia etmez.

## Her Dokunuş Bir Sonuç

Modelde her çekim isteği bir `Signal`dır. Anahtar fotoğrafın adı, sıra numarası isteğin verildiği adımdır. Kamera kitaplığının modeli her isteğe tek bir sonuç döndürür.

```kotlin
// Camera.kt — her cekim istegine tek bir sonuc dondurur
fun shoot(requests: List<Signal>): List<Signal> =
    requests.map { Signal(it.key, it.seq) }
```

```kotlin
// Main.kt — her cekim istegi tek bir sonuc olarak birebir ulasir
fun main() {
    val sent = listOf(
        Signal("foto.sabah", 1),
        Signal("foto.ogle", 2),
        Signal("foto.aksam", 3),
        Signal("foto.gece", 4),
    )
    val received = shoot(sent)
    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-1: anahtar=foto.sabah | kopya=1 -> birebir
olay-2: anahtar=foto.ogle | kopya=1 -> birebir
olay-3: anahtar=foto.aksam | kopya=1 -> birebir
olay-4: anahtar=foto.gece | kopya=1 -> birebir
birebir: 4
yinelenen: 0
ezilen: 0
kayip: 0
```

Bu dersin teslimi **birebir**dir. Dört isteğin dördü tek kopya olarak ulaştı. Önceki iki derste kural bir olayın yerini başka bir olayın almasını ezilen saymıştı; burada anahtarlar birbirinden farklı olduğu için hiçbir olay bir diğerinin yerini alamaz.

**SY1.** Model, her çekim isteğini başarılı kabul eder. Platformda çekim kamera meşgulken, izin geri alınmışken ya da kitaplık yeniden başlatılırken hata verebilir; hata geri çağrısı modelde yoktur.

## Hata Geri Çağrısı ve Sonuç Sözleşmesi

Kitaplığın sözleşmesi şudur: her çekim isteği için başarı geri çağrısı ya da hata geri çağrısından yalnızca biri çalışır. İkisi birden çalışmaz ve ikisinin de çalışmaması sözleşmeye aykırıdır. Modelin "her isteğe tek sonuç" kuralı bu sözleşmenin sade biçimidir: sonuç ya dosyadır ya da hatadır, ama her zaman tektir.

Uygulama açısından bu, hata geri çağrısının bir lüks olmadığı anlamına gelir. Başarı yolunu yazıp hata yolunu boş bırakan bir ekran, kullanıcıya hiçbir şey söylemeyen bir kayıp üretir: kullanıcı deklanşöre dokunmuş, ekranda bir şey değişmemiştir. Ölçümde iki çekimin kaybolması kural açısından yalnızca bir sayıdır; kullanıcı açısından ise iki ayrı hayal kırıklığıdır. Hata nesnesinin neden taşıdığı bilgi, kullanıcıya ne söylenebileceğini belirler: izin eksikliği için ayarlara yönlendirme, dolu depolama için yer açma önerisi.

## Ekranın Yaşam Döngüsü

Kamera önizlemesi ekranın yaşam döngüsüne bağlanır. Ekran görünür olduğunda kamera açılır, ekran gizlendiğinde kapanır. Kitaplığın çekim isteği kameranın açık olduğu bir zamanda anlam taşır; kamera kapalıyken verilen istek hata geri çağrısına düşer.

Bunun teslimle ilgisi, isteğin hangi anda verildiğindedir. Kullanıcı deklanşöre dokunup hemen başka bir uygulamaya geçerse, istek verilmiştir ama ekran gizlenirken kamera kapanır. Çekim tamamlanmadan kapanan kamera için kitaplık hata bildirir; fotoğraf hiç oluşmaz. Modelde bu durum, depolama dolduğunda olduğu gibi, bir isteğin kayıp olmasına karşılık gelir. Fark, nedenin depolama değil yaşam döngüsü olmasıdır. Kural bu iki nedeni ayırt etmez; ayırt etmek için hata nesnesine bakmak gerekir.

## İzin Verilmeden Yapılan İstek

İzin verilmemişken yapılan çekim isteği de hata geri çağrısına düşer. Kullanıcı izin penceresini yanıtlayana kadar uygulamanın verdiği istekler, izin verildikten sonra yeniden işlenmez. Aşağıdaki modelde izin 14 numaralı adımda verilir ve ondan önceki istekler sonuç üretmez. İlk üç istek aynı fotoğraf adını taşıyor: kullanıcı bir belgeyi çekmeye çalışıyor.

```kotlin
// Permission.kt — izin verilmeden onceki cekim isteklerinin sonucunu birakir
fun requirePermission(sent: List<Signal>, grantedAt: Int): List<Signal> =
    sent.filter { it.seq >= grantedAt }
```

```kotlin
// Main.kt — izin verilmeden yapilan istekler sonuc uretmez
fun main() {
    val sent = listOf(
        Signal("foto.belge", 12),
        Signal("foto.belge", 13),
        Signal("foto.belge", 14),
        Signal("foto.sayfa", 15),
    )
    val received = requirePermission(shoot(sent), grantedAt = 14)
    println("ulasan siralar: ${received.map { it.seq }}")

    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
ulasan siralar: [14, 15]
olay-12: anahtar=foto.belge | kopya=0 -> ezilen
olay-13: anahtar=foto.belge | kopya=0 -> ezilen
olay-14: anahtar=foto.belge | kopya=1 -> birebir
olay-15: anahtar=foto.sayfa | kopya=1 -> birebir
birebir: 2
yinelenen: 0
ezilen: 2
kayip: 0
```

12 ve 13 numaralı istekler sonuç üretmedi, ama aynı anahtarla 14 numaralı istek sonuç verdi. Kural bu yüzden ikisini kayıp değil ezilen saydı. Bu sayım kuralın tanımıyla tutarlıdır, ama fotoğraf açısından yanıltıcıdır: izinsiz istekler hiçbir fotoğrafın yerini almadı, çünkü fotoğraf hiç çekilmedi. Ezilen etiketi bu durumda yalnızca "aynı anahtarla daha sonra bir sonuç geldi" demektir; kullanıcının görmediği ve sonradan telafi edilmiş bir kayıp olarak okunmalıdır. Aynı durum anahtarlar farklı olsaydı kayıp olarak sayılacaktı. Kuralı ders kitabı gibi okumak, anahtar seçiminin sayıyı değiştirdiğini unutmamayı gerektirir.

**SY2.** Model, izni tek bir adımda ve kesin olarak verilmiş kabul eder. Platformda izin penceresi kullanıcıya birkaç kez gösterilebilir, "bir daha sorma" seçilirse ilerleyen çağrılar pencere göstermeden reddedilir ve izin sonradan ayarlardan verilebilir.

## Depolama Dolunca

Çekim sonucu bir dosyadır ve dosyanın yazılacağı bir yer olmalıdır. Depolama dolduğunda kitaplık sonucu kaydedemez ve hata geri çağrısına düşer. Modelde depolamanın kaç sonuç alabileceği tamsayı bir kapasitedir; sayı modelin uydurma değeridir.

```kotlin
// Storage.kt — depolama kapasitesi dolunca sonraki sonuclari birakir
fun store(results: List<Signal>, capacity: Int): List<Signal> =
    results.take(capacity)
```

```kotlin
// Main.kt — depolama dolunca sonraki cekimler ulasmaz
fun main() {
    val sent = listOf(
        Signal("foto.a", 5),
        Signal("foto.b", 6),
        Signal("foto.c", 7),
        Signal("foto.d", 8),
    )
    val received = store(shoot(sent), capacity = 2)
    println("ulasan siralar: ${received.map { it.seq }}")

    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
ulasan siralar: [5, 6]
olay-5: anahtar=foto.a | kopya=1 -> birebir
olay-6: anahtar=foto.b | kopya=1 -> birebir
olay-7: anahtar=foto.c | kopya=0 -> kayip
olay-8: anahtar=foto.d | kopya=0 -> kayip
birebir: 2
yinelenen: 0
ezilen: 0
kayip: 2
```

İlk iki çekim birebir ulaştı; 7 ve 8 numaralı çekimler kayıp oldu. Anahtarları farklı olduğu için hiçbiri bir diğerinin yerini almadı ve kural ezilen saymadı. Kural kaybın nedeninin dolu depolama olduğunu görmez; bunu bilmek için uygulamanın hata geri çağrısını dinlemesi gerekir.

**SY3.** Model, depolamayı sabit bir kapasiteyle kurar. Platformda boş yer kullanıcının başka işlerine göre değişir ve kapasite çekim sırasında tükenebilir; bu modelde yoktur.

## Medya Seçici ve Ortak Depolama

Her fotoğraf uygulamanın kendi çekimi olmayabilir. Kullanıcı galeriden mevcut bir fotoğrafı seçtiğinde seçim ortak bir medya deposundan gelir ve uygulamaya yalnızca seçilen dosyanın adresi verilir. Seçici ayrı bir izin istemez, çünkü uygulama bütün medyaya değil yalnızca kullanıcının seçtiğine erişir. Bu, teslim modelinde ayrı bir durumdur: seçim bir olaydır, ama olayın sahibi kullanıcıdır ve seçilen dosya gönderilip ulaşan bir sonuç gibi sayılabilir.

Çekimle seçim arasındaki fark, hata yolunun sorumluluğundadır. Çekimde depolama dolabilir ve izin eksik olabilir. Seçicide kullanıcı vazgeçebilir ve bu bir hata sayılmaz: boş bir sonuç döner. Vazgeçme, kayıp ya da ezilen değildir; çünkü hiçbir olay gönderilmemiştir. Bu ayrım, ölçüm modelinin sınırını gösterir: kural gönderilmiş olayları sayar, gönderilmemiş olayları değil.

## Önizleme Çekim Değildir

Kamera kitaplığı iki ayrı akış sunar: önizleme ve çekim. Önizleme ekranda sürekli güncellenen bir görüntüdür ve kullanıcıya kadrajı gösterir; çekim ise tek bir dosya üretir. Önizlemenin her karesi bir olay gibi görünür, ama uygulamaya teslim edilen bir sonuç değildir: kareler ekrana çizilir ve atılır. Bu dersin modelinde yalnızca çekim vardır, çünkü önizlemede alıcıya ulaşması gereken bir kare yoktur. Kareler atılabildiği için önizleme, konum ve sensör derslerindeki ezilen davranışının görsel karşılığıdır: yavaş bir ekran eski kareleri sessizce bırakır ve kimse bunu kayıp saymaz.

Çekim ise bırakılamaz. Kullanıcı bir fotoğraf istediğinde sonuç ya bir dosya ya da bir hatadır. Dosyanın yazılması zaman alır ve yazma bitmeden başarı geri çağrısı çalışmaz. Dosya yazılırken ekran gizlenirse, yazma çoğu zaman tamamlanır ama başarı geri çağrısı artık görünmeyen bir ekrana ulaşır. Bu durumda dosya vardır ve kullanıcı galeride görür; ama ekranın sonuca tepkisi, örneğin önizleme küçük resmini güncellemesi, gerçekleşmez. Kural açısından bu olay ulaştı sayılır; kullanıcı açısından ise sonucun yarısı kaybolmuştur. Modelin dışında kalan bu fark, sonucu ekrandan bağımsız bir yerde, örneğin bir görünüm modelinde, tutmayı gerektirir.

## Yaygın Yanılgılar

**"İkinci dokunuş ilk dokunuşun kopyasıdır."** Kopya, aynı sıranın birden çok kez ulaşmasıdır. İki dokunuş iki ayrı istektir ve sonuç da iki ayrıdır. Kullanıcının tek fotoğraf istediği durumda çözüm, ikinci dokunuşu istek verilmeden önce engellemektir; sonuç tarafında tekilleştirme iki fotoğrafı da çekilmiş haliyle bırakır.

**"Çekim isteği verildiyse fotoğraf vardır."** İstek yalnızca niyettir. Fotoğraf, başarı geri çağrısı çalıştığında vardır. Hata geri çağrısı çalıştıysa yoktur.

**"İzin bir kez verildi, kamera hep açılır."** Kamera başka bir uygulama tarafından kullanılıyor olabilir, aygıt kamerayı güç tasarrufu için kapatmış olabilir ya da kullanıcı izni sonradan geri almış olabilir. Her çekim isteğinde hata yolu hazır olmalıdır.

**"Dosya kaydedildiyse kullanıcı görmüştür."** Başarı geri çağrısı dosyanın yazıldığını bildirir, kullanıcının sonucu gördüğünü değil. Ekran o sırada gizliyse sonuç kayıtlıdır ama gösterilmemiştir. Uygulama sonucu ekran yeniden göründüğünde okuyabilecek bir yerde saklamazsa, kullanıcı fotoğrafı yalnızca galeride bulur.

**"Depolama doluluğu çekimden önce bilinemez."** Boş yer çekimden önce sorgulanabilir. Çekimden önce yapılan bir denetim, ölçümdeki iki kaybı kullanıcıya daha deklanşöre dokunmadan söylemeyi mümkün kılar; hata geri çağrısı ise son çaredir.

**"Önizleme görünüyorsa kamera hazırdır."** Önizleme çalışırken çekim hâlâ başarısız olabilir: depolama dolu, izin geri alınmış ya da bir önceki çekim henüz yazılıyor olabilir. Hazır olmayı çekim isteğinin sonucu belirler, önizleme belirlemez.

**"Ezilen yalnızca konum ve sensör için geçerlidir."** Ezilen, kuralın tanımında bir olayın yerini aynı anahtarlı daha yeni bir olayın alması demektir. İzinsiz istek ölçümünde olduğu gibi, çekimde de görülebilir. Kategori olayın türüne değil, anahtarlara ve sıralara bağlıdır.

**"Medya seçici de izin ister."** Seçici, kullanıcının kendi seçtiği dosyaya erişim verir; geniş depolama izni gerekmez.

## Sınırlayıcı Ölçüm

Deklanşöre art arda iki kez dokunulursa ne olur? Kullanıcı deklanşöre çabuk çabuk iki kez dokunduğunda uygulama iki ayrı çekim isteği verir. Bunlar aynı olayın iki kopyası değildir: iki ayrı istektir ve her biri kendi sırasını taşır.

```kotlin
// Main.kt — deklansore iki dokunus iki ayri sira olarak birebir ulasir
fun main() {
    val sent = listOf(
        Signal("foto.kapak", 9),
        Signal("foto.kapak", 10),
        Signal("foto.detay", 11),
    )
    val received = shoot(sent)
    val arrivals = sent.map { Arrival("olay-${it.seq}", it, received) }
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-9: anahtar=foto.kapak | kopya=1 -> birebir
olay-10: anahtar=foto.kapak | kopya=1 -> birebir
olay-11: anahtar=foto.detay | kopya=1 -> birebir
birebir: 3
yinelenen: 0
ezilen: 0
kayip: 0
```

9 ve 10 numaralı çekimler aynı anahtarı taşıyor, ama sıraları farklı olduğu için kural her birini kendi sırasına göre sayar. İkisi de birebir ulaştı; yinelenen sayılmadı. Yinelenen, aynı sıranın birden çok kez ulaşmasıdır. Kullanıcı iki fotoğraf istediyse iki fotoğraf alır. İkinci dokunuşun yoksayılmasını istiyorsak bu, uygulamanın kendi kuralıdır ve çekim isteğini vermeden önce uygulanmalıdır.

**SY4.** Model, iki dokunuşu iki bağımsız istek olarak kurar. Platformda kitaplık aynı anda tek bir çekim işlemeye izin verebilir ve ikinci isteği sıraya alabilir ya da reddedebilir; bu modelde yoktur.

## Özet

- Bu dersin teslimi: birebir. Her çekim isteği tek bir sonuç olarak ulaştı: birebir 4.
- Anahtarları farklı olan çekimler birbirinin yerini almaz; bu yüzden bu derste ezilen yoktur.
- Depolama dolunca sonraki iki çekim kayıp oldu: kayip 2. Kural nedeni görmez.
- İzin verilmeden yapılan iki istek, aynı anahtarlı sonraki istek ulaştığı için ezilen sayıldı: birebir 2, ezilen 2. Anahtar seçimi sayıyı değiştirir.
- Deklanşöre iki dokunuş iki ayrı sıradır ve ikisi de birebir ulaşır; yinelenen, aynı sıranın birden çok kez ulaşmasıdır.
- Kamera izni çalışma zamanı iznidir; sonuç geri çağrısı başarı ve hatayı ayırır.

## Sonraki Adım

Bu derste olay tek bir eylemden doğdu ve her isteğe tek bir sonuç verildi. Sensörlerde olay saniyede çok sayıda üretilir ve yavaş bir alıcı hepsine yetişemez. Sıradaki ders, `Sensörler`, yavaş alıcının atladığı sensör okumalarının teslimini ölçer.
