Что такое манифест приложения: назначение, структура и отличия по платформам

Манифест приложения — это структурированный файл метаданных, который сообщает операционной системе, среде выполнения или магазину приложений, как именно запускать, отображать и защищать ваше программное обеспечение. Без него современная ОС не знает, какую точку входа использовать, какие разрешения запрашивать, какому окну назначить иконку или как обновить версию. Понимание структуры манифеста необходимо не только при первой публикации, но и при каждом обновлении, смене иконки, добавлении новой возможности или переносе на другую платформу.

Главный принцип: манифест — это декларативный контракт между приложением и средой. Он не содержит исполняемого кода, а описывает намерения: «хочу доступ к камере», «запускай меня в полноэкранном режиме», «моя версия 2.3.1 совместима с API 33». Ошибка в этом контракте приводит к отказу в публикации, крашам при старте, утечкам приватных данных или невидимости приложения для пользователя.

Содержание
  1. Зачем нужен манифест: три базовые функции
  2. Основные платформы и их форматы манифеста
  3. Android: AndroidManifest.xml
  4. iOS / iPadOS / macOS: Info.plist
  5. Веб-приложения и PWA: manifest.json
  6. Windows (MSIX / AppX / Desktop Bridge): Package.appxmanifest
  7. Kubernetes: манифесты ресурсов (YAML)
  8. Другие среды
  9. Ключевые поля, которые встречаются почти везде
  10. Практический чек-лист проверки манифеста перед релизом
  11. Типичные ошибки и их последствия
  12. Сценарии: как действовать в типичных ситуациях
  13. Сценарий 1: Первая публикация в Google Play и App Store
  14. Сценарий 2: Добавление новой функции, требующей разрешения (например, Bluetooth-сканирование)
  15. Сценарий 3: Миграция на новый targetSdk / минимальную ОС
  16. Сценарий 4: Настройка PWA для установки на мобильный и десктоп
  17. Инструменты для работы с манифестами
  18. FAQ: частые вопросы
  19. Можно ли изменить package name / Bundle ID после публикации?
  20. Зачем нужен versionCode, если есть versionName?
  21. Почему Android требует android:exported явно, а iOS — нет?
  22. Нужен ли манифест для кроссплатформенных фреймворков (Flutter, React Native, Kotlin Multiplatform)?
  23. Что такое Trusted Web Activity (TWA) и как он связан с манифестом?
  24. Как проверить манифест на устройстве пользователя без доступа к исходникам?
  25. Резюме: следующий шаг

Зачем нужен манифест: три базовые функции

В любой платформе манифест решает три задачи:

  • Идентификация и запуск. Указывает точку входа (Activity, main.js, EntryPoint), имя пакета, версию, иконку, отображаемое имя. Без этого установщик не знает, что именно запускать и как показать приложение в лаунчере.
  • Декларация возможностей и ограничений. Перечисляет разрешения (камера, геолокация, интернет), минимальную и целевую версию ОС, поддерживаемые архитектуры, ориентации экрана, режимы совместимости.
  • Безопасность и изоляция. Определяет, какие компоненты экспортированы (доступны другим приложениям), какие данные можно резервировать, какие домены разрешены для сетевых запросов, какие цифровые подписи ожидаются.

Игнорирование любой из этих функций приводит к предсказуемым проблемам: отсутствие разрешения на камеру — краш при попытке сфотографировать; неверная минимальная версия API — установка на несовместимых устройствах с последующими ошибками; экспортированный провайдер без защиты — утечка базы данных стороннему приложению.

Основные платформы и их форматы манифеста

Формат файла и набор полей зависят от целевой среды. Ниже — краткий обзор самых распространённых вариантов.

Android: AndroidManifest.xml

Обязательный XML-файл в корне модуля app. Сборщик (Gradle) объединяет манифесты всех подключённых библиотек и модулей в итоговый файл внутри APK/AAB. Ключевые секции:

  • — корневой элемент с атрибутами package (идентификатор приложения), android:versionCode (целое число для сравнения версий), android:versionName (строковое представление для пользователя).
  • — minSdkVersion (минимальный API), targetSdkVersion (API, под который тестировалось поведение), maxSdkVersion (редко используется).
  • и — объявление опасных и обычных разрешений. С Android 6.0 (API 23) опасные разрешения запрашиваются в рантайме, но декларация в манифесте остаётся обязательной.
  • — глобальные атрибуты: android:icon, android:label, android:theme, android:allowBackup, android:networkSecurityConfig, android:extractNativeLibs.
  • Компоненты: , , , . У каждого — атрибуты android:exported (критично с Android 12 / API 31: должно быть явно true или false), android:permission, для запуска через лаунчер, диплинки, системные события.

Типичная ошибка: забыть добавить android:exported=»false» к внутренним сервисам или провайдерам — сборка упадёт с ошибкой Manifest merger failed при таргете API 31+.

iOS / iPadOS / macOS: Info.plist

Файл в формате Property List (XML или бинарный). Xcode генерирует его из цели (Target) → Info, но часто требует ручного редактирования. Ключи делятся на системные (префикс UI, NS, LS, CFBundle) и пользовательские.

  • Идентификация: CFBundleIdentifier (bundle ID), CFBundleShortVersionString (маркетинговая версия), CFBundleVersion (билд-номер), CFBundleDisplayName (имя под иконкой).
  • Точка входа: UIMainStoryboardFile или UILaunchStoryboardName / UISceneStoryboardFile для SceneDelegate.
  • Разрешения (Privacy Keys): NSCameraUsageDescription, NSLocationWhenInUseUsageDescription, NSMicrophoneUsageDescription и др. Обязательны строковые описания — без них App Store Connect отклонит сборку, а приложение упадёт при обращении к API.
  • Сетевая безопасность: NSAppTransportSecurity с NSAllowsArbitraryLoads (не рекомендуется для продакшена) или доменные исключения NSExceptionDomains.
  • Поддержка ориентаций: UISupportedInterfaceOrientations (массив строк), отдельно для iPhone и iPad.
  • URL-схемы и Universal Links: CFBundleURLTypes для кастомных схем (myapp://), com.apple.developer.associated-domains в Entitlements для Universal Links.

Отличие от Android: Info.plist не декларирует компоненты (ViewController, Service) — они подключаются через код и Storyboard/XIB. Entitlements (файл .entitlements) вынесен отдельно и подписывается вместе с бинарником; он управляет возможностями: Push Notifications, App Groups, Keychain Sharing, iCloud, Wallet.

Веб-приложения и PWA: manifest.json

JSON-файл, подключаемый через . Стандартизирован W3C (Web App Manifest). Позволяет установить веб-приложение на главный экран как нативное.

  • name / short_name — полное и краткое имя.
  • start_url — относительный URL точки входа при запуске с иконки (часто / или /?source=pwa для аналитики).
  • display — standalone (как нативное, без адресной строки), fullscreen, minimal-ui, browser.
  • icons — массив объектов с src, sizes (например, 192×192, 512×512), type (image/png, image/svg+xml), purpose (any, maskable). Maskable-иконки нужны для адаптивных иконок Android.
  • theme_color и background_color — цвет панели инструментов и фон сплэш-скрина.
  • orientation — portrait, landscape, any.
  • scope — навигационная область; переход за её пределы открывает браузер.
  • shortcuts — массив быстрых действий (App Shortcuts) с name, url, icons.

Важно: manifest.json не заменяет Service Worker. Для офлайн-работы и кэширования нужен отдельный SW, регистрируемый в основном JS. Манифест только описывает «устанавливаемость» и внешний вид.

Windows (MSIX / AppX / Desktop Bridge): Package.appxmanifest

XML-файл по схеме Microsoft. Используется для UWP, WinUI 3, упакованных Win32-приложений (MSIX). Основные разделы:

  • Identity — Name, Publisher, Version (четырёхчастная: Major.Minor.Build.Revision).
  • Properties — DisplayName, PublisherDisplayName, Logo (50×50), Description.
  • Dependencies — TargetDeviceFamily (MinVersion, MaxVersionTested) для Windows 10/11.
  • Resources — языки, масштабы ресурсов.
  • Applications / Application — Id, EntryPoint (для UWP — App, для Win32 — Windows.FullTrustApplication), Executable (путь к .exe внутри пакета), VisualElements (иконки, плитки, фон).
  • Capabilities — internetClient, microphone, location, documentsLibrary, runFullTrust (для Win32 в MSIX).
  • Extensions — файловые ассоциации, протоколы (URI schemes), фоновые задачи, Share Target, AppUriHandlers.

Для классических Win32 без упаковки манифест не обязателен, но app.manifest (embedded resource) нужен для DPI-awareness, High DPI, Common Controls 6.0, requestedExecutionLevel (asInvoker / requireAdministrator).

Kubernetes: манифесты ресурсов (YAML)

В экосистеме Kubernetes «манифест» — это YAML-файл (или набор файлов), описывающий желаемое состояние ресурсов: Deployment, Service, Ingress, ConfigMap, Secret, PersistentVolumeClaim. Это не манифест одного приложения в привычном смысле, а декларация инфраструктуры для этого приложения.

  • apiVersion, kind, metadata (name, namespace, labels, annotations).
  • spec — специфика ресурса: replicas, selector, template (pod spec с containers, volumes, env, ports, readiness/liveness probes), strategy.
  • Helm-чарты и Kustomize позволяют параметризовать манифесты под окружения (dev, staging, prod) без дублирования.

Ошибка: хранить Secret в открытом виде в Git. Используйте Sealed Secrets, External Secrets Operator или Vault-injection.

Другие среды

  • Electron / Tauri / Wails — используют package.json (name, version, main, build.appId, build.win/appId, build.mac/bundleId) и конфиги пакета (builder.yml, tauri.conf.json) для генерации нативных манифестов под каждую ОС.
  • Chrome Extensions (MV3) — manifest.json с manifest_version: 3, action, background.service_worker, permissions, host_permissions, content_scripts.
  • Firefox Add-ons / Safari Web Extensions — схожий JSON, но с различиями в доступных API и ключах.
  • Flatpak / Snap / AppImage — метаданные в metadata (Flatpak), snapcraft.yaml (Snap), встроенные в AppImage.

Ключевые поля, которые встречаются почти везде

Независимо от платформы, в любом манифесте вы встретите эквиваленты этих сущностей:

Суть Android iOS (Info.plist) Web (manifest.json) Windows (MSIX) Kubernetes
Уникальный идентификатор package CFBundleIdentifier — (origin + scope) Identity/Name metadata.name + namespace
Версия для пользователя versionName CFBundleShortVersionString version (нестандарт) Version metadata.labels[‘app.kubernetes.io/version’]
Версия для системы versionCode CFBundleVersion Version (Build)
Отображаемое имя android:label CFBundleDisplayName name / short_name Properties/DisplayName
Иконки android:icon (mipmap) CFBundleIcons / Assets.xcassets icons[] VisualElements/Logo + Tile
Минимальная ОС minSdkVersion MinimumOSVersion — (feature detection) TargetDeviceFamily/MinVersion — (node selector / k8s version)
Разрешения / Capabilities uses-permission Privacy Keys + Entitlements permissions (extensions) Capabilities RBAC, PSP, SecurityContext
Точка входа Activity с MAIN/LAUNCHER UIMainStoryboardFile / @main start_url Application/EntryPoint + Executable
Сетевая политика networkSecurityConfig NSAppTransportSecurity CSP, Service Worker Capability internetClient NetworkPolicy, Egress

Практический чек-лист проверки манифеста перед релизом

Перед каждой сборкой для магазина или продакшена пройдитесь по пунктам. Это сэкономит дни модерации и ночные откаты.

  1. Идентификатор и версия. Bundle ID / package name совпадает с зарегистрированным в консоли разработчика. versionCode / CFBundleVersion строго больше предыдущей релизной. versionName / CFBundleShortVersionString понятен пользователю (semver: major.minor.patch).
  2. Минимальная и целевая ОС. minSdkVersion / MinimumOSVersion обоснована: вы тестировали на этом минимальном API. targetSdkVersion / TargetDeviceFamily соответствует актуальной SDK на дату релиза (Google Play и App Store требуют таргетить свежие версии в течение 6–12 месяцев после выхода).
  3. Разрешения — принцип минимальности. Удалите всё, чем не пользуетесь в коде. Каждое лишнее разрешение — лишний вопрос у пользователя и повод для отказа в установке. Проверьте: если убрали функцию камеры, убрали ли CAMERA / NSCameraUsageDescription?
  4. Описания приватности (iOS) / rationale (Android). Строки NS*UsageDescription понятны нетехническому человеку: «Приложению нужен доступ к фото, чтобы вы могли прикрепить фото к отчёту». В Android 13+ для некоторых разрешений (например, уведомления) нужен рантайм-диалог с объяснением — подготовьте строки.
  5. Экспорт компонентов (Android). У каждого , , , явно задан android:exported. Внутренние — false. Публичные (диплинки, платежи, шаринг) — true с защитой android:permission или проверкой подписи вызывающего.
  6. Сетевая безопасность. Android: network_security_config.xml с cleartextTrafficPermitted=»false» (дефолт с API 28), пиннинг сертификатов для критических API. iOS: NSAppTransportSecurity без NSAllowsArbitraryLoads или с точечными исключениями. Web: CSP заголовки, manifest.json не разрешает обходить CSP.
  7. Иконки и адаптивные ресурсы. Android: мipmap-anydpi-v26 с foreground/background для адаптивных иконок. iOS: все размеры в Assets.xcassets (20–1024 pt), включая App Store 1024×1024. Web: maskable 512×512 + purpose=»maskable». Windows: Square44x44Logo, Square150x150Logo, Wide310x150Logo.
  8. Диплинки / App Links / Universal Links. Android: с android:autoVerify=»true» + assetlinks.json на домене. iOS: apple-app-site-association на /.well-known/ + Associated Domains Entitlement. Проверьте через adb shell am start -W -a android.intent.action.VIEW -d «https://domain/path» и xcrun simctl openurl booted «https://domain/path».
  9. Бэкап и отладка. Android: android:allowBackup=»false» для финансовых/медицинских приложений или кастомный android:fullBackupContent с исключением БД/токенов. android:debuggable=»false» в release (обычно проставляет Gradle автоматически). iOS: UIFileSharingEnabled / LSSupportsOpeningDocumentsInPlace только если нужно.
  10. Локализация строк манифеста. Android: строки в strings.xml по локалям, в манифесте — @string/app_name. iOS: InfoPlist.strings для CFBundleDisplayName, NS*UsageDescription. Web: отдельные manifest.json по локалям или динамическая генерация.

Типичные ошибки и их последствия

  • Неувеличенный versionCode / CFBundleVersion. Магазин отклонит загрузку: «Version code already exists». Приходится пересобирать артефакт.
  • Отсутствие NS*UsageDescription. App Store Connect: «Missing Purpose String». Краш при обращении к API на устройстве пользователя.
  • android:exported не задан при targetSdk 31+. Сборка не проходит: Manifest merger failed: Apps targeting Android 12 and higher are required to specify an explicit value for android:exported.
  • Жёсткодированные URL в манифесте. Смена среды (staging → prod) требует пересборки. Используйте BuildConfig / xcconfig / переменные окружения CI для подстановки.
  • Лишние разрешения. Пользователь видит «Приложение хочет доступ к контактам» для калькулятора — отказ в установке, негативные отзывы, проверка политики Google Play / App Store.
  • Несовпадение package name / Bundle ID с консолью. Нельзя загрузить артефакт; нельзя обновить существующее приложение (придётся публиковать как новое, теряя пользователей и отзывы).
  • Отсутствие assetlinks.json / apple-app-site-association. Диплинки открывают браузер вместо приложения. Потеря конверсии из email/SMS/QR-кодов.
  • Иконки только в одном разрешении. Размытость на новых экранах, предупреждения в консоли разработчика, плохой вид в лаунчере.
  • Secret в Kubernetes-манифесте в Git. Утечка токенов, ключей БД, сертификатов. Компромисс инфраструктуры.

Сценарии: как действовать в типичных ситуациях

Сценарий 1: Первая публикация в Google Play и App Store

  1. Зарезервируйте package name / Bundle ID в консолях. Они должны совпадать (желательно) или быть документированно разными.
  2. Заведите versionCode = 1, versionName = «1.0.0» / CFBundleVersion = «1», CFBundleShortVersionString = «1.0.0».
  3. Определите minSdkVersion / MinimumOSVersion по аналитике целевой аудитории (например, API 24 / iOS 15).
  4. Добавьте только необходимые разрешения с понятными описаниями.
  5. Подготовьте полный набор иконок (Android: mipmap-anydpi-v26 + legacy; iOS: все слоты в Assets.xcassets).
  6. Настройте Network Security Config / ATS.
  7. Сгенерируйте подписанный AAB / IPA, загрузите в Internal Testing / TestFlight, прогоните smoke-тесты на физических устройствах с минимальной и максимальной поддерживаемой ОС.
  8. Настройте Deep Links / Universal Links, проверьте assetlinks.json и apple-app-site-association.
  9. Отправьте на модерацию.

Сценарий 2: Добавление новой функции, требующей разрешения (например, Bluetooth-сканирование)

  1. Добавьте разрешение в манифест: Android — BLUETOOTH_SCAN (API 31+), BLUETOOTH_CONNECT; iOS — NSBluetoothAlwaysUsageDescription + UIBackgroundModes: bluetooth-central.
  2. Реализуйте рантайм-запрос с объяснением (Android: ActivityCompat.requestPermissions; iOS — системный диалог с вашей строкой).
  3. Обновите versionCode / CFBundleVersion.
  4. Протестируйте сценарий отказа пользователя: приложение не должно падать, должна быть понятная заглушка.
  5. Выкатите обновление.

Сценарий 3: Миграция на новый targetSdk / минимальную ОС

  1. Изучите release notes новой SDK: изменения в поведении (behavior changes), удалённые API, новые требования к манифесту (например, android:exported в API 31, SAFE_AREA в iOS 11+).
  2. Обновите targetSdkVersion / TargetDeviceFamily.
  3. Запустите полную регрессию на устройствах/эмуляторах с новой ОС.
  4. Исправьте депрекейты в коде и манифесте (замените android:requestLegacyExternalStorage на Scoped Storage, обновите UIWebView на WKWebView и т.д.).
  5. Поднимите versionCode, выкатите.

Сценарий 4: Настройка PWA для установки на мобильный и десктоп

  1. Создайте manifest.json с display: «standalone», start_url: «/?source=pwa», иконками 192, 512 (maskable).
  2. Добавьте во все HTML-страницы.
  3. Настройте Service Worker (Workbox / ручной) для кэширования статики и офлайн-страницы.
  4. Проверьте в Chrome DevTools → Application → Manifest: нет ошибок, иконки загружены, start_url валиден.
  5. Протестируйте установку: Chrome Android → «Установить приложение», Edge/Chrome Desktop → иконка в адресной строке.
  6. Добавьте shortcuts для частых действий (новый заказ, чат, профиль).

Инструменты для работы с манифестами

  • Android Studio → Merged Manifest — показывает итоговый манифест после объединения всех модулей и библиотек с подсветкой конфликтов.
  • aapt2 dump badging app.aab — быстро посмотреть package, versionCode, permissions, activities, иконки без распаковки.
  • Xcode → Target → Info — визуальный редактор Info.plist с подсказками по ключам.
  • plutil -lint Info.plist — валидация синтаксиса в CI.
  • PWA Builder (pwabuilder.com) — генерация manifest.json, проверка, упаковка в MSIX для Microsoft Store, APK для TWA (Trusted Web Activity).
  • Lighthouse (Chrome DevTools) — аудит PWA: наличие манифеста, иконок, SW, HTTPS.
  • kubeval / kubeconform — валидация Kubernetes-манифестов по схемам API в CI.
  • helm template — рендеринг чартов для проверки итоговых YAML перед apply.
  • MakeAppx.exe / msix-packaging-tool — упаковка и проверка MSIX-манифеста.

FAQ: частые вопросы

Можно ли изменить package name / Bundle ID после публикации?

Нет. Это создаёт новое приложение в магазине. Пользователи не получат обновление, вы потеряете отзывы, рейтинг и историю загрузок. Единственный вариант — опубликовать как отдельное приложение и мигрировать пользователей вручную (диплинк, уведомление).

Зачем нужен versionCode, если есть versionName?

versionCode — целое число, которое система сравнивает для определения «новее/старее». versionName — строка для человека. Вы можете выпустить versionName «1.0.1» с versionCode 5, если между релизами были внутренние билды. Главное — монотонное возрастание versionCode.

Почему Android требует android:exported явно, а iOS — нет?

В Android компоненты (Activity, Service, Receiver, Provider) по умолчанию были экспортированы до API 31, что создавало дыры в безопасности. Google зафиксировал безопасный дефолт: «явно скажи, публичный это компонент или нет». В iOS компоненты не декларируются в Info.plist — доступность управляется кодом, Entitlements и App Sandbox.

Нужен ли манифест для кроссплатформенных фреймворков (Flutter, React Native, Kotlin Multiplatform)?

Да. Фреймворки генерируют нативные проекты (android/app/src/main/AndroidManifest.xml, ios/Runner/Info.plist) при первой сборке. Вы правите их или конфигурируете через плагины (flutter_config, react-native-config, build.gradle / xcconfig). Игнорировать нативные манифесты нельзя — магазины проверяют именно их.

Что такое Trusted Web Activity (TWA) и как он связан с манифестом?

TWA — способ упаковать PWA в APK/AAB для Google Play. Android-обёртка минимальна: манифест содержит только Launcher-Activity с android:name=»com.google.androidbrowserhelper.trusted.LauncherActivity», с URL манифеста PWA и assetlinks.json для верификации домена. Веб-часть полностью работает в Chrome Custom Tab без адресной строки.

Как проверить манифест на устройстве пользователя без доступа к исходникам?

Android: adb shell dumpsys package com.example.app → раздел «Package», «Permissions», «Activities». iOS: в macOS Console.app или через Xcode Devices → Download Container → просмотр Info.plist в .app. Web: DevTools → Application → Manifest.

Резюме: следующий шаг

Манифест — это не бюрократия, а исполняемый контракт. Начните с аудита текущего файла: откройте его, пройдитесь по чек-листу выше, устраните найденные проблемы. Если вы только создаёте проект — сгенерируйте минимальный валидный манифест через официальные шаблоны (Android Studio New Project, Xcode App Template, PWA Builder, kubectl create deployment —dry-run=client -o yaml), а затем добавляйте поля только по мере появления реальной необходимости. Каждое добавленное разрешение, экспортируемый компонент или сетевое исключение — это поверхность атаки и точка отказа. Держите манифест минимальным, версионируйте его в Git вместе с кодом, и он перестанет быть источником неожиданных сюрпризов на этапе релиза.

Материал носит информационный характер. Требования магазинов приложений (Google Play, App Store, Microsoft Store) и платформ (Android, iOS, Windows, Kubernetes) меняются регулярно. Перед релизом всегда проверяйте актуальную документацию и политики соответствующих консолей разработчика. Для приложений в регулируемых сферах (финтех, медицина, госсектор) обязательно согласовывайте манифест с профильными специалистами по безопасности и комплаенсу.

PEFile.ru