---
title: 'Bildirim Dosyası'
source: 'https://academia.sh/tr/kurslar/android-platformu/bildirim-dosyasi'
course: 'Android Platformu ve Araçlar'
language: tr
updated: '2026-10-21T05:02:36+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bildirim dosyasının uygulama bileşenlerini, izinleri ve donanım özelliklerini platforma bildirdiğini açıklar'
    - 'Bildirim dosyası birleştirmesinde bir öğenin istenenin korunması, üstüne yazılması ya da çakışma olarak sonuçlanmasını ayırır'
    - 'tools:replace işaretinin istenenin yerine verilen değeri koyduğunu ölçer'
    - 'Yer tutucunun değeri gelene kadar bekleyen, geldikten sonra tam karşılandığını sınırlayıcı ölçümle doğrular'
---

# Bildirim Dosyası

Bildirim dosyasının uygulamayı platforma tanıtma işlevinin ve birleştirmenin her öğe için istenenin korunup korunmadığı açısından modeli.

Önceki ders olan Görevler ve Geri Yığını, bir ekranın hangi göreve ve hangi sıraya yerleştiğini ölçtü. O ekran, bir uygulama bileşeni olarak platforma önceden tanıtılmadıkça hiç başlatılamaz. Bu tanıtmanın yeri bildirim dosyasıdır. Bu ders bildirim dosyasında ne yazdığını ve birden çok kaynaktan gelen bildirim dosyalarının tek dosyada nasıl birleştiğini ölçer.

Kursun ölçü ekseni açılış dersindeki gibidir: bu isteği platform nasıl karşılıyor. Karşılama dörttür: tam, ikame, bekleyen ve karşılıksız. Karşılamayı etiket değil kural verir: bekleyen ve karşılıksız doğrudan sonuçtan, verilen değer istenene eşitse tam, eşit değilse ikame çıkar. Aşağıdaki dosya o kuralı taşır ve her derste aynen yinelenir. Açılış dersindeki bağlayıcı sayı olan 3/2/2/1 burada değiştirilmez, yalnız atıfla anılır.

```kotlin
// Fulfillment.kt — bir istegin platformca nasil karsilandigini siniflandirir
sealed interface Outcome {
    data class Given(val value: String) : Outcome
    data class Waiting(val on: String) : Outcome
    data class Refused(val reason: String) : Outcome
}

class Ask(val label: String, val wanted: String, val outcome: Outcome) {
    val fulfillment: String = when (outcome) {
        is Outcome.Waiting -> "bekleyen"
        is Outcome.Refused -> "karsiliksiz"
        is Outcome.Given -> if (outcome.value == wanted) "tam" else "ikame"
    }

    fun report() {
        val detail = when (outcome) {
            is Outcome.Given -> "verilen=${outcome.value}"
            is Outcome.Waiting -> "bekledigi=${outcome.on}"
            is Outcome.Refused -> "neden=${outcome.reason}"
        }
        println("$label: istenen=$wanted | $detail -> $fulfillment")
    }
}

fun tally(asks: List<Ask>) {
    for (name in listOf("tam", "ikame", "bekleyen", "karsiliksiz")) {
        println("$name: ${asks.count { it.fulfillment == name }}")
    }
}
```

## Bildirim Dosyasının İşlevi

Bildirim dosyası (manifest) uygulamanın platforma verdiği yazılı beyandır. Platform uygulamayı çalıştırmadan önce bu dosyaya bakar ve dört şeyi öğrenir. Birincisi uygulama kimliğidir: uygulamayı aygıtta tekil kılan paket adı. İkincisi uygulama bileşenleridir: ekranlar, arka plan işleri, yayın alıcıları ve içerik sağlayıcılar burada bildirilmeyen bir bileşeni platform tanımaz. Üçüncüsü uygulamanın istediği izinlerdir. Dördüncüsü uygulamanın gerek duyduğu donanım özellikleridir; örneğin kamera `uses-feature` öğesiyle zorunlu ya da isteğe bağlı bildirilir. Aşağıdaki parça bu dört şeyi taşıyan küçük bir dosyadır.

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-feature android:name="android.hardware.camera" android:required="true" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application android:label="Notlar" android:allowBackup="true">
        <activity android:name=".NoteListActivity" android:exported="true" />
    </application>
</manifest>
```

Bu parça platform biçimindedir ve çalıştırılmaz. Bundan sonraki ölçümler dosyanın kendisini değil, birleştirme kuralını modeller. Model, platformun bu kuralını kurar: platformun gerçek birleştirme aracı değildir.

## Birleştirmenin Modeli

Bir uygulama tek bildirim dosyasıyla gelmez. Uygulama modülünün dosyası vardır; eklenen her kitaplık kendi dosyasını getirir; derleme varyantına özgü dosyalar da olabilir. Derleme adımı bunları tek dosyada birleştirir. Çakışma olmadığında öğeler olduğu gibi bir araya gelir. Aynı öğenin aynı özniteliği iki dosyada farklı değerdeyse birleştirme çözümü kendiliğinden bulamaz: yazar, uygulama dosyasında öğeyi `tools:replace` ile işaretleyip üstüne yazacağını bildirmedikçe birleştirme hatayla durur.

Model bunu öğe başına bir istek olarak kurar. İstenen, kitaplığın öğe için yazdığı değerdir. Uygulama o öğeye dokunmamışsa ya da aynı değeri yazmışsa kitaplığın değeri korunur. Uygulama farklı bir değer yazmış ve öğeyi `tools:replace` ile işaretlemişse verilen değer uygulamanınkidir. İşaret yoksa çakışma kalır ve değer verilmez. `mergeManifest` bunu uygular; tek katman olarak yalnız uygulama ile kitaplık alınır.

```kotlin
// Merge.kt — bildirim dosyasi birlestirmesi modeli
class Layer(val values: Map<String, String>, val replaced: Set<String> = emptySet())

fun mergeManifest(app: Layer, library: Layer): List<Ask> =
    library.values.toSortedMap().map { (key, wanted) ->
        val own = app.values[key]
        val outcome = when {
            own == null || own == wanted -> Outcome.Given(wanted)
            key in app.replaced -> Outcome.Given(own)
            else -> Outcome.Refused("isaretsiz-cakisma")
        }
        Ask(key, wanted, outcome)
    }
```

Anahtarlar `öğe.öznitelik` biçimindedir ve basılmadan önce sıralanır. İlk ölçümde kitaplık iki öğe getirir: kamerayı zorunlu bildiren donanım özelliği ve sağdan sola yazımı destekleyen bir uygulama özniteliği. Uygulama bu ikisine dokunmaz, yalnız kendi etiketini ve kendi ekranını yazar.

```kotlin
// Main.kt — cakismasiz birlestirme
fun main() {
    val app = Layer(mapOf(
        "application.label" to "Notlar",
        "activity.NoteListActivity" to "exported",
    ))
    val library = Layer(mapOf(
        "uses-feature.camera" to "required",
        "application.supportsRtl" to "true",
    ))
    val asks = mergeManifest(app, library)
    for (ask in asks) ask.report()
    tally(asks)
}
```

```text
application.supportsRtl: istenen=true | verilen=true -> tam
uses-feature.camera: istenen=required | verilen=required -> tam
tam: 2
ikame: 0
bekleyen: 0
karsiliksiz: 0
```

İki öğe de istenen gibi korundu. Ölçü yalnız `tam` sayısını değil, her öğenin kendi satırını verir: kitaplığın istediği bir değerin sessizce kaybolmadığı satırda görülür.

**AP1.** İlk iki ölçümde model yalnız iki katmanı, uygulama ve tek bir kitaplığı, birleştirir; üç katman sonraki bölümde ayrıca ölçülür. Birden çok kitaplık ya da derleme varyantı dosyası olduğunda öncelik sırasının nasıl işlediği bu ölçümlerde yoktur.

**AP2.** Her öğe tek bir anahtar ve tek bir değerle temsil edilir. Gerçek bildirim dosyasında bir öğenin birden çok özniteliği vardır; model bunları ayrı anahtarlar sayar.

## Üstüne Yazma ve Çakışma

İkinci ölçüm çakışmaları içerir. Kitaplık üç öğe getirir. `application.label` için uygulama aynı değeri yazmıştır. `application.allowBackup` için kitaplık `true` ister, uygulama `false` yazmıştır ve öğeyi `tools:replace` ile işaretlemiştir. `application.theme` için de değerler farklıdır ama uygulama öğeyi işaretlememiştir.

```kotlin
// Main.kt — ustune yazma ve cakisma
fun main() {
    val app = Layer(
        values = mapOf(
            "application.label" to "Notlar",
            "application.allowBackup" to "false",
            "application.theme" to "Koyu",
        ),
        replaced = setOf("application.allowBackup"),
    )
    val library = Layer(mapOf(
        "application.label" to "Notlar",
        "application.allowBackup" to "true",
        "application.theme" to "Acik",
    ))
    val asks = mergeManifest(app, library)
    for (ask in asks) ask.report()
    tally(asks)
}
```

```text
application.allowBackup: istenen=true | verilen=false -> ikame
application.label: istenen=Notlar | verilen=Notlar -> tam
application.theme: istenen=Acik | neden=isaretsiz-cakisma -> karsiliksiz
tam: 1
ikame: 1
bekleyen: 0
karsiliksiz: 1
```

Üç öğe üç ayrı karşılamaya düştü. `allowBackup` ikamedir: bir değer verildi, ama kitaplığın istediği değil. Kural bunu `true` ile `false` farkından görür, yazarın bilerek yaptığını bilmez. `theme` karşılıksızdır: değer verilmedi, çünkü işaretsiz çakışma birleştirmeyi durdurur. Kuralın gördüğü yalnız sonuç ve eşitliktir; `tools:replace`'in orada olup olmadığı karşılamayı doğrudan değil, verilen değer üzerinden etkiler.

M30/K02'de iki tanım buluşunca nasıl çözüldüğü sorulmuş, o kursun izin dersleri istenen ile verilen kümelerin buluşmasını ölçmüştü. Bu derste ölçü o değildir: iki kümenin buluşması değil, her öğenin ayrı bir istek olarak istenenin korunup korunmadığı ölçülür. Aynı iki dosya aynı anahtar kümesine sahip olabilir ve yine de öğelerin bir kısmı tam, bir kısmı ikame olur.

## Birleştirme Önceliği

Bildirim dosyası tek bir dosya değildir. Derleme sırasında uygulamanın ana dosyası, derleme varyantının dosyaları ve her kitaplığın kendi dosyası birleştirilir. Öncelik sırası kitaplıktan varyanta doğru artar: kitaplık en düşük önceliktedir, uygulamanın ana dosyası ortada durur ve derleme varyantının dosyaları en yüksek önceliktedir. Düşük öncelikli katmanın yazdığı değeri yüksek öncelikli katman aynen bırakabilir, aynı değerle yineleyebilir ya da farklı bir değerle işaretleyerek ezebilir. Aşağıdaki parça iki işareti gösterir: `tools:replace` öznitelik değerini ezer, `tools:node="remove"` öğeyi birleşimden çıkarır.

```xml
<application
    android:label="@string/app_name"
    tools:replace="android:label">
    <activity android:name=".LegacyScreen" tools:node="remove" />
</application>
```

Model bu önceliği üç katmanlı bir zincir olarak kurar. İstenen, en düşük katmanın yani kitaplığın yazdığı değerdir. Sonraki her katman değeri korur, aynı değeri yineler ya da farklı bir değer yazar. Farklı değer yalnız o katman öğeyi işaretlemişse geçer; işaretsiz fark çakışmadır ve zincir orada durur. Kitaplıkta hiç bulunmayan bir öğe için istenecek bir değer olmadığından model onu karşılıksız verir.

```kotlin
// Chain.kt — katmanli birlestirme modeli
fun mergeChain(key: String, layers: List<Layer>): Ask {
    val wanted = layers.first().values[key] ?: return Ask(key, "-", Outcome.Refused("kitaplikta-yok"))
    var current = wanted
    for (layer in layers.drop(1)) {
        val value = layer.values[key] ?: continue
        if (value == current) continue
        if (key in layer.replaced) current = value
        else return Ask(key, wanted, Outcome.Refused("isaretsiz-cakisma"))
    }
    return Ask(key, wanted, Outcome.Given(current))
}
```

İlk ölçümde üç katman vardır ve sıra kitaplık, ana dosya, varyanttır. Kitaplık üç öğe yazar. Uygulamanın ana dosyası bir öğeyi aynı değerle yineler ve bir öğeyi işaretsiz farklı bir değerle yazar. Varyant bir öğeyi işaretleyerek ezer.

```kotlin
// Main.kt — uc katman
fun main() {
    val library = Layer(mapOf("etiket" to "kitapligin-adi", "yon" to "sagdan-sola", "kamera" to "zorunlu"))
    val variant = Layer(mapOf("etiket" to "varyantin-adi"), setOf("etiket"))
    val app = Layer(mapOf("yon" to "sagdan-sola", "kamera" to "istege-bagli"))
    val asks = listOf("etiket", "yon", "kamera").map { mergeChain(it, listOf(library, app, variant)) }
    for (ask in asks) ask.report()
    tally(asks)
}
```

```text
etiket: istenen=kitapligin-adi | verilen=varyantin-adi -> ikame
yon: istenen=sagdan-sola | verilen=sagdan-sola -> tam
kamera: istenen=zorunlu | neden=isaretsiz-cakisma -> karsiliksiz
tam: 1
ikame: 1
bekleyen: 0
karsiliksiz: 1
```

Öğe `etiket` varyant tarafından ezilince verilen, istenenden farklı olduğu için ikamedir. Öğe `yon` hiç değişmedi ve tamdır. Öğe `kamera` işaretsiz bir farkla karşılaştı: uygulama kitaplığın zorunlu dediği donanımı isteğe bağlı yazdı ama öğeyi işaretlemedi, bu yüzden değer verilmedi.

**AP3.** Model katman sırasını sabit alır: kitaplık, uygulamanın ana dosyası, varyant. Gerçek birleştirmede birden çok kitaplığın ve birden çok varyant dosyasının kendi arasındaki sırası ayrıca belirlenir; ölçüm bunu kapsamaz.

## Çakışmanın Çözülmesi

İşaretsiz bir çakışma iki biçimde çözülür: ya düşük öncelikli katman değerini bırakır ya da yüksek öncelikli katman öğeyi işaretler. Kitaplık dosyasını değiştirmek çoğu zaman mümkün olmadığından çözüm uygulama tarafındadır. İşaretin yerine göre sonuç değişir: işaret ezen katmanda durursa değer ezilir, işaret araya başka bir katman girdiğinde yalnız o katmana kadar etki eder. Aşağıdaki ölçüm iki ayrı durumu karşılaştırır. Birincisinde uygulama kamera öğesini işaretleyerek ezer. İkincisinde işareti uygulamanın ana dosyası koymuştur ve varyant dosyası sonradan farklı bir değer yazar.

```kotlin
// Main.kt — isaretin yeri
fun main() {
    val library = Layer(mapOf("kamera" to "zorunlu"))
    val marked = Layer(mapOf("kamera" to "istege-bagli"), setOf("kamera"))
    val appMarked = Layer(mapOf("kamera" to "istege-bagli"), setOf("kamera"))
    val variantOther = Layer(mapOf("kamera" to "yasak"))
    val asks = listOf(
        mergeChain("kamera", listOf(library, marked)).let { Ask("uygulama-isaretli", it.wanted, it.outcome) },
        mergeChain("kamera", listOf(library, appMarked, variantOther)).let { Ask("ana-dosya-isaretli", it.wanted, it.outcome) },
    )
    for (ask in asks) ask.report()
    tally(asks)
}
```

```text
uygulama-isaretli: istenen=zorunlu | verilen=istege-bagli -> ikame
ana-dosya-isaretli: istenen=zorunlu | neden=isaretsiz-cakisma -> karsiliksiz
tam: 0
ikame: 1
bekleyen: 0
karsiliksiz: 1
```

İşaret yalnız onu koyan katmanın değerini korur; sonraki katmanın farklı değeri yeniden işaret ister. Kural bunu ayırt eder: iki istek aynı öğeye bakar ama ilkinde zincirin son halkası işaretlidir, ikincisinde değildir.

**AP4.** Model işareti öğe düzeyinde tutar. Gerçek dosyada işaret öznitelik düzeyinde de verilebilir ve birden çok özniteliği aynı anda kapsayabilir; ölçüm bunu ayırmaz.

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

Modelin ölçemediği bir yan var: değer bildirim dosyasında yazılı olmayabilir. Kitaplık ya da uygulama dosyası değeri `${appLabel}` gibi bir yer tutucuyla (placeholder) bırakır; gerçek değeri derleme varyantının ayarı verir. Yer tutucu çözülmeden birleştirme sonucu belli olmaz. `resolvePlaceholder` aynı öğeyi iki kez sorar: önce varyant değeri vermemişken, sonra vermişken.

```kotlin
// Placeholder.kt — yer tutucunun cozulmesi
fun resolvePlaceholder(label: String, wanted: String, token: String, provided: Map<String, String>): Ask {
    val value = provided[token]
    val outcome = if (value == null) Outcome.Waiting("derleme-varyanti") else Outcome.Given(value)
    return Ask(label, wanted, outcome)
}
```

```kotlin
// Main.kt — ayni oge, iki an
fun main() {
    val before = resolvePlaceholder("application.label", "Notlar", "appLabel", emptyMap())
    val after = resolvePlaceholder("application.label", "Notlar", "appLabel", mapOf("appLabel" to "Notlar"))
    val asks = listOf(before, after)
    for (ask in asks) ask.report()
    tally(asks)
}
```

```text
application.label: istenen=Notlar | bekledigi=derleme-varyanti -> bekleyen
application.label: istenen=Notlar | verilen=Notlar -> tam
tam: 1
ikame: 0
bekleyen: 1
karsiliksiz: 0
```

Aynı öğe önce bekleyen, sonra tam oldu. Bekleyen karşılama kalıcı bir sonuç değil, bir andır: kuralın bekleyen dediği şey, bekleneni veren gelince başka bir sonuca döner. Bu yüzden iki satır aynı etiketi taşır ve sayım iki ayrı istek gibi görür. Ölçü, yer tutucunun değerinin yanlış olup olmadığını da söylemez; yalnız verilenin istenene eşit olup olmadığına bakar.

**AP5.** Model yer tutucu çözülmediğinde derlemenin gerçekte ne ürettiğini, yani hata mı verdiğini yoksa boş bir değerle mi sürdüğünü iddia etmez. Bekleyen karşılama yalnız modelin sınıflandırmasıdır.

## Özet

- Bu dersin ölçütü: **karşılama**; birleştirmede her öğe için istenenin korunup korunmadığı, küme değil öğe başına istek. Bu dersin karşılaması: **tam**.
- Bildirim dosyası uygulama kimliğini, uygulama bileşenlerini, izinleri ve donanım özelliklerini platforma bildirir.
- Birleştirmede kitaplığın değeri uygulama dokunmadığı ya da aynısını yazdığı sürece tam korunur.
- `tools:replace` ile üstüne yazılan öğe ikamedir: verilen değer istenenden farklıdır. İşaretsiz çakışma karşılıksızdır.
- Yer tutucu, değerini derleme varyantı verene kadar bekleyendir; verdikten sonra aynı öğe tam olur.

## Sonraki Adım

Bildirim dosyası uygulamanın ne olduğunu bildirir; ekranlarda gösterilen metin, görsel ve düzen ise kaynaklarda durur. Sonraki ders, kaynak sisteminin istenen yapılandırma için kaynak seçerken tam eşleşme bulunamadığında ne verdiğini ölçer.
