Use GoogleService-Info.plist diferente para esquemas de compilação diferentes


110

Estou usando um esquema de compilação para prod e um para teste (com 2 identificadores de pacote diferentes) e estou tentando usar um GoogleService-Info.plist separado para cada esquema. Existe alguma maneira de selecionar manualmente o arquivo plist a ser usado ao inicializar o GCM (e o login do goole)? Ou é possível evitar o uso do plist e fazer a configuração manualmente?

Obrigado!


3
Você usa dois alvos diferentes? Em seguida, tenha arquivos diferentes (com o mesmo nome) em diferentes recursos de pacote de cópia (que estão nas fases de construção).
— Alexander Zimin

6
Esse artigo foi útil para mim medium.com/rocket-fuel/… .
— Eugeny

Funcionou perfeitamente para mim stackoverflow.com/a/58709334/11537677
— Knight Fighter

Respostas:


142

Detalhes

Testado em:

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

Solução

  1. Crie uma pasta com todos os seus arquivos Google.plist (com nomes diferentes) no projeto

insira a descrição da imagem aqui

  1. Adicionar script de execução

insira a descrição da imagem aqui

Não se esqueça de alterar o valor de PATH_TO_GOOGLE_PLISTS

Código

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

Nomes de esquemas de construção

insira a descrição da imagem aqui


2
Salve meu dia, ótima resposta
— Siddh de

1
Esta é a resposta certa. Aparentemente, o Firebase Analytics requer esse arquivo plist no diretório raiz do seu aplicativo, mesmo se você chamar configure(options:). github.com/firebase/quickstart-ios/issues/5
— Rob Bajorek

2
Esta é uma solução muito boa e deve ser aceita como resposta.
— Luke Brandon Farrell

1
Muito leve e inteligente, ótima resposta. Obrigado!
— gabuchan

1
@smileBot você pode pular -r, mais informações: comando cp no Linux / Unix
— Vasily Bodnarchuk

73

A resposta de @inidona funcionou para mim. Depois de convertê-lo para Swift

para Swift 2.3:

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

para Swift 3.0:

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

para Swift 4.0:

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

1
Com o código acima, você tem dois arquivos de GoogleService-Info.plistarquivos diferentes em locais diferentes ou pode dois arquivos com nomes diferentes. Você poderia fornecer mais informações sobre quais são os nomes reais dos arquivos e onde eles estão localizados?
— Varun Gupta de

1
Eu tenho 2 arquivos chamados GoogleService-Info-dev.plist GoogleService-Info-live.plist este código permite que você diga ao seu aplicativo com qual arquivo de informações você deseja trabalhar, em vez do padrão GoogleService-Info-dev.plist, use a instrução condicional ou sinalizadores de destino para alternar entre seus arquivos
— Essam Elmasry

sim, no AppDelegate
— Essam Elmasry

1
me dá 'Não foi possível localizar o arquivo de configuração:' GoogleService-Info.plist ''
— orium

Documento recente diz "Aviso: esta abordagem pode impactar a coleta do Analytics em algumas circunstâncias" firebase.google.com/docs/projects/multiprojects
— Shingo Fukuyama

30

Verifique este artigo: https://medium.com/@brunolemos/how-to-setup-a-different-firebase-project-for-debug-and-release-environments-157b40512164

No Xcode, crie dois diretórios dentro do seu projeto: Debuge Release. Coloque cada GoogleService-Info.plistarquivo lá.

Em AppDelegate.m, dentro do didFinishLaunchingWithOptionsmétodo, coloque o código:

Objective-C

  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];

Swift 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)

Arraste e solte as pastas Debuge Releasepara Build Phases > Copy Bundle Resources:

Fases de construção> Copiar recursos de pacote

É isso aí :)


1
Isso funcionou para mim. Você tem que adicionar essas pastas como referência, caso contrário, irá travar, de fato. Obrigado!
— Eironeia

Esta solução ainda não resolve o problema do Analyticsframework, você não pode dizer qual .plistestá sendo carregado.
— Lifely de

@Bruno Lemos, Posso usar dois projetos Firebase de um projeto xcode simultaneamente? Não como Debug& Release? Porque quando tento fazer isso, sempre already configured crash.acabo com Segui as instruções mais recentes do documento oficial do Firebase. Obrigado
— Tulon

24

Acho que você pode usar essa maneira para configurar seu GoogleService-Info.plist de forma dinâmica e usar nomes diferentes para identificadores de pacote diferentes.

ciao andreas

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

5
Com o código acima, você tem dois arquivos diferentes, arquivos GoogleService-Info.plist em locais diferentes ou dois arquivos com nomes diferentes. Você poderia fornecer mais informações sobre quais são os nomes reais dos arquivos e onde eles estão localizados?
— Varun Gupta de

4
Estou recebendo este erro no log durante a chamada configureWithOptions:Could not locate configuration file: 'GoogleService-Info.plist'
— Babken Vardanyan

14

Percebi que o Google espera que o nome do arquivo seja GoogleServiceInfo.plist no código:

 * 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

a frase chave é esta

leia o arquivo GoogleServices-Info.plist fornecido com o destino do seu aplicativo

Então, simplesmente copiei o mesmo arquivo, coloquei-o em diretórios diferentes e limitei-o a destinos diferentes:

insira a descrição da imagem aqui


Obrigado, muito simples e funciona muito bem para mim, Xcode 10.1, FirebaseCore (5.3.1)
— infinity_coding7

Como evitar o erro "Multiple command produc" que ocorre depois de múltiplos arquivos Plist ou outros arquivos no App
— Wahab Khan Jadon

11

Se o GoogleService-Info.plisttiver um nome diferente, ele afetará seus resultados analíticos. O Firebase irá avisá-lo sobre isso. https://github.com/firebase/firebase-ios-sdk/issues/230#issuecomment-327138180 . Por esse motivo, nenhuma dessas soluções de tempo de execução fornecerá os melhores resultados analíticos.

Existem duas soluções que não mexem com o Analytics.

  1. Use um destino diferente com cada esquema e associe cada versão do GoogleService-Info.plistseu próprio destino. Consulte Associação de destino no inspetor de arquivos no lado direito do Xcode. Para mais informações Veja esta questão .

  2. Use um script fase de construção para copiar a versão correta de GoogleService-Info.plistna pasta de compilação. Eu uso um ID de pacote diferente para teste e produção. Isso me permite ter as duas versões do aplicativo instaladas em paralelo. Isso também significa que, com o script abaixo, posso nomear meus diferentes GoogleService-Info.plistarquivos com o ID do pacote. Por exemplo:

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

Script de fase de construção

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"

Nota: você terá que mudar PATH_TO_CONFIGpara se adequar à sua configuração.

Script de fase de construção


Esta é a melhor solução até agora. Como o Firebase Crashlytics só pode usar o arquivo GoogleService-Info.plist para fazer upload de arquivos dSYM usando o script 'upload-symbols' - esta solução funciona perfeitamente!
— Alexey Galishnikov

6

Você não pode evitar o uso do plist com o Firebase. A melhor solução que encontrei até agora para você seria adicionar os dois arquivos e nomeá-los

GoogleService-Info_stage.plist

e

GoogleService-Info_prod.plist

Então, a partir do seu código, você pode chamar o arquivo correto. Dessa forma, seu aplicativo não travará se você não tiver o arquivo. Basta substituir FILENAME por GoogleService-Info_prod ou GoogleService-Info_stage.

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

As configurações de tempo de execução podem levar a problemas de relatórios analíticos, conforme mencionado nos documentos .
— Alex

6

Atrasado mas acho que devo postar essa resposta para ajudar novos desenvolvedores, encontrei um artigo muito bom que resolveu meu problema e prometo que pode te ajudar também :)
Confira este artigo que resolve seu problema também.

Etapa 1:
copie o GoogleService-Info.plist correspondente ao seu ambiente de desenvolvimento Firebase no diretório Dev . Da mesma forma, copie o GoogleService-Info.plist correspondente ao seu ambiente de produção do Firebase no diretório Prod . Certifique-se de desmarcar “Copiar itens se necessário” e todos os alvos em “Adicionar aos alvos” .

(Etapa 1 link da imagem (não consigo adicionar imagem por causa de menos reputações))

Etapa 2:
no navegador de projetos Xcode, selecione o destino do aplicativo. Alterne para a guia Build Phases na parte superior e, em seguida, adicione uma New Run Script Phase . Nomeie a fase “Setup Firebase Environment GoogleService-Info.plist” ou algo parecido e coloque-o antes da etapa “Copy Bundle Resources” .

Etapa 3:
implemente um script de shell que copiará o GoogleService-Info.plist apropriado no pacote de aplicativos com base na configuração de compilação. Copie e cole o seguinte script de shell na fase de execução do script que você acabou de criar:

# 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

3

Essa resposta é muito inspirada na resposta de @abbood , mas um pouco mais específica sobre como fazê-lo.

Para cada um de seus alvos, por exemplo, dev, stg, prod:

  • Baixe o correspondente GoogleService-Info.plistpara uma pasta separada com o nome de seu destino
  • No Xcode, clique com o botão direito na pasta do seu aplicativo e escolha Add files to "your app" insira a descrição da imagem aqui
  • Selecione a pasta que contém o alvo GoogleService-Info.plist, certifique-se Copy items if needede Create groupssão selecionados, verifique apenas o destino correspondente na lista de alvos, e pressioneAdd insira a descrição da imagem aqui

É isso aí. Agora você deve ter algo semelhante a esta estrutura

insira a descrição da imagem aqui

Quando você constrói um alvo, o correto GoogleService-Info.plistserá usado.


Funcionou perfeitamente para mim.
— Şafak Gezer

2

Veja como fazer no Xamarin C #:

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

Lembre-se de incluir o namespace do Firebase:

using Firebase.Analytics;

2

Esta é a minha solução!

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];

E é isso!


1

Acho que não é possível alcançar sem usar o GoogleService-Info.plist.Porque antes de começar a integrar seu aplicativo iOS com os componentes do Google Sign-In, você deve baixar as dependências e configurar seu projeto Xcode. E esse processo mostra que isso GoogleService-Info.plisttem um grande fator.

Portanto, as soluções e ideias aqui nesta questão do SO podem ajudá-lo com seu problema. Apenas mova a cópia principal GoogleService-Info plistdo aplicativo para 2 pastas separadas e, em seguida, use as fases de construção "Copiar arquivos" em cada destino para importar o plist específico de destino para a pasta Recursos.

Verifique também isto questão do SO , ela pode lhe dar mais informações / idéias para o seu problema.


Aqui, alvo significa um esquema diferente para o mesmo projeto? Depois de ler as perguntas, concluí que o destino significa um destino de construção diferente completamente e não apenas um esquema de construção diferente para o mesmo destino.
— Varun Gupta de

1
Mas e se você tiver um destino com uma configuração diferente para cada esquema?
— evya

1

Com o Xcode 9.2, preciso que os arquivos de ambos os destinos sejam nomeados "googleServiceInfo.plist", mas colocados em diretórios diferentes, com o diretório / arquivo para cada destino especificado em "Build Phases", "Copy Bundle Resources".

A solução acima não era minha solução preferida, mas eu já havia tentado usar nomes de arquivo diferentes ao longo das linhas da resposta de @inidona, convertida para Swift 4:

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

Infelizmente, isso não corrigiu as mensagens de erro do Firebase. Nesta pergunta: Firebase iOS SDK - o uso de um arquivo de configuração diferente de GoogleService-Info.plist gera um aviso do console que o autor da postagem original parece ter corrigido ao atualizar o Firebase Pod, mas não o confirmei.


1

Eu resolvi isso com este:

    #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

Se algum de vocês cometer um erro e o Xcode reclamar

"Vários comandos produzem GoogleService-Info.plist"

depois de aplicar a resposta do @Knight Fighter , você pode querer:

  • Verifique as fases de construção> Copiar recursos do pacote
  • Filtro para arquivos nomeados GoogleService-Info.plist
  • Remova todas as referências que você tiver a ele, uma vez que já está sendo copiado através do script.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.