对不同的构建方案使用不同的GoogleService-Info.plist


109

我正在使用一个用于prod的构建方案,一个用于暂存的构建方案(具有2个不同的包标识符),并且我试图为每个方案使用单独的GoogleService-Info.plist。初始化GCM(和goole登录)时,有什么方法可以手动选择要使用的plist文件吗?还是可以避免使用plist并手动进行设置?

谢谢!


3
您使用两个不同的目标?然后在不同的副本捆绑资源中(在构建阶段)使用不同的文件(具有相同的名称)。
亚历山大·齐敏

6
这文章是有帮助的,我medium.com/rocket-fuel/...
Eugeny

Answers:


142

细节

经过测试:

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

  1. 使用项目中的所有Google.plist文件(名称不同)创建文件夹

在此处输入图片说明

  1. 添加运行脚本

在此处输入图片说明

不要忘记更改PATH_TO_GOOGLE_PLISTS的

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

构建方案名称

在此处输入图片说明


2
救救我这一天的好答案
Siddh '18

1
这是正确的答案。显然,Firebase Analytics要求应用程序的根目录中包含plist文件,即使您调用configure(options:)github.com/firebase/quickstart-ios/issues/5
Rob Bajorek

2
这是一个非常好的解决方案,应该被接受为答案。
卢克·布兰登·法雷尔

1
非常轻巧,很聪明。谢谢!
gabuchan

1
@smileBot您可能会跳过-r,更多信息:Linux / Unix中的cp命令
Vasily Bodnarchuk

73

@inidona的答案对我有用。将其转换为Swift之后

对于Swift 2.3:

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

对于Swift 3.0:

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

对于Swift 4.0:

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

1
使用上面的代码,您是否GoogleService-Info.plist在不同位置具有两个不同的文件文件,或者两个文件具有不同的名称。您能否提供更多有关实际文件名以及它们在哪里放置的信息?
Varun Gupta

1
我有2个名为GoogleService-Info-dev.plist的文件GoogleService-Info-live.plist此代码可让您告诉您要使用的应用程序信息信息文件,而不是使用条件语句或默认的GoogleService-Info-dev.plist目标标记在文件之间交替显示
Essam Elmasry

是啊,在AppDelegate的
埃萨姆Elmasry

1
给我“无法找到配置文件:” GoogleService-Info.plist”
Orium

最新文档显示“警告:此方法可能会在某些情况下影响Analytics(分析)集合” firebase.google.com/docs/projects/multiprojects
福山慎吾

30

检查本文:https : //medium.com/@brunolemos/how-to-setup-a-different-firebase-project-for-debug-and-release-environments-157b40512164

在Xcode上,在项目内创建两个目录:DebugRelease。将每个GoogleService-Info.plist文件放在那里。

在方法AppDelegate.m内的上didFinishLaunchingWithOptions,放置以下代码:

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

斯威夫特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)

DebugRelease文件夹都拖放到Build Phases > Copy Bundle Resources

构建阶段>复制捆绑包资源

而已 :)


1
这对我有用。您必须在此处添加这些文件夹作为参考,否则确实会崩溃。谢谢!
Eironeia '18

该解决方案仍然无法解决Analytics框架问题,您无法确定.plist正在加载哪个。
充满生命力

@Bruno Lemos,我可以同时使用一个xcode项目中的两个Firebase项目吗?不是DebugRelease吗?因为当我尝试执行此操作时,我总是最终already configured crash.会遵循Firebase官方文档中的最新说明。谢谢
Tulon

24

我认为您可以使用这种方式动态配置GoogleService-Info.plist,并对不同的包标识符使用不同的名称。

乔·安德里亚斯

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

5
使用上面的代码,您是否在不同的位置有两个不同的文件GoogleService-Info.plist文件,或者两个文件具有不同的名称。您能否提供更多有关实际文件名以及它们在哪里放置的信息?
Varun Gupta

4
我在configureWithOptions调用期间在日志中遇到此错误:Could not locate configuration file: 'GoogleService-Info.plist'
Babken Vardanyan

14

我注意到Google在代码中希望文件名是GoogleServiceInfo.plist:

 * 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

关键是这个

从与您的应用目标捆绑在一起的文件GoogleServices-Info.plist中读取

因此,我只是复制了相同的文件并将其放入不同的目录,并将其绑定到不同的目标:

在此处输入图片说明


谢谢,非常简单,对我来说效果很好,Xcode 10.1,FirebaseCore(5.3.1)
infinity_coding7,19年

如何避免由于应用程序中存在多个Plist或其他文件而导致的“多个命令产生”错误
Wahab Khan Jadon

11

如果GoogleService-Info.plist名称不同,则会影响您的分析结果。Firebase会就此警告您。https://github.com/firebase/firebase-ios-sdk/issues/230#issuecomment-327138180。因此,这些运行时解决方案都无法提供最佳的分析结果。

有两种解决方案不会与Analytics(分析)混淆。

  1. 对每个方案使用不同的目标,并将每个版本GoogleService-Info.plist与自己的目标相关联。请参阅Xcode右侧文件检查器中的Target Membership。有关更多信息,请参见此问题

  2. 使用构建阶段脚本到正确的版本复制GoogleService-Info.plist到构建目录。我使用不同的包ID进行登台和生产。这使我可以同时安装两个版本的应用程序。这也意味着在下面的脚本中,我可以GoogleService-Info.plist使用包ID 命名不同的文件。例如:

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

构建阶段脚本

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"

注意:您将不得不更改PATH_TO_CONFIG以适合您的设置。

构建阶段脚本


这是迄今为止最好的解决方案。由于Firebase Crashlytics只能使用“ upload-symbols”脚本使用GoogleService-Info.plist文件上传dSYM文件-此解决方案非常有效!
Alexey Galishnikov

6

您无法避免将plist与Firebase一起使用。我到目前为止为您找到的最佳解决方案是添加文件并命名

GoogleService-Info_stage.plist

GoogleService-Info_prod.plist

然后从您的代码中可以调用正确的文件。如果没有文件,这种方式不会使您的应用程序崩溃。只需将FILENAME替换为GoogleService-Info_prod或GoogleService-Info_stage。

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

运行时配置可能导致docs中提到的分析报告问题。
亚历克斯

6

很晚了,但我认为我必须发布此答案以帮助新开发人员,我找到了一篇很好的文章来解决我的问题,并且我保证它也可以为您提供帮助:)
检查文章,同样可以解决您的问题。

步骤1:
将与您的Firebase开发环境相对应的GoogleService-Info.plist复制到Dev目录中。同样,将与您的Firebase生产环境相对应的GoogleService-Info.plist复制到Prod目录中。确保取消选中“如果需要,复制项目”“添加到目标”下的所有目标。

(第1步图片链接(由于信誉降低,我无法添加图片))

步骤2:
在Xcode项目导航器中,选择应用程序目标。切换到顶部的Build Phases选项卡,然后添加New Run Script Phase。将阶段命名为“ Setup Firebase Environment GoogleService-Info.plist”或类似的名称,并将其放置在“ Copy Bundle Resources”之前步骤之前。

步骤3:
实施一个Shell脚本,该脚本将根据构建配置将相应的GoogleService-Info.plist复制到应用程序捆绑包中。将以下shell脚本复制并粘贴到您刚创建的运行脚本阶段:

# 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

这个答案非常受@abbood启发的答案,但是在操作方法上更加具体。

对于您的每个目标,例如dev,stg,prod:

  • 将对应GoogleService-Info.plist的文件下载到以您的目标命名的单独文件夹中
  • 在Xcode中,右键单击您的应用文件夹,然后选择 Add files to "your app" 在此处输入图片说明
  • 选择包含目标的的文件夹GoogleService-Info.plist,确保Copy items if neededCreate groups被选中,仅检查目标列表中的相应目标,然后按Add 在此处输入图片说明

而已。现在您应该具有类似于此结构的内容

在此处输入图片说明

建立目标时,GoogleService-Info.plist将使用正确的目标。


为我完美地工作。
Şafak基色

2

这是在Xamarin C#中执行的方法:

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

请记住包括Firebase命名空间:

using Firebase.Analytics;

2

这是我的解决方案!

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

就是这样!


1

我认为如果不使用,就无法实现。GoogleService-Info.plist.因为在开始将iOS应用与Google Sign-In组件集成之前,必须下载依赖项并配置Xcode项目。这个过程表明GoogleService-Info.plist有很大的影响。

因此,此SO问题中的解决方案和想法可以帮助您解决问题。刚刚移动了主副本GoogleService-Info plist out移出应用程序到2个单独的文件夹中,然后使用每个目标上的“构建阶段”“复制文件”将目标特定的plist导入到Resources文件夹中。

还要检查此SO问题,它可能会为您提供更多的信息/想法。


在这里,目标是否意味着针对同一项目的不同方案?阅读问题之后,我收集到该目标意味着完全不同的构建目标,而不仅仅是针对同一目标的不同构建方案。
Varun Gupta

1
但是,如果您为每个方案有一个目标且配置不同,该怎么办?
evya

1

使用Xcode 9.2,我需要将两个目标的文件都命名为“ googleServiceInfo.plist”,但要放置在不同的目录中,并在“构建阶段”,“复制捆绑资源”中指定每个目标的目录/文件。

上面不是我的首选解决方案,但是我之前曾尝试使用@inidona的答案使用不同的文件名,并转换为Swift 4:

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

不幸的是,这不能纠正Firebase错误消息。在此问题中:Firebase iOS SDK-使用除GoogleService-Info.plist以外的配置文件会生成控制台警告,原始海报似乎已通过更新Firebase Pod而得到修复,但我尚未确认。


1

我通过以下方法解决了这个问题:

    #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

如果你们中的一些人出错并且Xcode抱怨

“多个命令产生了GoogleService-Info.plist”

在应用@Knight Fighter 响应后,您可能想要:

  • 检查构建阶段>复制捆绑资源
  • 筛选名称为的文件 GoogleService-Info.plist
  • 删除所有对其的引用,因为它已通过脚本复制。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.