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!

nwaxgui
fonte
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

Vasily Bodnarchuk
fonte
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!)
Essam Elmasry
fonte
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í :)

Bruno Lemos
fonte
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];
Inidona
fonte
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

abbood
fonte
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

Onato
fonte
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)
}
pierre23
fonte
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
Knight Fighter
fonte
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.

Bjørn Egil
fonte
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;
Sune Kjærgård
fonte
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!

Ignacio Hernández
fonte
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.

KENdi
fonte
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.

Djruss70
fonte
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
Arafin Russell
fonte
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.
Luiz dias
fonte