Використовуйте різні GoogleService-Info.plist для різних схем збірки


110

Я використовую схему збірки для prod і одну для постановки (з двома різними ідентифікаторами пакету) і намагаюся використовувати окремий GoogleService-Info.plist для кожної схеми. Чи є спосіб вручну вибрати пліст-файл, який буде використовуватися при ініціалізації GCM (і входу в goole)? Або можливо уникнути використання плістера та зробити налаштування вручну?

Дякую!


3
Ви використовуєте дві різні цілі? Потім у різних ресурсах Copy Bundle (у фазах збірки) є різні файли (з однаковою назвою).
Олександр Зімін

6
Ця стаття була корисною для мене medium.com/rocket-fuel/… .
Євгеній

Для мене прекрасно працював stackoverflow.com/a/58709334/11537677
лицар-винищувач

Відповіді:


142

Деталі

Тестовано на:

  • Xcode 9.2
  • Xcode 10.2 (10E125)
  • Xcode 11.0 (11A420a)

Рішення

  1. Створіть папку з усіма файлами Google.plist (з різними назвами) у проекті

введіть тут опис зображення

  1. Додати сценарій запуску

введіть тут опис зображення

Не забудьте змінити значення PATH_TO_GOOGLE_PLISTS

Код

PATH_TO_GOOGLE_PLISTS="${PROJECT_DIR}/SM2/Application/Firebase"

case "${CONFIGURATION}" in

   "Debug_Staging" | "AdHoc_Staging" )
        cp -r "$PATH_TO_GOOGLE_PLISTS/GoogleService-Info-dev.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;

   "Debug_Poduction" | "AdHoc_Poduction" | "Distribution" | "Test_Poduction" )
        cp -r "$PATH_TO_GOOGLE_PLISTS/GoogleService-Info-prod.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;

    *)
        ;;
esac

Побудувати імена схем

введіть тут опис зображення


2
Врятуй мій день чудовою відповіддю
Siddh

1
Це правильна відповідь. Мабуть, Firebase Analytics вимагає, щоб файл кореневища в кореневому каталозі вашого додатка, навіть якщо ви телефонували configure(options:). github.com/firebase/quickstart-ios/isissue/5
Роб Байорек

2
Це дуже приємне рішення, і його слід сприймати як відповідь.
Люк Брендон Фаррелл

1
Дуже легкий і розумний, чудова відповідь. Дякую!
габучан

1
@smileВи можете пропустити -rбільше інформації: команда cp в Linux / Unix
Василь Боднарчук

74

Відповідь @inidona працювала на мене. Після того як я перетворив його на Swift

для Swift 2.3:

let filePath = NSBundle.mainBundle().pathForResource("GoogleService-Info", ofType: "plist")
let options = FIROptions(contentsOfFile: filePath)
FIRApp.configureWithOptions(options)

для Swift 3.0:

let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")!
let options = FIROptions(contentsOfFile: filePath)
FIRApp.configure(with: options)

для Swift 4.0:

let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")!
let options = FirebaseOptions(contentsOfFile: filePath)
FirebaseApp.configure(options: options!)

1
Маючи вказаний вище код, чи є у вас два різних файли GoogleService-Info.plistфайлів у різних місцях чи можуть два файли з різними іменами. Надайте, будь ласка, додаткову інформацію про фактичні назви файлів та де вони розміщуються?
Варун Гупта

1
У мене є 2 файли з іменем GoogleService-Info-dev.plist GoogleService-Info-live.plist Цей код дозволяє повідомити ур додатку, який інформаційний файл, з яким ви хочете працювати, замість GoogleService-Info-dev.plist використовуйте умовний вислів або цільові прапори для чергування ваших файлів
Essam Elmasry

yup, в AppDelegate
Elmasry

1
дає мені "Не вдалося знайти файл конфігурації:" GoogleService-Info.plist "'
orium

В останньому документі сказано: "Увага! Цей підхід може вплинути на колекцію Analytics за певних обставин" firebase.google.com/docs/projects/multiprojects
Shingo Fukuyama

30

Перегляньте цю статтю: https://medium.com/@brunolemos/how-to-setup-a-different-firebase-project-for-debug-and-release-environments-157b40512164

На Xcode створіть два каталоги всередині вашого проекту: Debugі Release. Покладіть GoogleService-Info.plistтуди кожен файл.

Увімкніть AppDelegate.m, всередині didFinishLaunchingWithOptionsметоду, поставте код:

Ціль-С

  NSString *filePath;
#ifdef DEBUG
  NSLog(@"[FIREBASE] Development mode.");
  filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist" inDirectory:@"Debug"];
#else
  NSLog(@"[FIREBASE] Production mode.");
  filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist" inDirectory:@"Release"];
#endif

  FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
  [FIRApp configureWithOptions:options];

Швидкий 4

var filePath:String!
#if DEBUG
    print("[FIREBASE] Development mode.")
    filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist", inDirectory: "Debug")
#else
    print("[FIREBASE] Production mode.")
    filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist", inDirectory: "Release")
#endif

let options = FirebaseOptions.init(contentsOfFile: filePath)!
FirebaseApp.configure(options: options)

Перетягніть Debugі Releaseпапки, і папки Build Phases > Copy Bundle Resources:

Фази збирання> Скопіюйте ресурси групи

Це воно :)


1
Це працювало для мене. Ви повинні додати ці папки туди в якості посилань, інакше вони справді вийдуть з ладу. Дякую!
Ейронея

Це рішення все ще не вирішує проблему для Analyticsфреймворку, ви не можете сказати, що .plistзавантажується.
Життєздатний

@Bruno Lemos, Чи можу я використовувати два проекти Firebase з одного проекту xcode одночасно? Не як Debug& Release? Тому що, коли я намагаюся це зробити, я завжди закінчуюсь, already configured crash.я дотримувався останньої інструкції з офіційного документа Firebase. Спасибі
Тулон

24

Я думаю, ви можете використовувати цей спосіб, щоб динамічно налаштувати GoogleService-Info.plist і використовувати різні назви для різних ідентифікаторів пакетів.

ciao Andreas

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];

5
Маючи вказаний вище код, чи є у вас два різних файли файлів GoogleService-Info.plist в різних місцях чи два файли з різними іменами. Надайте, будь ласка, додаткову інформацію про фактичні назви файлів та де вони розміщуються?
Варун Гупта

4
Я отримую цю помилку в журналі під час виклику configureWithOptions:Could not locate configuration file: 'GoogleService-Info.plist'
Бабкен Варданян

14

Я помітив, що Google очікує, що ім'я файлу буде GoogleServiceInfo.plist у коді:

 * The method |configureWithError:| will read from the file GoogleServices-Info.plist bundled with
 * your app target for the keys to configure each individual API. To generate your
 * GoogleServices-Info.plist, please go to https://developers.google.com/mobile/add
 *
 * @see GGLContext (Analytics)
 * @see GGLContext (SignIn)
 */
@interface GGLContext : NSObject

ключова фраза ця

читати з файлу GoogleServices-Info.plist у комплекті з цільою програми

Тому я просто скопіював один і той самий файл і помістив його в різні каталоги та прив’язав його до різних цілей:

введіть тут опис зображення


Дякую, дуже просте і дуже добре працює для мене, Xcode 10.1, FirebaseCore (5.3.1)
infinity_coding7

Як уникнути помилки "Кілька команд виробляти", яка виникає після декількох Plist або інших файлів у додатку
Wahab Khan

11

Якщо GoogleService-Info.plistназва має інше ім'я, це вплине на результати аналізу. Firebase попередить вас про це. https://github.com/firebase/firebase-ios-sdk/isissue/230#issuecomment-327138180 . З цієї причини жодне з цих рішень часу не забезпечить найкращих результатів аналітики.

Є два рішення, які не заплутуються в Analytics.

  1. Використовуйте іншу ціль для кожної схеми та асоціюйте кожну версію GoogleService-Info.plistіз власною ціллю. Див. Цільове членство у інспекторі файлів праворуч у Xcode. Для отримання додаткової інформації див. Це питання .

  2. Використання фази збірки сценарію , щоб скопіювати правильну версію з GoogleService-Info.plistв каталог збірки. Я використовую інший ідентифікатор пакета для постановки та виготовлення. Це дозволяє мені паралельно встановити обидві версії програми. Це також означає, що в нижченаведеному сценарії я можу назвати свої різні GoogleService-Info.plistфайли з ідентифікатором пакету. Наприклад:

    • GoogleService-Info-com.example.app.plist
    • GoogleService-Info-com.example.app.staging.plist

Побудувати фазовий сценарій

PATH_TO_CONFIG=$SRCROOT/Config/GoogleService-Info-$PRODUCT_BUNDLE_IDENTIFIER.plist
FILENAME_IN_BUNDLE=GoogleService-Info.plist
BUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
echo cp $PATH_TO_CONFIG "$BUILD_APP_DIR/$FILENAME_IN_BUNDLE"
cp $PATH_TO_CONFIG "$BUILD_APP_DIR/$FILENAME_IN_BUNDLE"

Примітка: Вам доведеться змінити, PATH_TO_CONFIGщоб відповідати вашим налаштуванням.

Побудувати фазовий сценарій


Це найкраще рішення поки що. Оскільки Firebase Crashlytics може використовувати лише файл GoogleService-Info.plist для завантаження файлів dSYM за допомогою сценарію "upload-символів" - це рішення працює чудово!
Олексій Галішніков

7

Пізно, але я думаю, що я повинен опублікувати цю відповідь, щоб допомогти новим розробникам. Я знайшов дуже гарну статтю, яка переосмислила мою проблему, і я обіцяю, що вона може вам допомогти :)
Перевірте цю статтю, яка також вирішить вашу проблему.

Крок 1.
Скопіюйте GoogleService-Info.plist, що відповідає вашому середовищу розробки Firebase, у каталог Dev . Аналогічно скопіюйте GoogleService-Info.plist, що відповідає виробничому середовищу Firebase, у каталог Prod . Зніміть прапорець "Копіювати елементи, якщо потрібно" та всі цілі в розділі "Додати до цілей" .

(Посилання на зображення кроку 1 (я не можу додати зображення через меншу репутацію))

Крок 2.
У навігаторі проектів Xcode виберіть ціль програми. Перейдіть на вкладку Фази збірки у верхній частині, а потім додайте новий етап сценарію запуску . Назвіть фазу «Налаштування Firebase Environment GoogleService-Info.plist» або щось для цього і поставте її перед кроком «Копіювати ресурси ресурсу» .

Крок 3:
Реалізуйте скрипт оболонки, який скопіює відповідний GoogleService-Info.plist у пакет програм на основі конфігурації збірки. Скопіюйте та вставте наступний скрипт оболонки у створений вами сценарій запуску:

# Name of the resource we're selectively copying
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist

# Get references to dev and prod versions of the GoogleService-Info.plist
# NOTE: These should only live on the file system and should NOT be part of the target (since we'll be adding them to the target manually)
GOOGLESERVICE_INFO_DEV=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Dev/${GOOGLESERVICE_INFO_PLIST}
GOOGLESERVICE_INFO_PROD=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Prod/${GOOGLESERVICE_INFO_PLIST}

# Make sure the dev version of GoogleService-Info.plist exists
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_DEV}"
if [ ! -f $GOOGLESERVICE_INFO_DEV ]
then
    echo "No Development GoogleService-Info.plist found. Please ensure it's in the proper directory."
    exit 1
fi

# Make sure the prod version of GoogleService-Info.plist exists
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_PROD}"
if [ ! -f $GOOGLESERVICE_INFO_PROD ]
then
    echo "No Production GoogleService-Info.plist found. Please ensure it's in the proper directory."
    exit 1
fi

# Get a reference to the destination location for the GoogleService-Info.plist
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
echo "Will copy ${GOOGLESERVICE_INFO_PLIST} to final destination: ${PLIST_DESTINATION}"

# Copy over the prod GoogleService-Info.plist for Release builds
if [ "${CONFIGURATION}" == "Release" ]
then
    echo "Using ${GOOGLESERVICE_INFO_PROD}"
    cp "${GOOGLESERVICE_INFO_PROD}" "${PLIST_DESTINATION}"
else
    echo "Using ${GOOGLESERVICE_INFO_DEV}"
    cp "${GOOGLESERVICE_INFO_DEV}" "${PLIST_DESTINATION}"
fi

6

Ви не можете уникнути використання списку з Firebase. Найкращим рішенням, яке я знайшов поки що для вас, було б додати обидва файли та назвати його

GoogleService-Info_stage.plist

і

GoogleService-Info_prod.plist

Тоді зі свого коду можна зателефонувати у правильний файл. Це не призведе до збою вашої програми, якщо у вас немає файлу. Просто замініть FILENAME на GoogleService-Info_prod або GoogleService-Info_stage.

if let configFile = Bundle.main.path(forResource: "FILENAME", ofType: "plist"), 
    let options = FirebaseOptions(contentsOfFile: configFile)   
{
   FirebaseApp.configure(options: options)
}

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

3

Ця відповідь дуже натхненна відповіддю @abbood , але трохи конкретніше, як це зробити.

Для кожної з ваших цілей, наприклад, dev, stg, prod:

  • Завантажте відповідну GoogleService-Info.plistокрему папку, названу за вашою ціллю
  • У Xcode клацніть правою кнопкою миші папку програми та виберіть Add files to "your app" введіть тут опис зображення
  • Виберіть папку , що містить Таргет GoogleService-Info.plist, переконайтеся , Copy items if neededі Create groupsобрані, тільки перевірити відповідну мету в списку цілей, і натиснітьAdd введіть тут опис зображення

Це воно. Тепер у вас повинно бути щось подібне до цієї структури

введіть тут опис зображення

Коли ви будуєте ціль, GoogleService-Info.plistбуде використано правильне .


Для мене прекрасно працювали.
Şafak Gezer

2

Ось як це зробити в Xamarin C #:

string plistPath = NSBundle.MainBundle.PathForResource ("GoogleService-Info", "plist");
Options options = new Options (plistPath);
App.Configure (options);

Не забудьте включити простір імен Firebase:

using Firebase.Analytics;

2

Це моє рішення!

NSString *filePath;
if([self isProduction]){
    filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
}else{
    filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info-Sandbox" ofType:@"plist"];
}
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];

І це все!


1

Я думаю, що цього неможливо досягти без використання програми " GoogleService-Info.plist.Тому що перед тим, як почати інтегрувати додаток iOS з компонентами входу в Google", ви повинні завантажити залежності та налаштувати проект Xcode. І цей процес показує, що на GoogleService-Info.plistце є великий фактор.

Тож рішення та ідеї, наведені в цьому питанні, можуть допомогти вам у вирішенні вашої проблеми Щойно перемістив основну копію програми GoogleService-Info plistз додатка у дві окремі папки, потім використав "Фази збирання файлів" на етапі збирання для імпорту цільового списку в папку "Ресурси".

Також перевірте це питання , тому воно може дати вам більше інформації / ідеї щодо вашої проблеми.


Тут чи означає ціль іншу схему для одного проекту? Прочитавши питання, я зрозумів, що ціль означає зовсім іншу ціль побудови, а не просто іншу схему побудови для однієї і тієї ж цілі.
Варун Гупта

1
Але що робити, якщо у вас є одна ціль з різною конфігурацією для кожної схеми?
evya

1

З Xcode 9.2 мені потрібні файли для обох цілей з назвою "googleServiceInfo.plist", але розміщені в різних каталогах, з каталогом / файлом для кожної цілі, вказаною в "Фази збірки", "Копіювати ресурси ресурсу".

Вищезгадане не було моїм кращим рішенням, але я раніше намагався використовувати різні назви файлів відповідно до відповіді @ inidona, перетвореної на Swift 4:

 let filePath = Bundle.main.path(forResource: "googleServiceInfo-Pro", ofType: "plist")!
 let options = FirebaseOptions(contentsOfFile: filePath)
 FirebaseApp.configure(options: options!)

На жаль, це не виправило повідомлення про помилки Firebase. У цьому питанні: Firebase iOS SDK - Використання файлу конфігурації, відмінного від GoogleService-Info.plist, генерує консольне попередження, що оригінальний плакат, здається, виправлений оновленням Podbase Firebase, але я цього не підтвердив.


1

Я вирішив це цим:

    #if STAGING
        if let filePath = Bundle.main.path(forResource: "GoogleService-Info-Dev", ofType: "plist"),
            let options = FirebaseOptions(contentsOfFile: filePath) {
                FirebaseApp.configure(options: options)
        } else {
            fatalError("GoogleService-Info-Dev.plist is missing!")
        }
    #else
        if let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist"),
            let options = FirebaseOptions(contentsOfFile: filePath) {
                FirebaseApp.configure(options: options)
        } else {
            fatalError("GoogleService-Info.plist is missing!")
        }
    #endif

1

Якщо хтось із вас потрапляє в помилку, Xcode скаржиться

"Кілька команд створюють GoogleService-Info.plist"

після застосування @Knight Fighter відповіді ви можете:

  • Перевірте фази збірки> Скопіюйте ресурси ресурсу
  • Фільтр для файлів з назвою GoogleService-Info.plist
  • Видаліть всі посилання, які у вас є, оскільки вони вже копіюються через сценарій.

0

Тому я замислювався над тим же питанням і використовуючи деякі ідеї з попередніх публікацій, деякі з яких публікують додатки GoogleServices-Info.plistдля всіх середовищ у всіх додатках, і це викликає непокору.

Я придумав розширюване рішення, яке копіює GoogleSerives-Info.plistфайл під час збирання. Більше того, цей підхід може підтримувати стільки середовищ, скільки вам подобається, завдяки можливості налаштувати та дотримуватися простої конвенції, полегшуючи управління.

По-перше, у мене є три середовища: debug(Для запуску в тренажері та пристрої, що відладжують налагодження і активне скорочення коду), staging(для розгортання для тестового польоту) і releaseдля виробництва.

Першим кроком є ​​створення конфігурацій:

введіть тут опис зображення

Виберіть "Продукт" -> "Схема" -> "Редагувати схему" та дублюйте / створюйте нове, як потрібно. Пройдіть кожну схему та призначте її відповідну конфігурацію зі спадного меню "Конфігурація побудови" у кожній із категорій:

введіть тут опис зображення

Я йду на крок далі і знімаю прапорець "запустити" для схем, які потрібно розподілити, тобто випустити та інсценізувати, і навпаки зніміть прапорець "архів" для налагодження. Ви повинні робити те, що для вас має сенс.

введіть тут опис зображення

Під фази збірки додайте наступний сценарій запуску ( CONFIGURATIONS_FOLDERзмінна може бути налаштована за бажанням - просто переконайтеся, що ви використовуєте те саме ім’я папки на наступному кроці):

# Get a reference to the folder which contains the configuration subfolders.
CONFIGURATIONS_FOLDER=Firebase
# Get a refernce to the filename of a 'GoogleService-Info.plist' file.
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
# Get a reference to the 'GoogleService-Info.plist' for the current configuration.
GOOGLESERVICE_INFO_PLIST_LOCATION=${PROJECT_DIR}/${TARGET_NAME}/${CONFIGURATIONS_FOLDER}/${CONFIGURATION}/${GOOGLESERVICE_INFO_PLIST}
# Check if 'GoogleService-Info.plist' file for current configuration exist.
if [ ! -f $GOOGLESERVICE_INFO_PLIST_LOCATION ]
then
  echo "No '${GOOGLESERVICE_INFO_PLIST}' file found for the configuration '${CONFIGURATION}' in the configuration directory '${PROJECT_DIR}/${TARGET_NAME}/${CONFIGURATIONS_FOLDER}/${CONFIGURATION}'."
  exit 1
fi
# Get a reference to the destination location for the GoogleService-Info.plist.
GOOGLESERVICE_INFO_PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
# Copy 'GoogleService-Info.plist' for current configution to destination.
cp "${GOOGLESERVICE_INFO_PLIST_LOCATION}" "${GOOGLESERVICE_INFO_PLIST_DESTINATION}"
echo "Successfully coppied the '${GOOGLESERVICE_INFO_PLIST}' file for the '${CONFIGURATION}' configuration from '${GOOGLESERVICE_INFO_PLIST_LOCATION}' to '${GOOGLESERVICE_INFO_PLIST_DESTINATION}'."

введіть тут опис зображення

У вибраній папці конфігурацій ("Firebase" у наведеному вище прикладі) папки гнізд для кожної конфігурації названі точно так само, як її відповідна конфігурація (залежно від регістру), всередині якої розміщуються відповідні GoogleServices-Info.plistфайли, як-от так:

введіть тут опис зображення

І останнє, але не менш важливе, я також хочу, щоб рівень кореня GoogleServices-Info.plistне був доданий до проекту випадково, тому я додаю наступне до свого .gitignore.

# Ignore project level GoogleService-Info.plist
/[Project Name]/GoogleService-Info.plist
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.