Программирование с ИИ
ENRU
12.2

Android и iOS

версии, подписи, разрешения, идентификатор

Что это

У мобильного приложения, кроме кода, есть паспорт: кто его выпустил, какая это версия, что ему разрешено делать и как он называется для системы. Эти четыре вещи живут не в коде, а в настройках платформенных папок — и именно из-за них сборка, которая прекрасно запускалась на твоём телефоне, не принимается магазином.

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

Как выглядит в коде

1. Версия — это два разных числа

version: 1.2.0+34

Одна строка в pubspec.yaml, а при сборке из неё получается два значения:

ЧастьAndroidiOSКто её видит
1.2.0versionNameVersionпользователь в магазине
34versionCodeBuildтолько магазин

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

Это самая частая и самая глупая потеря времени при публикации: сборка идёт двадцать минут, а отказ приходит из-за числа, которое забыли увеличить на единицу.

2. Идентификатор — навсегда

измерено
Android:  com.lunario.pogoda      (applicationId)
iOS:      com.lunario.pogoda      (bundle identifier)

Это внутреннее имя приложения в системе и в магазине. Правило одно и оно жёсткое: после первой публикации его сменить нельзя. Можно только выпустить другое приложение и просить пользователей переустановить — с потерей всех отзывов, оценок и установок.

Шаблоны проектов подставляют сюда com.example.<имя>. Опубликовать с com.example не получится: магазины такие идентификаторы не принимают. Менять надо до первой публикации, и лучше — в первый день.

3. Разрешения объявляются в двух местах по-разному

Android — список в манифесте:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>

iOS — не список, а объяснения для пользователя:

<key>NSLocationWhenInUseUsageDescription</key>
<string>Нужно, чтобы показать погоду в вашем городе.</string>

Разница принципиальная. На Android ты объявляешь, что приложению нужно. На iOS ты обязан написать, зачем — текстом, который пользователь увидит в системном окне. Нет текста — приложение не пройдёт проверку, а на устройстве упадёт в момент запроса.

И ещё одно, что часто понимают неправильно: объявление в манифесте — это не разрешение. Разрешение даёт пользователь, во время работы приложения, и может отказать (статья 11.5). Объявление лишь даёт право спросить.

4. Подпись

Артефакт, который уходит в магазин, подписан криптографическим ключом. Подпись отвечает на один вопрос: это обновление того же приложения или другого?

ПлатформаЧем подписываютГде хранится
Androidключ в файле-хранилище (keystore)у тебя, не в репозитории
iOSсертификат разработчика и профильв учётной записи Apple

Про Android-ключ надо знать одну вещь, и она неприятная: потерял ключ — не можешь выпустить обновление. Никогда. Приложение в магазине остаётся, а обновить его нельзя — только публиковать заново под новым идентификатором. Сервис подписи от магазина частично спасает ситуацию, но включать его надо заранее, до первой публикации.

Отсюда два правила:

  • Ключ и пароли к нему — не в репозиторий. Файл хранилища, пароли, пути к ним выносятся в файл, который в .gitignore. Это ровно тот же разговор, что про .env в статье 5.7, просто ставка выше.
  • Резервная копия ключа — в двух местах, и ни одно из них не твой ноутбук.

Отладочная подпись, которой инструменты подписывают сборки при разработке, для магазина не годится. Признак проблемы: артефакт называется app-debug.apk или в логе сборки видно signingConfig debug.

Что ещё отрежет пользователей

измерено
minSdk 26      ← ниже этой версии Android приложение не установится

Минимальная версия системы — тихое решение с громкими последствиями. Подняли, чтобы заработала библиотека, — отрезали часть пользователей. Это нормальный обмен, но он должен быть осознанным: ИИ поднимает минимальную версию мимоходом, одной строкой в настройках, и в объяснении об этом не пишет.

Как сказать ИИ

Ключевой приём для этой статьи — требовать объяснения последствий, а не правок. Настройки платформы меняются редко и стоят дорого.

Запрос
Предложи, что изменить, чтобы заработала эта библиотека.
Для каждой правки в android/ и ios/ отдельно напиши,
что она меняет для пользователя: минимальная версия
системы, новые разрешения, размер приложения.
Правки, затрагивающие minSdk, помечай явно.
Запрос
Вот список разрешений моего приложения: <список>.
Приложение делает только <описание>.
Какие из разрешений лишние? Для каждого нужного напиши
текст объяснения для iOS — по-русски, одно предложение.

Второй запрос решает сразу две задачи: убирает лишние разрешения, из-за которых отказывают в публикации, и пишет те самые тексты объяснений, которые забывают.

Запрос
Я готовлю обновление. Что надо поднять в версии
и где именно это записано в проекте?
Покажи строку до и после.
Запрос
Проверь, не попали ли в репозиторий файлы подписи
и пароли: ключи, хранилища, профили, файлы свойств.
Список найденного и строки для .gitignore.

На что смотреть

Разрешения «на всякий случай». В приложении со списком городов появились камера и контакты. ИИ добавляет разрешения, когда библиотека теоретически умеет ими пользоваться. Магазины за это отказывают, а пользователи — удаляют.

Нет текста объяснения для iOS. Разрешение объявлено, объяснения нет: отказ при проверке.

Версия не поднята. Загрузка отклонена, двадцать минут сборки впустую.

Идентификатор остался com.example. Шаблон не правили.

Отладочная подпись. app-debug.apk вместо подписанного артефакта.

Файлы подписи в репозитории. Хранилище ключа, пароли, профили — всё это попадает в историю git, а оттуда уже не удаляется просто так.

minSdk поднят без объяснения. Одна строка, и часть пользователей больше не может установить приложение.

Разрешение объявлено, но отказ не обработан. Самая частая ошибка в коде на эту тему — та же, что в статье 11.5.

Шпаргалка

  • 1.2.0+34: первое для людей, второе для магазина и обязано расти.

  • Идентификатор приложения после публикации не меняется — решай сразу.

  • Android объявляет разрешения, iOS требует объяснить зачем — текстом.

  • Объявление в манифесте ≠ разрешение: его даёт пользователь и может отказать.

  • Потерял ключ подписи — обновления не будет. Копия в двух местах.

  • Ключи и пароли — в .gitignore, а не в репозиторий.

  • minSdk — это решение о том, кто не сможет поставить приложение.

  • Проси у ИИ не правку настроек, а правку с ценой для пользователя.