Sử dụng GoogleService-Info.plist khác nhau cho các sơ đồ xây dựng khác nhau


110

Tôi đang sử dụng một lược đồ xây dựng cho sản phẩm và một lược đồ cho dàn dựng (với 2 số nhận dạng gói khác nhau) và tôi đang cố gắng sử dụng một GoogleService-Info.plist riêng biệt cho từng lược đồ. Có cách nào để chọn tệp plist theo cách thủ công để sử dụng khi khởi chạy GCM (và đăng nhập goole) không? Hoặc có thể tránh sử dụng plist và thiết lập theo cách thủ công không?

Cảm ơn!


3
Bạn sử dụng hai mục tiêu khác nhau? Sau đó, có các tệp khác nhau (có cùng tên) trong Tài nguyên Gói Bản sao khác nhau (trong các giai đoạn xây dựng).
Alexander Zimin

6
Bài viết đó rất hữu ích cho tôi medium.com/rocket-fuel/… .
Eugeny

Làm việc hoàn hảo cho tôi stackoverflow.com/a/58709334/11537677
Knight Fighter

Câu trả lời:


142

Chi tiết

Đã thử nghiệm trên:

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

Giải pháp

  1. Tạo thư mục với tất cả các tệp Google.plist của bạn (với các tên khác nhau) trong dự án

nhập mô tả hình ảnh ở đây

  1. Thêm tập lệnh chạy

nhập mô tả hình ảnh ở đây

Đừng quên thay đổi giá trị 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

Xây dựng tên lược đồ

nhập mô tả hình ảnh ở đây


2
Lưu câu trả lời tuyệt vời trong ngày của tôi
Siddh

1
Đây là câu trả lời đúng. Rõ ràng Firebase Analytics yêu cầu tệp plist đó trong thư mục gốc của ứng dụng của bạn, ngay cả khi bạn gọi configure(options:). github.com/firebase/quickstart-ios/issues/5
Rob Bajorek

2
Đây là một giải pháp rất hay và nên được chấp nhận là câu trả lời.
Luke Brandon Farrell

1
Rất nhẹ nhàng và thông minh, câu trả lời tuyệt vời. Cảm ơn bạn!
gabuchan

1
@smileBạn có thể bỏ qua -r, thông tin thêm: lệnh cp trong Linux / Unix
Vasily Bodnarchuk 19/02/19

73

Câu trả lời của @inidona phù hợp với tôi. Sau khi tôi chuyển đổi nó sang Swift

cho Swift 2.3:

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

cho Swift 3.0:

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

cho Swift 4.0:

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

1
Với đoạn mã trên, bạn có hai tệp GoogleService-Info.plisttin khác nhau ở các vị trí khác nhau hoặc có thể hai tệp có tên khác nhau. Bạn có thể vui lòng cung cấp thêm một số thông tin về tên tệp thực sự là gì và chúng được đặt ở đâu?
Varun Gupta,

1
Tôi có 2 tệp có tên GoogleService-Info-dev.plist GoogleService-Info-live.plist mã này cho phép bạn thông báo cho tệp thông tin ứng dụng của bạn mà bạn muốn làm việc thay vì sử dụng câu lệnh điều kiện GoogleService-Info-dev.plist mặc định hoặc nhắm mục tiêu cờ để thay thế giữa các tập tin của bạn
Essam Elmasry

vâng, trong AppDelegate
Essam Elmasry.

1
cung cấp cho tôi 'Không thể định vị tệp cấu hình:' GoogleService-Info.plist ''
orium

Tài liệu gần đây cho biết "Cảnh báo: Phương pháp này có thể ảnh hưởng đến việc thu thập Analytics trong một số trường hợp" firebase.google.com/docs/projects/multiprojects
Shingo Fukuyama

30

Kiểm tra bài viết này: https://medium.com/@brunolemos/how-to-setup-a-dierence-firebase-project-for-debug-and-release-enosystem-157b40512164

Trên Xcode, tạo hai thư mục bên trong dự án của bạn: DebugRelease. Đặt từng GoogleService-Info.plisttệp ở đó.

Trên AppDelegate.m, bên trong didFinishLaunchingWithOptionsphương thức, hãy đặt mã:

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)

Kéo và thả cả hai DebugReleasecác thư mục vào Build Phases > Copy Bundle Resources:

Xây dựng giai đoạn> Sao chép tài nguyên gói

Đó là nó :)


1
Điều này đã làm việc cho tôi. Bạn phải thêm các thư mục này vào đó làm tài liệu tham khảo, nếu không nó sẽ bị sập. Cảm ơn!
Eironeia

Giải pháp này vẫn không giải quyết được vấn đề cho Analyticskhuôn khổ, bạn không thể biết cái nào .plistđang được tải.
Lifely

@Bruno Lemos, Tôi có thể sử dụng đồng thời hai dự án Firebase từ một dự án xcode không? Không phải là Debug& Release? Vì khi tôi cố gắng làm điều này, tôi luôn kết thúc với lý do là already configured crash.tôi đã làm theo hướng dẫn mới nhất từ ​​tài liệu chính thức của Firebase. Cảm ơn
Tulon

24

Tôi nghĩ rằng bạn có thể sử dụng cách này để định cấu hình động GoogleService-Info.plist của mình và sử dụng các tên khác nhau cho các số nhận dạng gói khác nhau.

ciao Andreas

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

5
Với đoạn mã trên, bạn có hai tệp GoogleService-Info.plist tệp khác nhau ở các vị trí khác nhau hoặc có thể hai tệp có tên khác nhau. Bạn có thể vui lòng cung cấp thêm một số thông tin về tên tệp thực sự là gì và chúng được đặt ở đâu?
Varun Gupta

4
Tôi nhận được lỗi này trong nhật ký trong cuộc gọi configWithOptions:Could not locate configuration file: 'GoogleService-Info.plist'
configWithOptions Babken Vardanyan

14

Tôi nhận thấy rằng google mong đợi tên tệp là GoogleServiceInfo.plist trong mã:

 * 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

cụm từ chính là cái này

đọc từ tệp GoogleServices-Info.plist đi kèm với mục tiêu ứng dụng của bạn

Vì vậy, tôi chỉ cần sao chép cùng một tệp và đặt nó vào các thư mục khác nhau và giới hạn nó với các mục tiêu khác nhau:

nhập mô tả hình ảnh ở đây


Cảm ơn, rất đơn giản và hoạt động rất tốt đối với tôi, Xcode 10.1, FirebaseCore (5.3.1)
infinity_coding7

Làm thế nào để tránh lỗi "Nhiều lệnh sản" xảy ra sau vì nhiều Plist hoặc các tập tin khác trong App
Wahab Khan Jadon

11

Nếu GoogleService-Info.plistcó tên khác, nó sẽ ảnh hưởng đến kết quả phân tích của bạn. Firebase sẽ cảnh báo bạn về điều này. https://github.com/firebase/firebase-ios-sdk/issues/230#issuecomment-327138180 . Vì lý do này, không có giải pháp thời gian chạy nào sẽ cung cấp kết quả phân tích tốt nhất.

Có hai giải pháp sẽ không gây rắc rối với Analytics.

  1. Sử dụng một mục tiêu khác với từng lược đồ và liên kết từng phiên bản của GoogleService-Info.plistvới mục tiêu của chính nó. Xem Tư cách thành viên mục tiêu trong Trình kiểm tra tệp ở phía bên phải trong Xcode. Để biết thêm thông tin Xem câu hỏi này .

  2. Sử dụng kịch bản giai đoạn xây dựng để sao chép phiên bản chính xác của GoogleService-Info.plistvào thư mục xây dựng. Tôi sử dụng một ID gói khác để dàn dựng và sản xuất. Điều này cho phép tôi cài đặt song song cả hai phiên bản của ứng dụng. Điều đó cũng có nghĩa là với tập lệnh bên dưới, tôi có thể đặt tên các GoogleService-Info.plisttệp khác nhau của mình bằng ID gói. Ví dụ:

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

Xây dựng kịch bản giai đoạn

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"

Lưu ý: Bạn sẽ phải thay đổi PATH_TO_CONFIGđể phù hợp với thiết lập của mình.

Xây dựng kịch bản giai đoạn


Đây là giải pháp tốt nhất cho đến nay. Vì Firebase Crashlytics chỉ có thể sử dụng tệp GoogleService-Info.plist để tải lên tệp dSYM bằng tập lệnh 'upload-Symbol' - giải pháp này hoạt động hoàn hảo!
Alexey Galishnikov

6

Bạn không thể tránh sử dụng plist với Firebase. Giải pháp tốt nhất mà tôi tìm thấy cho đến nay cho bạn đó là thêm cả hai tệp và đặt tên cho nó

GoogleService-Info_stage.plist

GoogleService-Info_prod.plist

Sau đó, từ mã của bạn, bạn có thể gọi đúng tệp. Cách này sẽ không làm hỏng ứng dụng của bạn nếu bạn không có tệp. Chỉ cần thay thế FILENAME bằng GoogleService-Info_prod hoặc GoogleService-Info_stage.

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

Cấu hình thời gian chạy có thể dẫn đến các vấn đề báo cáo phân tích như đã đề cập trong tài liệu .
Alex

6

Đã muộn nhưng tôi nghĩ tôi phải đăng câu trả lời này để giúp các nhà phát triển mới, tôi đã tìm thấy một bài viết rất hay giải đáp được vấn đề của tôi và tôi hứa nó cũng có thể giúp bạn :)
Hãy xem bài viết này cũng giải quyết được vấn đề của bạn.

Bước 1:
Sao chép GoogleService-Info.plist tương ứng với môi trường phát triển Firebase của bạn vào thư mục Dev . Tương tự, sao chép GoogleService-Info.plist tương ứng với môi trường sản xuất Firebase của bạn trong thư mục Sản phẩm . Đảm bảo bỏ chọn “Sao chép các mục nếu cần” và tất cả các mục tiêu trong “Thêm vào mục tiêu” .

(Liên kết hình ảnh bước 1 (Tôi không thể thêm hình ảnh vì ít danh tiếng))

Bước 2:
Trong trình điều hướng dự án Xcode, chọn mục tiêu ứng dụng. Chuyển sang tab Giai đoạn xây dựng ở trên cùng, sau đó thêm Giai đoạn chạy kịch bản mới . Đặt tên cho giai đoạn là “Thiết lập Môi trường Firebase GoogleService-Info.plist” hoặc một cái gì đó có hiệu lực và đặt nó trước “Tài nguyên gói sao chép” .

Bước 3:
Triển khai tập lệnh shell sẽ sao chép GoogleService-Info.plist thích hợp vào gói ứng dụng dựa trên cấu hình bản dựng. Sao chép và dán tập lệnh shell sau vào giai đoạn chạy tập lệnh mà bạn vừa tạo:

# 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

Câu trả lời này được truyền cảm hứng rất nhiều từ @abbood , nhưng cụ thể hơn một chút về cách thực hiện.

Đối với mỗi mục tiêu của bạn, ví dụ như dev, stg, prod:

  • Tải xuống GoogleService-Info.plistthư mục tương ứng với một thư mục riêng biệt được đặt tên theo mục tiêu của bạn
  • Trong Xcode, nhấp chuột phải vào thư mục ứng dụng của bạn và chọn Add files to "your app" nhập mô tả hình ảnh ở đây
  • Chọn thư mục chứa mục tiêu GoogleService-Info.plist, đảm bảo Copy items if neededvà đã Create groupsđược chọn, chỉ kiểm tra mục tiêu tương ứng trong danh sách mục tiêu và nhấnAdd nhập mô tả hình ảnh ở đây

Đó là nó. Bây giờ bạn sẽ có một cái gì đó tương tự như cấu trúc này

nhập mô tả hình ảnh ở đây

Khi bạn xây dựng một mục tiêu, mục tiêu chính xác GoogleService-Info.plistsẽ được sử dụng.


Làm việc hoàn hảo cho tôi.
Şafak Gezer

2

Đây là cách thực hiện trong Xamarin C #:

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

Hãy nhớ bao gồm không gian tên Firebase:

using Firebase.Analytics;

2

Đây là giải pháp của tôi!

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

Và đó là nó!


1

Tôi nghĩ rằng không thể đạt được nếu không sử dụng GoogleService-Info.plist.Vì trước khi bạn có thể bắt đầu tích hợp ứng dụng iOS của mình với các thành phần Đăng nhập của Google, bạn phải tải xuống các phần phụ thuộc và định cấu hình dự án Xcode của mình. Và quá trình này cho thấy điều đó GoogleService-Info.plistcó một yếu tố quan trọng.

Vì vậy, các giải pháp và ý tưởng ở đây trong câu hỏi SO này có thể giúp bạn giải quyết vấn đề của mình. Vừa di chuyển bản sao chính củaGoogleService-Info plist ứng dụng vào 2 thư mục riêng biệt, sau đó sử dụng "Copy Files" trong các giai đoạn xây dựng trên mỗi mục tiêu để nhập plist mục tiêu cụ thể vào thư mục Tài nguyên.

Cũng kiểm tra câu hỏi SO này , nó có thể cung cấp cho bạn thêm thông tin / ý tưởng cho vấn đề của bạn.


Ở đây, target có nghĩa là một lược đồ khác cho cùng một dự án? Sau khi đọc các câu hỏi, tôi thu thập được rằng mục tiêu có nghĩa là một mục tiêu xây dựng khác hoàn toàn và không chỉ là một kế hoạch xây dựng khác cho cùng một mục tiêu.
Varun Gupta,

1
Nhưng nếu bạn có một mục tiêu với một cấu hình khác nhau cho mỗi chương trình?
evya

1

Với Xcode 9.2, tôi cần các tệp cho cả hai mục tiêu được đặt tên là "googleServiceInfo.plist" nhưng được đặt trong các thư mục khác nhau, với thư mục / tệp cho từng mục tiêu được chỉ định trong "Xây dựng giai đoạn", "Sao chép tài nguyên gói".

Ở trên không phải là giải pháp ưa thích của tôi, nhưng trước đây tôi đã thử sử dụng các tên tệp khác nhau dọc theo dòng câu trả lời của @ inidona, được chuyển đổi thành Swift 4:

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

Rất tiếc, điều này không sửa được thông báo lỗi Firebase. Trong câu hỏi này: Firebase iOS SDK - Sử dụng tệp cấu hình khác với GoogleService-Info.plist tạo ra cảnh báo bảng điều khiển mà người đăng ban đầu dường như đã khắc phục bằng cách cập nhật Firebase Pod nhưng tôi chưa xác nhận điều này.


1

Tôi đã giải quyết điều này bằng cách này:

    #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

Nếu một số bạn gặp lỗi và Xcode phàn nàn

"Nhiều lệnh tạo ra GoogleService-Info.plist"

sau khi áp dụng phản hồi @Knight Fighter , bạn có thể muốn:

  • Kiểm tra các giai đoạn xây dựng> Sao chép tài nguyên gói
  • Lọc các tệp có tên GoogleService-Info.plist
  • Xóa bất kỳ tham chiếu nào bạn có vì nó đã được sao chép thông qua tập lệnh.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.