1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/CarGuo-GSYFlutterBook

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Flutter-iOS-Build.md 25 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 10.03.2025 00:06 5767d61

В предыдущей статье «Руководство по пакетированию и отправке на проверку для Android и iOS» были представлены руководства по пакетированию Flutter для Android и iOS, но эта часть в основном затрагивает локальные процессы сборки и выпуска.

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

Конечно, большинство времени можно использовать сторонние службы непрерывной интеграции (CI), однако специализированные службы для Flutter встречаются реже, а самостоятельная установка бесплатна, поэтому данная статья будет посвящена самостоятельному созданию системы независимого пакетирования.

Поскольку команда для пакетирования Android довольно проста, здесь основное внимание уделяется конфигурированию и установке Flutter для iOS, а это действительно больше относится к CI для iOS.

1. Поддержка параметров

Сначала многие параметры конфигурации на iOS записываются в файл Info.plist, так что первым шагом является решение задачи поддержки динамического изменения параметров в Info.plist во время сборки. Это поможет нам настроить различные версии приложения для разных окружений, таких как QA, Release, Dev и т.д.```sh /usr/libexec/PlistBuddy -c "Set CFBundleVersion ${CFBundleVersion}" ./Runner/Info.plist

/usr/libexec/PlistBuddy -c "Print CFBundleVersion" ./Runner/Info.plist


На Mac есть встроенное командное средство `PlistBuddy`, которое удовлетворяет наши требования, как показано выше:

- Через команду `Set` можно динамически настраивать версию, код и ID приложений третьих сторон в `plist`;
- Через команду `Print` можно выводить информацию из `plist`.

После того как поддержка конфигураций `plist` завершена, следующий шаг — настройка информации о разработчике на машине. Самый простой способ — открыть Xcode и войти в аккаунт разработчика, чтобы позволить Xcode автоматически настроить все данные разработки через опцию `Автоматическое управление подписями`.

![image](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image1)

Однако я не рекомендую этот метод, поскольку **машина для сборки может использоваться несколькими проектами, и вход нескольких разработчиков в один общий аккаунт представляет риск, а также усложняет управление сертификатами и профилями**.

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

## Второй этап: ручная конфигурация сертификата

Ручная конфигурация сертификата и мобильного профиля может быть сложной, но она делает сервис более универсальным и позволяет лучше понять процесс сборки приложений для iOS.1. Создайте файл `CertificateSigningRequest.certSigningRequest` с помощью локального ключа, как показано ниже:

![image](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image2)

2. На официальном сайте Apple в разделе [developer](https://developer.apple.com/account/resources/certificates/add) нажмите "Создать сертификат", выберите созданный ранее файл `CertificateSigningRequest.certSigningRequest`, затем скачайте файл сертификата `.cer`.

![image](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image3)

3. Обратите внимание, что этот файл `.cer` нельзя установить напрямую на сервер сборки. Его следует установить на машину, где был создан файл `CertificateSigningRequest.certSigningRequest`. Затем используйте его для экспорта сертификата, чтобы получить зашифрованный файл `p12`, который можно установить на сервер сборки.

![image](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image4)

4. Установите сертификат, переместив файл `p12` на сервер сборки, откройте его, введите пароль, указанный во время создания, и установите его в раздел "Логин" ключей. Теперь вы должны видеть сертификат Apple Distribution с Team ID в вашем хранилище ключей.

5. После установки возможно появление сообщения "сертификат недоверенный". Это может произойти из-за отсутствия сертификата AppleWWDRCA (Apple Worldwide Developer Relations Certification Authority) на вашем устройстве. Вы можете скачать и установить его по следующим адресам:

- <https://developer.apple.com/cn/support/code-signing/>
- <https://developer.apple.com/support/expiration/>## Третий этап: конфигурация профиля

После настройки сертификата переходим к настройке профиля. Для этого воспользуйтесь сайтом Apple Developers в разделе [Profiles](https://developer.apple.com/account/resources/profiles/add).

1. Выберите режим `Distribution` — `App Store` для создания соответствующего типа сборки. Если это тестовый выпуск (QA), обычно выбирается Ad Hoc, то есть режим, требующий привязки файла к уникальному идентификатору устройства (UDID), но не требующий публикации в магазине.

![image](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image5)

2. Выберите необходимый Bundle ID (App ID). ![изображение](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image6)

3. Выберите ранее сгенерированное сертификатное издание "Distribution". Важно выбрать именно это сертификатное издание.

![изображение](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image7)

4. Введите имя профилирования "Provisioning Profile Name", которое будет использоваться в дальнейшем. Если вы используете "Ad Hoc", то на этом этапе можно выбрать уже добавленные устройства по их уникальным идентификаторам (UDID).

5. После завершения конфигурации скачайте файл "mobile provision" и поместите его в директорию `/Users/ваш_аккаунт/Library/MobileDevice/Provisioning Profiles` на машине сборки. Этот файл понадобится вам позднее.> Если вы собираете версию для магазина, выберите "Distribution" — "App Store". Если вы собираете версию для тестирования (QA), выберите "Distribution" — "Ad Hoc". Сертификат "App Store" позволяет загружать приложение только через официальный магазин или TestFlight, а сертификат "Ad Hoc" позволяет загружать приложение через внутреннюю систему распределения (через добавление тестовых устройств по их UDID).## Четвертый раздел: Конфигурирование проекта

После настройки сертификатов и профилирования следует приступить к настройке самого проекта.

Сначала клонируйте проект, который требуется собрать, на машину сборки (это делается только для тестового конфигурирования), затем откройте проект "ios/Runner.xcworkspace". На этом этапе вы заметите, что проект находится в таком состоянии, поскольку нет доступного аккаунта разработчика:

![изображение](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image8)

Затем отключите автоматическое управление подписями ("Automatically manage signing"), после чего выберите профиль, который вы ранее установили. В результате Xcode автоматически найдёт соответствующий сертификат в ключах и покажет правильную конфигурацию сертификата и профиля.

![изображение](http://img.cdn.guoshuyu.cn/20210429_Flutter-iOS-Build/image9)

На этом этапе стоит обратить внимание на то, что проект по умолчанию использует автоматическое управление подписями ("Automatically manage signing") во время локального развития, так как это удобнее. Поэтому нам нужно сделать так, чтобы проект использовал ручное управление подписями и указывал конкретный файл "mobile provision".Поэтому когда вы отключаете "Автоматическое управление подписью" и указываете профиль на машине Xcode, вы фактически изменяете файл "ios/Runner.xcodeproj/project.pbxproj" вашего проекта. Теперь вы можете использовать команду "git diff" для создания файла "patch", который позволит вам применять изменения к вашему проекту после клонирования с помощью команды "git apply".

```sh
git diff > ./release.patch
```Если есть несколько режимов сборки, например, проект собирается с несколькими bundleId и профилями (QA, Release), можно создать несколько файлов `.patch`. 


> ⚠️ Внимание: **на сторонних машинах сборки каждый раз клонируется новый проект, после сборки он удаляется**, что гарантирует независимость и чистоту каждого сборочного процесса. Создание различных файлов `.patch` позволяет указывать различные `mobile provision`, а значит использовать разные сертификаты, включая одинаковый проект с различными `bundle id`.

## 5\. Начало сборки

1. Перед тем как начать сборку, необходимо выполнить команду **`security unlock-keychain -p xxxxx`** для разблокировки ключей, где `xxxxx` — это пароль вашего Mac.

2. Выполните команду `flutter build ios --release` для создания версии приложения для релиза (`App.framework`) и (`Flutter.framework`).

3. Используйте команду `xcodebuild` для компиляции iOS-кода:

```sh
xcodebuild -workspace Runner.xcworkspace -scheme Runner -sdk iphoneos -configuration Release archive -archivePath $PWD/build/Runner.xcarchive

⚠️ Здесь важно отметить, что если во время сборки возникают ошибки связанные с .sh скриптами, такими как "xcode_backend.sh" или embed_and_thin, или PhaseScriptExecution Thin\ Binary /Users/xxxxx/Library/Developer/Xcode/DerivedData/, рекомендуется запустить полный цикл Archive в Xcode на машине сборки. При первом запуске могут появиться запросы на авторизацию выполнения некоторых шаблонов, введите пароль и завершите процесс, затем повторите вышеупомянутую команду.4. После выполнения команды Archive, следует перейти к этапу export. Перед этим необходимо подготовить файл ExportOptions.plist для указания конфигураций экспорта, пример такого файла может выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>destination</key>
    <string>export</string>
    <key>method</key>
    <string>app-store</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>ваш bundleId</key>
        <string>название provision, которое было определено ранее</string>
    </dict>
    <key>signingCertificate</key>
    <string>Apple Distribution</string>
    <key>signingStyle</key>
    <string>manual</string>
    <key>stripSwiftSymbols</key>
    <true/>
    <key>teamID</key>
    <string>идентификатор вашей разработочной группы</string>
    <key>uploadBitcode</key>
    <false/>
    <key>uploadSymbols</key>
    <false/>
</dict>
</plist>

где

  • если значение method равно store, то пишите app-store; если равно QA, то пишите ad-hoc;
  • в <dict> разделе provisioningProfiles необходимы bundleId и имя, определённое ранее в provision;
  • teamID требует Team ID вашего сертификата разработчика;
  • при использовании store можно добавить конфигурацию uploadBitcode и uploadSymbols; при использовании QA эти параметры могут быть опущены; также для QA можно указать режим thinning;

image

Далее с помощью команды exportArchive и файла конфигурации ExportOptions.plist создаётся архив. Обычно требуется два различных файла ExportOptions.plist: один для QA, другой для Prod. В результате получается .ipa файл.```sh xcodebuild -exportArchive -exportOptionsPlist ExportOptions.plist -archivePath $PWD/build/Runner.xcarchive -exportPath $package_path -allowProvisioningUpdates


Если используется режим `store`, следующий шаг — использовать программу `Transporter` на компьютере Mac для загрузки `.ipa` файла на App Store Connect, либо использовать командную строку для загрузки своего приложения или контента на App Store Connect.

$ xcrun altool --validate-app -f file -t platform -u username [-p password] [--output-format xml] $ xcrun altool --upload-app -f file -t platform -u username [-p password] [--output-format xml]


> Обычно `altool` находится по пути `/Applications/Xcode.app/Contents/Developer/usr/bin/altool`, более подробная информация доступна по адресу https://help.apple.com/asc/appsaltool/

Если используется режим `QA`, вам потребуется подготовить `html` файл, как показано ниже:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Документ</title>
</head>
<body>
<a href=itms-services://?action=download-manifest&url=https://xxxx.xxxx.cn/aaaa/bbbbb/ios/DistributionSummary.plist>Установить</a>
</body>
</html>
```Затем в файле `DistributionSummary.plist` следует указать путь к скачиваемому `.ipa` файлу, что позволит осуществить внутреннюю автономную доставку для тестирования (`QA`).  (*Можно установить только на устройства, для которых были указаны UDID в сертификате `QA`. *)

<plist версия="1.0"> <ключ>элементы</ключ> <массив> <ключ>активы</ключ> <массив> <ключ>вид</ключ> <строка>software-package</строка> <ключ>url</ключ> <строка>https://xxxx.xxxxxx.cn/xxxx/Runner.ipa</строка> <ключ>вид</ключ> <строка>full-size-image</строка> <ключ>необходимо-блестеть</ключ> <истинно/> <ключ>url</ключ> <строка>http://xxxx.xxxxxx.cn/assets/applog/icon.png</строка> <ключ>вид</ключ> <строка>display-image</строка> <ключ>необходимо-блестеть</ключ> <истинно/> <ключ>url</ключ> <строка>http://xxxx.xxxxxx.cn/assets/applog/icon.png</строка> </массив> <ключ>метаданные</ключ> <ключ>идентификатор-пакета</ключ> <строка>com.xxxx.demo</строка> <ключ>версия-пакета</ключ> <строка>1.0.0</строка> <ключ>вид</ключ> <строка>software</строка> <ключ>название</ключ>

                <строка>XXXX App download</строка>
             </dict>
         </dict>
     </массив>
 </dict>
 </plist>
 ```
## Раздел шесть. Окружение с несколькими версиями FlutterЕсли требуется наличие нескольких проектов, собираемых на одной машине, но с различными версиями Flutter и других компонентов, то **для macOS можно создать несколько разных профилей входа**, что позволит получить различные окружения сборки. Важно обратить внимание на версию CocoaPods, так как:

- Версия Flutter 1.22 использует по умолчанию версию CocoaPods 1.8.0; использование версии 1.10.0 может привести к ошибкам в логотипах и других проблемах;

- Для Flutter 2.0 требуется версия CocoaPods 1.10.0.

По умолчанию **CocoaPods устанавливается в директорию `/usr/local/bin` на macOS**, которая является общедоступной для всех профилей. Чтобы решить эту проблему, необходимо установить `rvm` (Ruby Version Manager) в каждом профиле, чтобы управлять отдельными версиями CocoaPods.

Кратко:

- 1. Установите `rvm` через `curl`;

```
curl -L get.rvm.io | bash -s stable && source ~/.rvm/scripts/rvm
```

- 2. Установите нужную версию Ruby с помощью команды `rvm install 2.5.5`, а также просмотрите доступные версии с помощью `rvm list known`;

> Обратите внимание, что команда `rvm install` может завершиться ошибкой из-за необходимости обновления `brew` или проблем со связью;

- 3. Можно установить несколько версий Ruby и использовать конкретную версию с помощью команд `rvm use <Version> --default` или `rvm use <Version>`;

> Без использования ключа `default` следующее запуск командной строки вернётся к ранее установленному значению `default`.- 4. Установите желаемую версию CocoaPods при использовании текущей версии Ruby, чтобы при смене версии Ruby с помощью `rvm use` автоматически менялась и версия CocoaPods.

```sh
sudo gem install cocoapods -v <Version> -n /usr/local/bin
```

На практике после установки `rvm` в различных аккаунтах версии CocoaPods будут разделены между ними.

## Последнее

Разговор был долгим, но автоматическая сборка Xcode действительно удобна. Однако процесс конфигурации помогает понять процессы сборки и сертификации, которые ранее были неизвестны.

Дополнительно, вы можете указывать различные параметры Dart при сборке Android или iOS с помощью команды `--dart-define`.

```sh
flutter build ios --release --dart-define=CHANNEL=GSY --dart-define=LANGUAGE=Dart
```

Параметры могут быть получены в Dart-коде с помощью метода `String.fromEnvironment`.

```
const CHANNEL = String.fromEnvironment('CHANNEL');
const LANGUAGE = String.fromEnvironment('LANGUAGE');
```

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/CarGuo-GSYFlutterBook.git
git@api.gitlife.ru:oschina-mirror/CarGuo-GSYFlutterBook.git
oschina-mirror
CarGuo-GSYFlutterBook
CarGuo-GSYFlutterBook
master