Utilizza diversi GoogleService-Info.plist per diversi schemi di build


110

Sto utilizzando uno schema di compilazione per prod e uno per la gestione temporanea (con 2 diversi identificatori di bundle) e sto cercando di utilizzare un GoogleService-Info.plist separato per ogni schema. Esiste un modo per selezionare manualmente il file plist da utilizzare durante l'inizializzazione di GCM (e l'accesso goole)? O è possibile evitare di utilizzare il plist e fare la configurazione manualmente?

Grazie!


3
Usi due bersagli diversi? Quindi avere file diversi (con lo stesso nome) in diverse risorse del pacchetto di copia (che nelle fasi di compilazione).
Alexander Zimin

6
Quell'articolo è stato utile per me medium.com/rocket-fuel/… .
Eugeny

Ha funzionato perfettamente per me stackoverflow.com/a/58709334/11537677
Knight Fighter

Risposte:


142

Dettagli

Testato su:

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

Soluzione

  1. Crea una cartella con tutti i tuoi file Google.plist (con nomi diversi) nel progetto

inserisci qui la descrizione dell'immagine

  1. Aggiungi script di esecuzione

inserisci qui la descrizione dell'immagine

Non dimenticare di modificare il valore PATH_TO_GOOGLE_PLISTS

Codice

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

Crea nomi di schemi

inserisci qui la descrizione dell'immagine


2
Salva la mia giornata grande risposta
Siddh

1
Questa è la risposta esatta. Apparentemente Firebase Analytics richiede quel file plist nella directory principale della tua app, anche se chiami configure(options:). github.com/firebase/quickstart-ios/issues/5
Rob Bajorek

2
Questa è una soluzione molto carina e dovrebbe essere accettata come risposta.
Luke Brandon Farrell

1
Molto leggero e intelligente, ottima risposta. Grazie!
gabuchan

1
@smileBot puoi saltare -r, maggiori informazioni: comando cp in Linux / Unix
Vasily Bodnarchuk,

73

La risposta di @inidona ha funzionato per me. Dopo averlo convertito in Swift

per Swift 2.3:

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

per Swift 3.0:

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

per Swift 4.0:

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

1
Con il codice sopra, hai due file di GoogleService-Info.plistfile diversi in posizioni diverse o puoi due file con nomi diversi. Potresti fornire qualche informazione in più su quali sono i nomi effettivi dei file e dove si trovano?
Varun Gupta

1
Ho 2 file denominati GoogleService-Info-dev.plist GoogleService-Info-live.plist questo codice ti consente di dire alla tua app con quale file di informazioni vuoi lavorare invece del predefinito GoogleService-Info-dev.plist usa la dichiarazione condizionale o flag di destinazione per alternare i file
Essam Elmasry

sì, in AppDelegate
Essam Elmasry

1
mi dà "Impossibile individuare il file di configurazione:" GoogleService-Info.plist "
orium

Un documento recente dice "Attenzione: questo approccio può influire sulla raccolta di Analytics in alcune circostanze" firebase.google.com/docs/projects/multiprojects
Shingo Fukuyama

30

Controlla questo articolo: https://medium.com/@brunolemos/how-to-setup-a-different-firebase-project-for-debug-and-release-environments-157b40512164

Su Xcode, crea due directory all'interno del tuo progetto: Debuge Release. Metti GoogleService-Info.plistlì ogni file.

Su AppDelegate.m, all'interno del didFinishLaunchingWithOptionsmetodo, inserisci il codice:

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)

Drag & drop sia Debuge Releasecartelle alla Build Phases > Copy Bundle Resources:

Fasi di compilazione> Copia risorse bundle

Questo è tutto :)


1
Questo ha funzionato per me. Devi aggiungere queste cartelle lì come riferimento, altrimenti andrà in crash, anzi. Grazie!
Eironeia

Questa soluzione ancora non risolve il problema per il Analyticsframework, non è possibile sapere quale .plistviene caricato.
Lifely

@Bruno Lemos, posso usare due progetti Firebase da un progetto xcode contemporaneamente? Non come Debug& Release? Perché quando provo a farlo finisco sempre con already configured crash.aver seguito le ultime istruzioni dal documento ufficiale di Firebase. Grazie
Tulon

24

Penso che tu possa utilizzare questo modo per configurare il tuo GoogleService-Info.plist in modo dinamico e utilizzare nomi diversi per identificatori di bundle diversi.

ciao Andreas

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

5
Con il codice sopra, hai due file diversi file GoogleService-Info.plist in posizioni diverse o possono due file con nomi diversi. Potresti fornire qualche informazione in più su quali sono i nomi effettivi dei file e dove si trovano?
Varun Gupta

4
Ricevo questo errore nel registro durante la chiamata configureWithOptions:Could not locate configuration file: 'GoogleService-Info.plist'
Babken Vardanyan

14

Ho notato che Google si aspetta che il nome del file sia GoogleServiceInfo.plist nel codice:

 * 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

la frase chiave è questa

leggere dal file GoogleServices-Info.plist in bundle con la destinazione dell'app

Quindi ho semplicemente copiato lo stesso file e l'ho inserito in directory diverse e l'ho limitato a destinazioni diverse:

inserisci qui la descrizione dell'immagine


Grazie, molto semplice e funziona molto bene per me, Xcode 10.1, FirebaseCore (5.3.1)
infinity_coding7

Come evitare l'errore "Produzione di più comandi" che si verifica dopo a causa di più file Plist o altri file all'interno dell'app
Wahab Khan Jadon

11

Se GoogleService-Info.plistha un nome diverso, influirà sui risultati delle analisi. Firebase ti avviserà di questo.https://github.com/firebase/firebase-ios-sdk/issues/230#issuecomment-327138180 . Per questo motivo, nessuna di queste soluzioni runtime fornirà i migliori risultati di analisi.

Esistono due soluzioni che non interferiscono con Analytics.

  1. Usa un target diverso con ogni schema e associa ogni versione di GoogleService-Info.plistal proprio target. Vedere target appartenenza nel Inspector File sul lato destro in Xcode. Per ulteriori informazioni Vedi questa domanda .

  2. Utilizzare uno script della fase di compilazione per copiare la versione corretta di GoogleService-Info.plistnella directory di compilazione. Utilizzo un ID bundle diverso per lo staging e la produzione. Ciò mi consente di avere entrambe le versioni dell'app installate in parallelo. Significa anche che con lo script seguente posso nominare i miei diversi GoogleService-Info.plistfile con l'ID bundle. Per esempio:

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

Crea script fase

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: sarà necessario modificare PATH_TO_CONFIGin base alla configurazione.

Crea script fase


Questa è la migliore soluzione finora. Poiché Firebase Crashlytics può utilizzare solo il file GoogleService-Info.plist per caricare file dSYM utilizzando lo script "upload-symbol", questa soluzione funziona perfettamente!
Alexey Galishnikov il

6

Non puoi evitare di utilizzare il plist con Firebase. La soluzione migliore che ho trovato finora per te sarebbe stata quella di aggiungere entrambi i file e nominarli

GoogleService-Info_stage.plist

e

GoogleService-Info_prod.plist

Quindi dal tuo codice puoi chiamare il file corretto. In questo modo la tua app non andrà in crash se non hai il file. Basta sostituire FILENAME con GoogleService-Info_prod o GoogleService-Info_stage.

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

Le configurazioni di runtime possono portare a problemi di reportistica analitica come indicato nei documenti .
Alex

6

In ritardo ma penso di dover pubblicare questa risposta per aiutare i nuovi sviluppatori, ho trovato un ottimo articolo che ha risolto il mio problema e prometto che può aiutare anche te :)
Controlla questo articolo che risolve il tuo problema.

Passaggio 1:
copia il file GoogleService-Info.plist corrispondente al tuo ambiente di sviluppo Firebase nella directory Dev . Allo stesso modo, copia il GoogleService-Info.plist corrispondente al tuo ambiente di produzione Firebase nella directory Prod . Assicurati di deselezionare "Copia elementi se necessario" e tutti i target in "Aggiungi a target" .

(Passaggio 1 collegamento all'immagine (non riesco ad aggiungere un'immagine a causa della minore reputazione))

Passaggio 2:
nel navigatore del progetto Xcode, seleziona la destinazione dell'app. Passa alla scheda Build Phases in alto, quindi aggiungi una New Run Script Phase . Assegna alla fase il nome "Setup Firebase Environment GoogleService-Info.plist" o qualcosa in tal senso e inseriscilo prima di "Copy Bundle Resources" .

Passaggio 3:
implementa uno script della shell che copierà l'appropriato GoogleService-Info.plist nell'app bundle in base alla configurazione della build. Copia e incolla il seguente script di shell nella fase di esecuzione dello script appena creata:

# 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

Questa risposta è molto ispirata da @abbood , ma un po 'più specifica su come farlo.

Per ciascuno dei tuoi obiettivi, ad esempio dev, stg, prod:

  • Scarica il corrispondente GoogleService-Info.plistin una cartella separata che prende il nome dalla tua destinazione
  • In Xcode, fai clic con il pulsante destro del mouse sulla cartella dell'app e scegli Add files to "your app" inserisci qui la descrizione dell'immagine
  • Selezionare la cartella contenente i target GoogleService-Info.plist, assicurarsi che Copy items if needede Create groupssiano selezionati, controllare solo il target corrispondente nell'elenco dei target e premereAdd inserisci qui la descrizione dell'immagine

Questo è tutto. Ora dovresti avere qualcosa di simile a questa struttura

inserisci qui la descrizione dell'immagine

Quando costruisci un obiettivo, GoogleService-Info.plistverrà utilizzato il corretto .


Ha funzionato perfettamente per me.
Şafak Gezer

2

Ecco come farlo in Xamarin C #:

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

Ricorda di includere lo spazio dei nomi Firebase:

using Firebase.Analytics;

2

Questa è la mia soluzione!

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 questo è tutto!


1

Penso che non sia possibile ottenere risultati senza utilizzare il GoogleService-Info.plist.perché prima di poter iniziare a integrare la tua app iOS con i componenti di Google Sign-In, devi scaricare le dipendenze e configurare il tuo progetto Xcode. E questo processo mostra che GoogleService-Info.plistha un grande fattore su di esso.

Quindi le soluzioni e l'idea qui in questa domanda SO possono aiutarti con il tuo problema. Ho appena spostato la copia principale del fileGoogleService-Info plist fuori dall'app in 2 cartelle separate, quindi utilizzare la funzione Build Phases "Copia file" su ciascuna destinazione per importare il plist specifico di destinazione nella cartella Risorse.

Controlla anche questa domanda SO , potrebbe darti maggiori informazioni / idee sul tuo problema.


In questo caso, target significa uno schema diverso per lo stesso progetto? Dopo aver letto le domande, ho capito che il target indica un target di build completamente diverso e non solo uno schema di build diverso per lo stesso target.
Varun Gupta

1
Ma cosa succede se hai un obiettivo con una configurazione diversa per ogni schema?
evya

1

Con Xcode 9.2, avevo bisogno che i file per entrambi i target fossero denominati "googleServiceInfo.plist" ma collocati in directory diverse, con la directory / file per ogni target specificato in "Build Phases", "Copy Bundle Resources".

Quanto sopra non era la mia soluzione preferita, ma in precedenza avevo provato a utilizzare nomi di file diversi sulla falsariga della risposta di @ inidona, convertita in Swift 4:

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

Sfortunatamente, questo non ha corretto i messaggi di errore di Firebase. In questa domanda: Firebase iOS SDK: l'utilizzo di un file di configurazione diverso da GoogleService-Info.plist genera un avviso della console che il poster originale sembra essere stato risolto aggiornando Firebase Pod ma non l'ho confermato.


1

Ho risolto questo problema:

    #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 alcuni di voi cadono in un errore e Xcode si lamenta

"Più comandi producono GoogleService-Info.plist"

dopo aver applicato la risposta di @Knight Fighter , potresti voler:

  • Seleziona Build Phases> Copy Bundle Resources
  • Filtra per file denominati GoogleService-Info.plist
  • Rimuovi tutti i riferimenti che hai ad esso, poiché è già stato copiato attraverso lo script.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.