Use diferentes GoogleService-Info.plist para diferentes esquemas de compilación

110

Estoy usando un esquema de compilación para prod y uno para estadificación (con 2 identificadores de paquete diferentes) y estoy tratando de usar un GoogleService-Info.plist separado para cada esquema. ¿Hay alguna forma de seleccionar manualmente el archivo plist que se utilizará al inicializar GCM (y el inicio de sesión de goole)? ¿O es posible evitar el uso de plist y realizar la configuración manualmente?

¡Gracias!

nwaxgui
fuente
3
¿Utiliza dos objetivos diferentes? Luego, tenga diferentes archivos (con el mismo nombre) en diferentes recursos de paquete de copia (que en las fases de construcción).
Alexander Zimin
6
Ese artículo fue útil para mí medium.com/rocket-fuel/… .
Eugenia
Funcionó perfectamente para mí stackoverflow.com/a/58709334/11537677
Knight Fighter

Respuestas:

142

Detalles

Probado en:

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

Solución

  1. Cree una carpeta con todos sus archivos Google.plist (con diferentes nombres) en el proyecto

ingrese la descripción de la imagen aquí

  1. Agregar secuencia de comandos de ejecución

ingrese la descripción de la imagen aquí

No olvide cambiar el 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

Crear nombres de esquemas

ingrese la descripción de la imagen aquí

Vasily Bodnarchuk
fuente
2
Save my day great answer
Siddh
1
Esta es la respuesta correcta. Aparentemente, Firebase Analytics requiere ese archivo plist en el directorio raíz de su aplicación, incluso si llama configure(options:). github.com/firebase/quickstart-ios/issues/5
Rob Bajorek
2
Esta es una solución muy buena y debería aceptarse como la respuesta.
Luke Brandon Farrell
1
Muy ligero e inteligente, gran respuesta. ¡Gracias!
gabuchan
1
@smileBot puede omitir -r, más información: comando cp en Linux / Unix
Vasily Bodnarchuk
74

La respuesta de @inidona funcionó para mí. Después de convertirlo en 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
fuente
1
Con el código anterior, ¿tiene dos archivos de GoogleService-Info.plistarchivos diferentes en diferentes ubicaciones o puede que dos archivos con nombres diferentes? ¿Podría proporcionar más información sobre cuáles son los nombres reales de los archivos y dónde están ubicados?
Varun Gupta
1
Tengo 2 archivos llamados GoogleService-Info-dev.plist GoogleService-Info-live.plist, este código le permite decirle a su aplicación con qué archivo de información desea trabajar en lugar del predeterminado GoogleService-Info-dev.plist use la declaración condicional o banderas de destino para alternar entre sus archivos
Essam Elmasry
sí, en AppDelegate
Essam Elmasry
1
me da 'No se pudo ubicar el archivo de configuración:' GoogleService-Info.plist ''
orium
Un documento reciente dice "Advertencia: este enfoque puede afectar la recopilación de Analytics en algunas circunstancias" firebase.google.com/docs/projects/multiprojects
Shingo Fukuyama
30

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

En Xcode, cree dos directorios dentro de su proyecto: Debugy Release. Coloque cada GoogleService-Info.plistarchivo allí.

En AppDelegate.m, dentro del didFinishLaunchingWithOptionsmétodo, ponga el código:

C objetivo

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

Rápido 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)

Arrastre y suelte ambas carpetas Debugy Releaseen Build Phases > Copy Bundle Resources:

Fases de compilación> Copiar recursos del paquete

Eso es :)

Bruno Lemos
fuente
1
Esto funcionó para mí. Debe agregar estas carpetas allí como referencia, de lo contrario, se bloqueará, de hecho. ¡Gracias!
Eironeia
Esta solución aún no resuelve el problema del Analyticsmarco, no puede saber cuál .plistse está cargando.
Lifely
@Bruno Lemos, ¿Puedo usar dos proyectos de Firebase de un proyecto de xcode simultáneamente? ¿No como Debug& Release? Porque cuando trato de hacer esto, siempre termino con already configured crash.que he seguido las últimas instrucciones del documento oficial de Firebase. Gracias
Tulon
24

Creo que puede usar esta forma para configurar su GoogleService-Info.plist de forma dinámica y usar diferentes nombres para diferentes identificadores de paquete.

ciao Andreas

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];
inidona
fuente
5
Con el código anterior, ¿tiene dos archivos diferentes GoogleService-Info.plist en diferentes ubicaciones o puede tener dos archivos con nombres diferentes? ¿Podría proporcionar más información sobre cuáles son los nombres reales de los archivos y dónde están ubicados?
Varun Gupta
4
Recibo este error en el registro durante la llamada configureWithOptions:Could not locate configuration file: 'GoogleService-Info.plist'
Babken Vardanyan
14

Me di cuenta de que Google espera que el nombre del archivo sea GoogleServiceInfo.plist en el 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

la frase clave es esta

leer del archivo GoogleServices-Info.plist incluido con el objetivo de su aplicación

Así que simplemente copié el mismo archivo y lo puse en diferentes directorios, y lo limité a diferentes destinos:

ingrese la descripción de la imagen aquí

abbood
fuente
Gracias, muy simple y funciona muy bien para mí, Xcode 10.1, FirebaseCore (5.3.1)
infinity_coding7
Cómo evitar el error de "producción de comandos múltiples" que ocurre después debido a múltiples Plist u otros archivos dentro de la aplicación
Wahab Khan Jadon
11

Si GoogleService-Info.plisttiene un nombre diferente, afectará los resultados de sus análisis. Firebase te advertirá sobre esto. https://github.com/firebase/firebase-ios-sdk/issues/230#issuecomment-327138180 . Por esta razón, ninguna de estas soluciones en tiempo de ejecución proporcionará los mejores resultados de análisis.

Hay dos soluciones que no afectarán a Analytics.

  1. Utilice un objetivo diferente con cada esquema y asocie cada versión de GoogleService-Info.plistcon su propio objetivo. Consulte Membresía de destino en el inspector de archivos en el lado derecho de Xcode. Para obtener más información, consulte esta pregunta .

  2. Utilice un script de fase de compilación para copiar la versión correcta de GoogleService-Info.plisten el directorio de compilación. Utilizo un ID de paquete diferente para la puesta en escena y la producción. Esto me permite tener ambas versiones de la aplicación instaladas en paralelo. También significa que con el siguiente script puedo nombrar mis diferentes GoogleService-Info.plistarchivos con el ID del paquete. Por ejemplo:

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

Crear script de 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: Tendrá que cambiar PATH_TO_CONFIGpara adaptarse a su configuración.

Crear script de fase

Onato
fuente
Esta es la mejor solución hasta ahora. Debido a que Firebase Crashlytics solo puede usar el archivo GoogleService-Info.plist para cargar archivos dSYM usando el script 'upload-symbols', ¡esta solución funciona perfectamente!
Alexey Galishnikov
6

No puede evitar usar plist con Firebase. La mejor solución que encontré hasta ahora para ti sería agregar ambos archivos y nombrarlos

GoogleService-Info_stage.plist

y

GoogleService-Info_prod.plist

Luego, desde su código, puede llamar al archivo correcto. De esta manera, no bloqueará su aplicación si no tiene el archivo. Simplemente reemplace 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)
}
pierre23
fuente
Las configuraciones en tiempo de ejecución pueden generar problemas de informes de análisis, como se menciona en los documentos .
Alex
6

Tarde, pero creo que debo publicar esta respuesta para ayudar a los nuevos desarrolladores, encontré un muy buen artículo que resuelve mi problema y prometo que también puede ayudarlo :)
Consulte este artículo que también resuelve su problema.

Paso 1:
Copie el archivo GoogleService-Info.plist correspondiente a su entorno de desarrollo de Firebase en el directorio Dev . De manera similar, copie GoogleService-Info.plist correspondiente a su entorno de producción de Firebase en el directorio Prod . Asegúrese de desmarcar "Copiar elementos si es necesario" y todos los destinos en "Agregar a destinos" .

(Enlace de imagen del paso 1 (no puedo agregar una imagen porque tengo menos reputación))

Paso 2:
En el navegador de proyectos Xcode, seleccione el destino de la aplicación. Cambie a la pestaña Build Phase en la parte superior, luego agregue una New Run Script Phase . Nombra la fase "Configurar el entorno de Firebase GoogleService-Info.plist" , o algo parecido, y colócalo antes del paso "Copiar recursos del paquete" .

Paso 3:
Implemente una secuencia de comandos de shell que copiará el archivo GoogleService-Info.plist apropiado en el paquete de aplicaciones según la configuración de la compilación. Copie y pegue el siguiente script de shell en la fase de ejecución del script que acaba de crear:

# 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
Caballero de combate
fuente
3

Esta respuesta está muy inspirada en la respuesta de @abbood , pero un poco más específica sobre cómo hacerlo.

Para cada uno de sus objetivos, por ejemplo, dev, stg, prod:

  • Descargue el correspondiente GoogleService-Info.plista una carpeta separada con el nombre de su objetivo
  • En Xcode, haga clic con el botón derecho en la carpeta de su aplicación y elija Add files to "your app" ingrese la descripción de la imagen aquí
  • Seleccione la carpeta que contiene del objetivo GoogleService-Info.plist, asegúrese Copy items if neededy Create groupsse seleccionan, marque sólo la diana correspondiente en la lista de objetivos, y pulseAdd ingrese la descripción de la imagen aquí

Eso es. Ahora debería tener algo similar a esta estructura

ingrese la descripción de la imagen aquí

Cuando construyas un objetivo, se GoogleService-Info.plistusará el correcto .

Bjørn Egil
fuente
Funcionó perfectamente para mí.
Şafak Gezer
2

Aquí se explica cómo hacerlo en Xamarin C #:

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

Recuerde incluir el espacio de nombres de Firebase:

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

¡Esta es mi solución!

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

¡Y eso es!

Ignacio Hernández
fuente
1

Creo que no es posible lograrlo sin usar el GoogleService-Info.plist.Porque antes de que pueda comenzar a integrar su aplicación iOS con los componentes de Google Sign-In, debe descargar las dependencias y configurar su proyecto Xcode. Y este proceso muestra que GoogleService-Info.plisttiene un gran factor.

Entonces, las soluciones y la idea aquí en esta pregunta SO pueden ayudarlo con su problema. Simplemente movió la copia principal GoogleService-Info plistfuera de la aplicación a 2 carpetas separadas, luego usó las Fases de compilación "Copiar archivos" en cada objetivo para importar el plist específico del objetivo a la carpeta Recursos.

También verifique esta pregunta SO , podría darle más información / idea sobre su problema.

KENdi
fuente
Aquí, ¿objetivo significa un esquema diferente para el mismo proyecto? Después de leer las preguntas, deduje que el objetivo significa un objetivo de construcción diferente por completo y no solo un esquema de construcción diferente para el mismo objetivo.
Varun Gupta
1
Pero, ¿qué pasa si tiene un objetivo con una configuración diferente para cada esquema?
evya
1

Con Xcode 9.2, he necesitado que los archivos para ambos objetivos se llamen "googleServiceInfo.plist" pero se coloquen en directorios diferentes, con el directorio / archivo para cada objetivo especificado en "Fases de compilación", "Copiar recursos de paquete".

La anterior no era mi solución preferida, pero anteriormente había intentado usar diferentes nombres de archivo en la línea de la respuesta de @ inidona, convertida a Swift 4:

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

Desafortunadamente, esto no corrigió los mensajes de error de Firebase. En esta pregunta: SDK de Firebase iOS: el uso de un archivo de configuración que no sea GoogleService-Info.plist genera una advertencia de consola que parece que el póster original se solucionó al actualizar Firebase Pod, pero no lo he confirmado.

djruss70
fuente
1

Resolví esto con esto:

    #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
fuente
1

Si alguno de ustedes cae en un error y Xcode se queja

"Varios comandos producen GoogleService-Info.plist"

después de aplicar la respuesta de @Knight Fighter , es posible que desee:

  • Verifique Fases de compilación> Copiar recursos del paquete
  • Filtrar archivos con nombre GoogleService-Info.plist
  • Elimine cualquier referencia que tenga a él, ya que ya se está copiando a través del script.
Luiz Dias
fuente