Замена App Center для .NET MAUI: гайд 2026

App Center закрыт с марта 2025. Собираем на .NET MAUI рабочую замену: Firebase App Distribution, TestFlight и Google Play Internal Testing, плюс GitHub Actions пайплайн с подписью iOS и Android.

Замена App Center для .NET MAUI 2026

Обновлено: 8 сентября 2026

Замена App Center для .NET MAUI в 2026 году: связка из трёх сервисов. Firebase App Distribution для кросс-платформенной раздачи бета-сборок, TestFlight для официального бета-тестирования iOS и Google Play Internal Testing для Android. Microsoft окончательно закрыл App Center 31 марта 2025 года, и большинство команд, которые я вижу в консалтинге, до сих пор либо тянут артефакты в общий Slack-канал, либо пытаются собрать «монстра Франкенштейна» из старых CLI-скриптов. Ниже я разберу рабочую связку на 2026 год с полными пайплайнами и подписью.

  • App Center Build, Distribute, Crashes, Analytics и Push были отключены 31 марта 2025 года. CLI и API больше не отвечают, все webhooks мертвы.
  • Оптимальный стек для .NET MAUI в 2026: Firebase App Distribution (раздача внутренним тестерам), TestFlight (внешние iOS-бета), Google Play Internal Testing (Android-бета в проде), Sentry или Firebase Crashlytics (крэши).
  • Firebase App Distribution работает и с APK, и с AAB, и с IPA, до 200 тестеров бесплатно, интегрируется с fastlane и GitHub Actions одной командой.
  • TestFlight требует нотаризации через notarytool (altool закрыт с ноября 2023) и валидного provisioning profile типа App Store distribution.
  • Миграция крэшей: App Center Crashes уходит в Sentry (open-source SDK для MAUI) или Firebase Crashlytics; аналитика переезжает в Firebase Analytics или Application Insights.

Что случилось с App Center и почему нужна замена

Microsoft объявил о закрытии Visual Studio App Center ещё в апреле 2024 года, а 31 марта 2025 года окончательно выключил все сервисы: Build, Distribute, Test, Crashes, Analytics и Push Notifications. Официальное объявление можно прочитать в Microsoft Learn: App Center retirement notice. С этого момента любые CLI-команды appcenter distribute release возвращают 404, ключи API отозваны, а публичные ссылки на дистрибутивы больше не работают.

Большинство команд эту миграцию тянут до последнего, и вот почему это плохо. Без работающего канала раздачи бета-сборок QA получают билды через AirDrop или Telegram, что убивает воспроизводимость и историю версий. Я в трёх проектах разгребал последствия, и в двух случаях команда потеряла двухнедельный трек регрессий, потому что не могла сопоставить, кто какую сборку тестировал. Держите открытыми в фоне официальный гайд Firebase App Distribution и документацию TestFlight: это базовые ссылки, пока настраиваешь замену.

Отдельно про push-уведомления и Notification Hub. App Center Push был отключён ещё в 2020 году, поэтому если ваш MAUI-проект до сих пор его дёргает, это уже мёртвый код, удаляйте. Актуальная замена сейчас: Firebase Cloud Messaging напрямую или Azure Notification Hubs с прямыми регистрациями.

Сравнение альтернатив App Center для .NET MAUI

Прежде чем ставить конкретный сервис, полезно увидеть картину целиком. Ни одна платформа не покрывает всё, что делал App Center, поэтому в 2026 году правильная стратегия такая: комбинировать сервисы, а не искать «серебряную пулю». Ниже сравнение, которое я использую при первом разговоре с командой, оценивающей миграцию.

ВозможностьFirebase App DistributionTestFlightGoogle Play Internal TestingCodemagic Distribute
ПлатформыiOS + AndroidiOS толькоAndroid толькоiOS + Android
Формат артефактаAPK, AAB, IPAIPA (подписан App Store)APK, AABAPK, AAB, IPA
Макс. тестеровБез лимита10 000 внешних100 на трекПо плану
Обзор Apple/GoogleНе требуетсяТребуется для внешнихНе требуетсяНе требуется
СтоимостьБесплатноБесплатно (в рамках Apple Developer $99/год)Бесплатно (в рамках Google Play $25 разово)От $28/мес
CLI / автоматизацияfirebase CLI, fastlane pilot альтернативаfastlane pilot, notarytoolfastlane supply, Google Play APICodemagic YAML
Скорость публикацииСекунды10–40 минут processingМинутыСекунды
Обратная связь тестеровЧерез email/ссылкуВстроенный feedback + скриншотыЧерез Play StoreЧерез email

Практический вывод такой. Firebase App Distribution — рабочая лошадка для внутренней раздачи (быстро, бесплатно, кросс-платформенно), TestFlight обязателен для сколько-нибудь серьёзного iOS-бета-цикла (там реальные пользователи со скриншот-фидбеком), а Google Play Internal Testing удобен как «предпродакшн» для Android, потому что там уже подписанные Play Store артефакты, идентичные тому, что уйдёт в релиз.

Firebase App Distribution для .NET MAUI: пошаговая настройка

Начну с Firebase App Distribution, потому что это самый прямой путь от App Center. У него похожие концепции (группы тестеров, релизы, notes), и мигрируется он за один день. Большинство команд пропускают шаг с сервисным аккаунтом, а потом две недели дебажат, почему в CI при загрузке падает 401. Проверьте по чеклисту ниже.

Шаг 1. Создание Firebase проекта и приложений

  1. Заведите проект на console.firebase.google.com (либо используйте существующий, если Analytics или FCM уже там).
  2. Добавьте два приложения: iOS (Bundle ID вашего Info.plist) и Android (Package name из AndroidManifest.xml).
  3. Скачайте google-services.json и GoogleService-Info.plist. Они нужны только для Firebase SDK (Analytics/Crashlytics). Для App Distribution как такового они не требуются, но пусть лежат в проекте.
  4. В разделе App Distribution включите сервис и создайте группы тестеров, например qa-internal и stakeholders.

Шаг 2. Сервисный аккаунт для CI

Это тот самый шаг, который большинство команд пропускают, и потом у них падает загрузка из GitHub Actions. Нужен именно service account, а не персональный токен:

# В Google Cloud Console → IAM → Service Accounts
# 1. Создайте service account: firebase-app-distribution-ci
# 2. Назначьте роль: Firebase App Distribution Admin
# 3. Скачайте JSON-ключ, сохраните как GOOGLE_APPLICATION_CREDENTIALS.json
# 4. В GitHub Actions добавьте секрет FIREBASE_SERVICE_ACCOUNT со всем содержимым JSON

Шаг 3. Загрузка Android AAB из .NET MAUI

Собираем подписанный AAB и заливаем через Firebase CLI:

# Publish подписанного AAB для Android
dotnet publish -f net9.0-android -c Release \
  -p:AndroidPackageFormat=aab \
  -p:AndroidKeyStore=true \
  -p:AndroidSigningKeyStore=$KEYSTORE_PATH \
  -p:AndroidSigningStorePass=$KEYSTORE_PASS \
  -p:AndroidSigningKeyAlias=$KEY_ALIAS \
  -p:AndroidSigningKeyPass=$KEY_PASS \
  -o ./artifacts/android

# Загрузка через firebase CLI (v13.20+)
firebase appdistribution:distribute \
  ./artifacts/android/*-Signed.aab \
  --app "1:123456789:android:abcdef" \
  --groups "qa-internal,stakeholders" \
  --release-notes-file ./release-notes.md

Шаг 4. Загрузка iOS IPA

Для iOS процесс похож, но требует Ad Hoc или Development provisioning profile. Firebase App Distribution не примет App Store подпись (это ограничение самой Apple), ищите profile с типом PROFILE_TYPE_IOS_APP_ADHOC:

dotnet publish -f net9.0-ios -c Release \
  -p:ArchiveOnBuild=true \
  -p:CodesignKey="Apple Distribution: MyCompany LLC" \
  -p:CodesignProvision="MyApp AdHoc" \
  -p:RuntimeIdentifier=ios-arm64 \
  -o ./artifacts/ios

firebase appdistribution:distribute \
  ./artifacts/ios/*.ipa \
  --app "1:123456789:ios:abcdef" \
  --groups "qa-internal" \
  --release-notes "Sprint 47 build, see JIRA MAUI-1234"

TestFlight для .NET MAUI iOS бета-тестирования

TestFlight в 2026 году это единственный способ дать реальным пользователям (не разработчикам, у которых UDID зарегистрирован) потестировать iOS-приложение до релиза. Это официальный канал Apple, поэтому он поддерживает внешних тестеров (до 10 000 человек), обязательный App Review для внешних групп и встроенный сбор скриншот-фидбека. Если раньше вы полностью полагались на Ad Hoc через App Center, время перестраиваться, потому что TestFlight требует App Store подпись и загрузку через Apple, а не через сторонние сервисы.

Настройка App Store Connect и API ключа

Первое, что стоит сделать даже до начала любой автоматизации, это создать API-ключ в App Store Connect. С 2023 года altool отключён, для загрузки используется xcrun notarytool и fastlane pilot. Полезно свериться с официальной документацией App Store Connect API, чтобы понимать, какие роли и scope доступны:

# App Store Connect → Users and Access → Keys
# Создайте ключ с ролью App Manager, скачайте .p8 файл (только один раз!)
# Запомните Key ID и Issuer ID

# Fastlane setup для CI
bundle init
echo 'gem "fastlane"' >> Gemfile
bundle install

# Fastfile для загрузки в TestFlight
lane :beta do
  api_key = app_store_connect_api_key(
    key_id: ENV["APP_STORE_KEY_ID"],
    issuer_id: ENV["APP_STORE_ISSUER_ID"],
    key_filepath: ENV["APP_STORE_KEY_PATH"],
    duration: 1200
  )

  pilot(
    api_key: api_key,
    ipa: "./artifacts/ios/MyApp.ipa",
    skip_waiting_for_build_processing: true,
    changelog: File.read("./release-notes.md"),
    distribute_external: false,
    groups: ["internal-qa"]
  )
end

Гочи, которые убьют вам полдня

  • Processing зависает на 40+ минут: обычно причина в отсутствии всех required device family icons или в невалидном ITSAppUsesNonExemptEncryption в Info.plist. Добавьте <key>ITSAppUsesNonExemptEncryption</key><false/>, и экспортный compliance закрывается автоматически.
  • Билд не появляется у внешних тестеров: проверьте, что группа помечена как External и прошла Beta App Review (первая версия занимает 24–48 часов, минорные обновления часто идут автоматом).
  • Bundle version conflict: App Store Connect отвергнет билд с уже загруженной комбинацией версии и bundle-версии. Инкрементируйте CFBundleVersion на каждый CI-запуск: -p:ApplicationVersion=$GITHUB_RUN_NUMBER.

Google Play Internal Testing для Android

Внутреннее тестирование в Google Play Console это не то же самое, что «internal app sharing» (последний нужен для быстрого шаринга одного APK на девайс). Internal Testing это полноценный трек внутри Play Console, до 100 email-адресов, публикация за минуты, автоматические обновления через Play Store на устройствах тестеров. Именно этот канал я использую как замену App Center для Android, он проверяет, что подпись, targetSdk и Play Console-политики отработают именно так, как в проде. Спецификации трека расписаны в официальном хелпе Google Play Console по testing tracks.

Первичная настройка Play Console

  1. Создайте приложение в Play Console (если ещё нет). Заполните обязательные секции: контент-рейтинг, целевую аудиторию, политику приватности.
  2. Перейдите в Testing → Internal testing → Create new release.
  3. Загрузите первую сборку вручную, чтобы Play Console принял upload key. Дальше можно автоматизировать через API.
  4. В Setup → API access создайте service account и назначьте роль Release Manager.

Автоматизация через fastlane supply

lane :internal_android do
  upload_to_play_store(
    package_name: "com.mycompany.myapp",
    aab: "./artifacts/android/com.mycompany.myapp-Signed.aab",
    track: "internal",
    release_status: "draft",
    json_key: ENV["GOOGLE_PLAY_JSON_KEY_PATH"],
    skip_upload_metadata: true,
    skip_upload_images: true,
    skip_upload_screenshots: true
  )
end

Автоматизация раздачи через GitHub Actions

Так, теперь к пайплайну. Ниже рабочий GitHub Actions воркфлоу, который собирает MAUI iOS + Android, заливает Android в Firebase App Distribution и в Google Play internal, а iOS уходит в Firebase (для Ad Hoc QA) и в TestFlight. Пайплайн top-down, как я всегда пишу: сначала контекст (триггеры, env), потом job'ы, потом стадии. Если у вас ещё нет базовой сборки, посмотрите отдельный разбор CI/CD для .NET MAUI на GitHub Actions, где расписаны шаги с подписью и провижн-профилями; здесь я не буду повторяться.

name: MAUI Beta Distribution
on:
  push:
    branches: [main, "release/*"]
  workflow_dispatch:

env:
  DOTNET_VERSION: 9.0.x
  BUILD_CONFIGURATION: Release
  ARTIFACTS_PATH: ./artifacts

jobs:
  android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}
      - name: Install MAUI workloads
        run: dotnet workload install maui-android
      - name: Decode keystore
        run: echo "${{ secrets.ANDROID_KEYSTORE_B64 }}" | base64 -d > keystore.jks
      - name: Publish signed AAB
        run: |
          dotnet publish -f net9.0-android -c $BUILD_CONFIGURATION \
            -p:AndroidPackageFormat=aab \
            -p:AndroidKeyStore=true \
            -p:AndroidSigningKeyStore=./keystore.jks \
            -p:AndroidSigningStorePass="${{ secrets.KEYSTORE_PASS }}" \
            -p:AndroidSigningKeyAlias="${{ secrets.KEY_ALIAS }}" \
            -p:AndroidSigningKeyPass="${{ secrets.KEY_PASS }}" \
            -p:ApplicationVersion=${{ github.run_number }} \
            -o $ARTIFACTS_PATH/android
      - name: Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{ secrets.FIREBASE_ANDROID_APP_ID }}
          serviceCredentialsFileContent: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
          groups: qa-internal
          file: ${{ env.ARTIFACTS_PATH }}/android/com.mycompany.myapp-Signed.aab
      - name: Google Play Internal
        uses: r0adkll/upload-google-play@v1
        with:
          serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_JSON_KEY }}
          packageName: com.mycompany.myapp
          releaseFiles: ${{ env.ARTIFACTS_PATH }}/android/com.mycompany.myapp-Signed.aab
          track: internal
          status: draft

  ios:
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}
      - run: dotnet workload install maui-ios
      - name: Import signing certificate
        uses: apple-actions/import-codesign-certs@v3
        with:
          p12-file-base64: ${{ secrets.IOS_DISTRIBUTION_P12 }}
          p12-password: ${{ secrets.IOS_DISTRIBUTION_P12_PASS }}
      - name: Download provisioning profile
        uses: apple-actions/download-provisioning-profiles@v3
        with:
          bundle-id: com.mycompany.myapp
          profile-type: IOS_APP_STORE
          issuer-id: ${{ secrets.APP_STORE_ISSUER_ID }}
          api-key-id: ${{ secrets.APP_STORE_KEY_ID }}
          api-private-key: ${{ secrets.APP_STORE_PRIVATE_KEY }}
      - name: Publish IPA
        run: |
          dotnet publish -f net9.0-ios -c $BUILD_CONFIGURATION \
            -p:ArchiveOnBuild=true \
            -p:CodesignKey="Apple Distribution: MyCompany LLC" \
            -p:CodesignProvision="MyApp AppStore" \
            -p:RuntimeIdentifier=ios-arm64 \
            -p:ApplicationVersion=${{ github.run_number }} \
            -o $ARTIFACTS_PATH/ios
      - name: TestFlight upload
        uses: apple-actions/upload-testflight-build@v3
        with:
          app-path: ${{ env.ARTIFACTS_PATH }}/ios/MyApp.ipa
          issuer-id: ${{ secrets.APP_STORE_ISSUER_ID }}
          api-key-id: ${{ secrets.APP_STORE_KEY_ID }}
          api-private-key: ${{ secrets.APP_STORE_PRIVATE_KEY }}

Такой пайплайн я обычно ставлю на release/*-ветки и workflow_dispatch, чтобы не заваливать TestFlight на каждый push в main. TestFlight processing на второй сборке в час стабильно замедляется, не гоняйте туда каждый коммит.

Что заменит crash reporting и аналитику

App Center Crashes и Analytics были важной частью пакета, и именно эта часть чаще всего забывается при миграции. К моменту, когда вам понадобится расследовать первый крэш в проде на TestFlight, поздно поднимать SDK. Ставьте сразу.

Sentry для .NET MAUI

Sentry — мой первый выбор для крэш-репортинга. SDK нативно поддерживает MAUI начиная с версии 4.0, есть автоматический symbolication для iOS/Android, и работает даже с NativeAOT-сборками (это важно, если вы читали разбор NativeAOT в .NET MAUI и уже включили публикацию). Настройка занимает минут пять:

// В MauiProgram.cs
builder.UseSentry(options =>
{
    options.Dsn = "https://[email protected]/000";
    options.TracesSampleRate = 0.2;
    options.AttachScreenshot = true;
    options.CacheDirectoryPath = FileSystem.CacheDirectory;
});

Firebase Crashlytics

Если вы уже поставили Firebase ради App Distribution, Crashlytics логично включить туда же. Для .NET MAUI используйте Plugin.Firebase.Crashlytics. SDK нужен в оба проекта (iOS + Android), symbol upload идёт через upload-symbols для iOS и firebase-crashlytics-buildtools для Android.

Аналитика

Firebase Analytics это самый безболезненный upgrade path с App Center Analytics: события и user properties мигрируют почти один в один. Альтернатива это Azure Application Insights (если у вас уже есть Azure-инфра), но SDK для MAUI придётся тянуть через community-обёртку, официального нет.

Миграция существующего пайплайна с App Center

Собственно чеклист, который я использую с командами. Идите строго сверху вниз, пункты нельзя переставлять местами, иначе получите период, когда старая раздача уже не работает, а новая ещё не настроена.

  1. Аудит App Center-упоминаний в кодовой базе. Ищите Microsoft.AppCenter, appcenter-cli, вебхуки Slack/Teams с URL appcenter.ms. Всё, что нашли, помечайте на удаление.
  2. Замените SDK пакеты. Удалите Microsoft.AppCenter.Crashes и Microsoft.AppCenter.Analytics из .csproj. Добавьте Sentry.Maui (4.10+) или Firebase-пакеты.
  3. Перенесите тестерские группы. Экспортируйте список email'ов из App Center (если у вас есть бэкап), заведите тех же людей в Firebase App Distribution как группу и в App Store Connect / Play Console как тестеров.
  4. Настройте service accounts. Firebase App Distribution Admin, Google Play Release Manager, App Store Connect API key. Секреты храните в GitHub Actions / Azure Pipelines.
  5. Соберите тестовый билд. Прогоните полный пайплайн на одном пре-релизе, убедитесь, что тестеры получили и iOS, и Android. Только после этого убирайте старый пайплайн.
  6. Обновите документацию для QA. Инструкции «как установить бета-сборку» изменились. Для Firebase App Distribution нужно принять приглашение по email и установить Firebase App Tester (iOS/Android). Для TestFlight ставим приложение TestFlight. Не оставляйте это без объяснения, иначе потеряете два дня на «у меня не приходит ссылка».
  7. Настройте мониторинг: Sentry alerts, Firebase Crashlytics velocity alerts. Первый крэш в TestFlight-беты вы должны увидеть до того, как тестер напишет.

Часто задаваемые вопросы

Что случилось с App Center?

Microsoft закрыл Visual Studio App Center 31 марта 2025 года. Все сервисы (Build, Distribute, Crashes, Analytics, Test) выключены, CLI возвращает 404, API-ключи отозваны. Официальное объявление опубликовано в апреле 2024 года на Microsoft Learn, ретирейтмент дал командам 12 месяцев на миграцию.

Есть ли бесплатная альтернатива App Center для .NET MAUI?

Да. Firebase App Distribution полностью бесплатен для внутренней раздачи, TestFlight входит в подписку Apple Developer ($99/год), Google Play Internal Testing бесплатен после разового платежа $25 за аккаунт Play Console. Sentry имеет бесплатный tier до 5000 крэшей в месяц.

Можно ли автоматизировать загрузку в TestFlight из GitHub Actions?

Да, используя App Store Connect API key и action apple-actions/upload-testflight-build@v3 либо fastlane pilot. Ключ создаётся в App Store Connect → Users and Access → Keys с ролью App Manager. Требуется macOS runner (macos-14) для сборки iOS.

Что использовать вместо App Center Push?

App Center Push был отключён ещё в 2020 году. Актуальные замены на 2026 год: Firebase Cloud Messaging напрямую (кросс-платформенно, бесплатно), Azure Notification Hubs (если у вас Azure-инфра), OneSignal (если нужны сегментация и analytics без бэкенда).

Работает ли Firebase App Distribution с .NET MAUI Blazor Hybrid?

Да. Blazor Hybrid это обычный MAUI-проект с BlazorWebView внутри, артефакт сборки такой же (AAB для Android, IPA для iOS), поэтому Firebase App Distribution принимает его без изменений. Особая настройка не требуется.

Sofia Rodriguez
Об авторе Sofia Rodriguez

Mobile DevOps engineer focused on the unglamorous stuff: build pipelines, signing, store releases, and the tooling that keeps teams shipping.