Utilisez différents GoogleService-Info.plist pour différents schémas de construction

110

J'utilise un schéma de construction pour prod et un pour la mise en scène (avec 2 identifiants de bundle différents) et j'essaie d'utiliser un GoogleService-Info.plist distinct pour chaque schéma. Existe-t-il un moyen de sélectionner manuellement le fichier plist à utiliser lors de l'initialisation de GCM (et de la connexion goole)? Ou est-il possible d'éviter d'utiliser le plist et de faire la configuration manuellement?

Merci!

nwaxgui
la source
3
Vous utilisez deux cibles différentes? Ensuite, ayez différents fichiers (avec le même nom) dans différentes ressources de copie de bundle (que dans les phases de construction).
Alexander Zimin
6
Cet article m'a été utile medium.com/rocket-fuel/… .
Eugeny
A parfaitement fonctionné pour moi stackoverflow.com/a/58709334/11537677
Knight Fighter

Réponses:

142

Détails

Testé sur:

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

Solution

  1. Créez un dossier avec tous vos fichiers Google.plist (avec des noms différents) dans le projet

entrez la description de l'image ici

  1. Ajouter un script d'exécution

entrez la description de l'image ici

N'oubliez pas de modifier la valeur de PATH_TO_GOOGLE_PLISTS

Code

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

Créer des noms de schémas

entrez la description de l'image ici

Vasily Bodnarchuk
la source
2
Save my day great answer
Siddh
1
C'est la bonne réponse. Apparemment, Firebase Analytics nécessite ce fichier plist dans le répertoire racine de votre application, même si vous appelez configure(options:). github.com/firebase/quickstart-ios/issues/5
Rob Bajorek
2
C'est une très bonne solution et devrait être acceptée comme réponse.
Luke Brandon Farrell
1
Très léger et intelligent, excellente réponse. Je vous remercie!
gabuchan
1
@smileBot vous pouvez sauter -r, plus d'informations: commande cp sous Linux / Unix
Vasily Bodnarchuk
74

La réponse de @inidona a fonctionné pour moi. Après l'avoir converti en Swift

pour Swift 2.3:

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

pour Swift 3.0:

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

pour Swift 4.0:

let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")!
let options = FirebaseOptions(contentsOfFile: filePath)
FirebaseApp.configure(options: options!)
Essam Elmasry
la source
1
Avec le code ci-dessus, avez-vous deux fichiers GoogleService-Info.plistfichiers différents à des emplacements différents ou deux fichiers avec des noms différents. Pourriez-vous s'il vous plaît fournir des informations supplémentaires sur les noms de fichiers réels et où sont-ils placés?
Varun Gupta
1
J'ai 2 fichiers nommés GoogleService-Info-dev.plist GoogleService-Info-live.plist ce code vous permet de dire à votre fichier d'informations sur l'application que vous souhaitez utiliser au lieu de l'instruction conditionnelle par défaut de GoogleService-Info-dev.plist ou drapeaux cibles pour alterner entre vos fichiers
Essam Elmasry
ouais, dans l'AppDelegate
Essam Elmasry
1
me donne 'Impossible de localiser le fichier de configuration:' GoogleService-Info.plist ''
orium
Un document récent indique "Avertissement: cette approche peut avoir un impact sur la collecte Analytics dans certaines circonstances" firebase.google.com/docs/projects/multiprojects
Shingo Fukuyama
30

Consultez cet article: https://medium.com/@brunolemos/how-to-setup-a-different-firebase-project-for-debug-and-release-environments-157b40512164

Sur Xcode, créez deux répertoires dans votre projet: Debuget Release. Mettez chaque GoogleService-Info.plistfichier là-bas.

Sur AppDelegate.m, à l'intérieur de la didFinishLaunchingWithOptionsméthode, mettez le code:

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

Faites glisser et déposez les deux dossiers Debuget Releasevers le Build Phases > Copy Bundle Resources:

Phases de construction> Copier les ressources du lot

C'est tout :)

Bruno Lemos
la source
1
Cela a fonctionné pour moi. Vous devez y ajouter ces dossiers comme référence, sinon cela plantera, en effet. Merci!
Eironeia
Cette solution ne résout toujours pas le problème du Analyticsframework, vous ne pouvez pas dire lequel .plistest chargé.
lifely
@Bruno Lemos, Puis-je utiliser simultanément deux projets Firebase d'un projet xcode? Pas comme Debug& Release? Parce que quand j'essaye de faire ça, je finis toujours par already configured crash.avoir suivi les dernières instructions du document officiel Firebase. Merci
Tulon
24

Je pense que vous pouvez utiliser cette méthode pour configurer votre GoogleService-Info.plist de manière dynamique et utiliser différents noms pour différents identifiants de bundle.

ciao Andreas

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];
Inidona
la source
5
Avec le code ci-dessus, avez-vous deux fichiers différents fichiers GoogleService-Info.plist à des emplacements différents ou deux fichiers avec des noms différents. Pourriez-vous s'il vous plaît fournir des informations supplémentaires sur les noms de fichiers réels et où sont-ils placés?
Varun Gupta
4
Je reçois cette erreur dans le journal lors de l'appel configureWithOptions:Could not locate configuration file: 'GoogleService-Info.plist'
Babken Vardanyan
14

J'ai remarqué que Google s'attend à ce que le nom de fichier soit GoogleServiceInfo.plist dans le code:

 * 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 phrase clé est celle-ci

lire à partir du fichier GoogleServices-Info.plist fourni avec votre application cible

J'ai donc simplement copié le même fichier et l'ai mis dans différents répertoires, et je l'ai lié à différentes cibles:

entrez la description de l'image ici

abbood
la source
Merci, très simple et fonctionne très bien pour moi, Xcode 10.1, FirebaseCore (5.3.1)
infinity_coding7
Comment éviter l'erreur "Plusieurs commandes produisent" qui se produisent après en raison de plusieurs fichiers Plist ou d'autres fichiers dans l'application
Wahab Khan Jadon
11

Si le GoogleService-Info.plista un nom différent, cela affectera vos résultats d'analyse. Firebase vous en avertira. https://github.com/firebase/firebase-ios-sdk/issues/230#issuecomment-327138180 . Pour cette raison, aucune de ces solutions d'exécution ne fournira les meilleurs résultats d'analyse.

Il existe deux solutions qui ne gâcheront pas Analytics.

  1. Utilisez une cible différente avec chaque schéma et associez chaque version de GoogleService-Info.plistà sa propre cible. Voir l' appartenance cible dans l' inspecteur de fichiers sur le côté droit dans Xcode. Pour plus d'informations, consultez cette question .

  2. Utilisez un script de phase de construction pour copier la version correcte de GoogleService-Info.plistdans le répertoire de construction. J'utilise un ID de bundle différent pour la mise en scène et la production. Cela me permet d'installer les deux versions de l'application en parallèle. Cela signifie également qu'avec le script ci-dessous, je peux nommer mes différents GoogleService-Info.plistfichiers avec l'ID du bundle. Par exemple:

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

Script de phase de construction

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"

Remarque: vous devrez changer PATH_TO_CONFIGen fonction de votre configuration.

Script de phase de construction

Onato
la source
C'est la meilleure solution à ce jour. Parce que Firebase Crashlytics ne peut utiliser que le fichier GoogleService-Info.plist pour télécharger des fichiers dSYM en utilisant le script 'upload-symboles' - cette solution fonctionne parfaitement!
Alexey Galishnikov
7

En retard mais je pense que je dois poster cette réponse pour aider les nouveaux développeurs, j'ai trouvé un très bon article qui résout mon problème et je vous promets qu'il pourra vous aider aussi :)
Consultez cet article qui résout votre problème aussi.

Étape 1:
Copiez le fichier GoogleService-Info.plist correspondant à votre environnement de développement Firebase dans le répertoire Dev . De même, copiez le GoogleService-Info.plist correspondant à votre environnement de production Firebase dans le répertoire Prod . Assurez-vous de décocher "Copier les éléments si nécessaire" et toutes les cibles sous "Ajouter aux cibles" .

(Lien d'image de l'étape 1 (je ne peux pas ajouter d'image en raison de moins de réputation))

Étape 2:
dans le navigateur de projet Xcode, sélectionnez la cible de l'application. Passez à l'onglet Phases de construction en haut, puis ajoutez une nouvelle phase de script d'exécution . Nommez la phase «Configurer l'environnement Firebase GoogleService-Info.plist» , ou quelque chose dans ce sens, et placez-la avant l' étape «Copier les ressources du bundle» .

Étape 3:
implémentez un script shell qui copiera le fichier GoogleService-Info.plist approprié dans le bundle d'applications en fonction de la configuration de compilation. Copiez et collez le script shell suivant dans la phase d'exécution du script que vous venez de créer:

# 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
Chevalier combattant
la source
6

Vous ne pouvez pas éviter d'utiliser le plist avec Firebase. La meilleure solution que j'ai trouvée jusqu'à présent pour vous serait d'ajouter les deux fichiers et de le nommer

GoogleService-Info_stage.plist

et

GoogleService-Info_prod.plist

Ensuite, à partir de votre code, vous pouvez appeler le fichier correct. De cette façon, votre application ne plantera pas si vous n'avez pas le fichier. Remplacez simplement FILENAME par 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
la source
Les configurations d'exécution peuvent entraîner des problèmes de rapport d'analyse, comme indiqué dans la documentation .
Alex
3

Cette réponse est très inspirée de @abbood , mais un peu plus précise sur la façon de le faire.

Pour chacune de vos cibles, par exemple dev, stg, prod:

  • Téléchargez le correspondant GoogleService-Info.plistdans un dossier distinct nommé d'après votre cible
  • Dans Xcode, cliquez avec le bouton droit sur votre dossier d'application et choisissez Add files to "your app" entrez la description de l'image ici
  • Sélectionnez le dossier contenant les cibles GoogleService-Info.plist, assurez-vous que Copy items if neededet Create groupssont sélectionnés, cochez uniquement la cible correspondante dans la liste des cibles et appuyez surAdd entrez la description de l'image ici

C'est tout. Maintenant, vous devriez avoir quelque chose de similaire à cette structure

entrez la description de l'image ici

Lorsque vous construisez une cible, la bonne GoogleService-Info.plistsera utilisée.

Bjørn Egil
la source
A parfaitement fonctionné pour moi.
Şafak Gezer
2

Voici comment procéder dans Xamarin C #:

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

N'oubliez pas d'inclure l'espace de noms Firebase:

using Firebase.Analytics;
Sune Kjærgård
la source
2

C'est ma solution!

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

Et c'est tout!

Ignacio Hernández
la source
1

Je pense qu'il n'est pas possible d'y parvenir sans utiliser le GoogleService-Info.plist.car avant de pouvoir commencer à intégrer votre application iOS avec les composants de connexion Google, vous devez télécharger les dépendances et configurer votre projet Xcode. Et ce processus montre que cela GoogleService-Info.plista un facteur important.

Ainsi, les solutions et l'idée ici dans cette question SO peuvent vous aider avec votre problème. Je viens de déplacer la copie principale duGoogleService-Info plist sortie de l'application dans 2 dossiers séparés, puis d'utiliser les phases de construction "Copier les fichiers" sur chaque cible pour importer le fichier plist spécifique à la cible dans le dossier Resources.

Vérifiez également cette question SO , elle pourrait vous donner plus d'informations / d'idées sur votre problème.

KENdi
la source
Ici, la cible signifie-t-elle un schéma différent pour le même projet? Après avoir lu les questions, j'ai compris que la cible signifiait une cible de construction complètement différente et pas seulement un schéma de construction différent pour la même cible.
Varun Gupta
1
Mais que faire si vous avez une cible avec une configuration différente pour chaque schéma?
evya
1

Avec Xcode 9.2, j'ai eu besoin que les fichiers pour les deux cibles soient nommés "googleServiceInfo.plist" mais placés dans des répertoires différents, avec le répertoire / fichier pour chaque cible spécifié dans "Build Phases", "Copy Bundle Resources".

Ce qui précède n'était pas ma solution préférée, mais j'avais déjà essayé d'utiliser différents noms de fichiers dans le sens de la réponse de @ inidona, convertie en Swift 4:

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

Malheureusement, cela n'a pas corrigé les messages d'erreur Firebase. Dans cette question: Firebase iOS SDK - L'utilisation d'un fichier de configuration autre que GoogleService-Info.plist génère un avertissement de console que l'affiche d'origine semble avoir corrigé en mettant à jour le pod Firebase mais je ne l'ai pas confirmé.

djruss70
la source
1

J'ai résolu ceci par ceci:

    #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
la source
1

Si certains d'entre vous tombent dans une erreur et que Xcode se plaint

"Plusieurs commandes produisent GoogleService-Info.plist"

après avoir appliqué la réponse @Knight Fighter , vous souhaiterez peut-être:

  • Vérifiez les phases de construction> Copier les ressources du bundle
  • Filtrer les fichiers nommés GoogleService-Info.plist
  • Supprimez toutes les références que vous y avez, car il est déjà copié via le script.
Luiz Dias
la source
0

J'ai donc réfléchi à la même question et en utilisant certaines idées de publications précédentes, dont certaines publient des applications avec GoogleServices-Info.plistpour tous les environnements dans toutes les applications et c'est un peu préoccupant.

J'ai mis au point une solution extensible qui copie le GoogleSerives-Info.plistfichier au moment de la construction. De plus, cette approche peut prendre en charge autant d'environnements que vous le souhaitez avec la possibilité de personnaliser et de suivre une convention simple, ce qui facilite la gestion.

Tout d'abord, j'ai trois environnements, debug(pour le débogage dans le simulateur et le périphérique whist et la coupe active du code), staging(pour le déploiement en vol d'essai) et releasepour la production.

La première étape consiste à créer votre (vos) configuration (s):

entrez la description de l'image ici

Sélectionnez "Produit" -> "Schéma" -> "Modifier le schéma" et dupliquez / créez-en un nouveau si nécessaire. Parcourez chaque Schéma et attribuez sa configuration respective à partir du menu déroulant "Build Configuration" dans chacune des catégories:

entrez la description de l'image ici

Je vais un peu plus loin et décoche «exécuter» pour les schémas qui doivent être distribués, c'est-à-dire la version et la mise en scène, et inversement décoche «archiver» pour le débogage. Vous devez faire ce qui a du sens pour vous.

entrez la description de l'image ici

Sous les phases de construction, ajoutez le script d'exécution suivant (la CONFIGURATIONS_FOLDERvariable peut être personnalisée comme vous le souhaitez - assurez-vous simplement d'utiliser le même nom de dossier à l'étape suivante):

# 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}'."

entrez la description de l'image ici

Dans le dossier de configuration que vous avez choisi ("Firebase" dans l'exemple ci-dessus), imbriquez des dossiers pour chaque configuration nommés exactement de la même manière que sa configuration respective (sensible à la casse), à ​​l'intérieur desquels placez les GoogleServices-Info.plistfichiers respectifs comme suit:

entrez la description de l'image ici

Enfin, j'aime également m'assurer qu'un niveau racine GoogleServices-Info.plistn'est pas ajouté au projet par accident, alors j'ajoute ce qui suit à mon .gitignore.

# Ignore project level GoogleService-Info.plist
/[Project Name]/GoogleService-Info.plist
Sagar Patel
la source