在 Swift 中使用 Google 日历 API 时收到错误 "Daily Limit For Unauthenticated Use Exceeded"

Receiving Error "Daily Limit For Unauthenticated Use Exceeded" When Using Google Calendar API in Swift

我目前正在开发一个需要在 Swift 中使用 Google 日历 API 的应用程序。不幸的是,该项目的进展处于停滞状态,因为我无法确定我需要如何进行才能克服标题中显示的错误。它在执行 google 登录功能后立即出现。绕过 firebase 客户端 ID 以支持通过 Google 开发人员控制台生成的不同客户端 ID 似乎也没有解决问题。在代码中多次出现时,我添加了范围值以及添加了“https://www.googleapis.com/auth/userinfo.profile" to the scope based on another Whosebug user's solution but none of it has resolved my problem. I do have a Google-Info.plist file who has been properly configured with the reverse ID as well as url scheme, and also attempted to use the client id from that plist file to perform the function, but it still doesn't seem to work. Below I have included code from the two dominant parts of my program that include references to the calendar api or authorization functions. Let me know if there's anything you see that may be incorrectly implemented or if I missed a step in getting this to work. Most of my code is based on the quickstart code provided here: https://developers.google.com/google-apps/calendar/quickstart/ios?ver=swift

仅进行了细微改动以允许额外实施 Firebase。 注意:Sign-In 似乎确实有效,并且正在成功地将数据传送到 firebase,一旦调用 Google 日历,它就不允许进一步的进展。除了我在下面提供的内容之外,还有一个单独的 viewcontroller 包含 google 登录按钮,但我不认为我遇到的问题在于 class ,因此它被排除在外。

APPDELEGATE
import UIKit
import Firebase
import GoogleSignIn
import FirebaseDatabase
import GoogleAPIClientForREST

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {

    var scopes = [kGTLRAuthScopeCalendarReadonly, "https://www.googleapis.com/auth/userinfo.profile"]


    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()

        GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
        GIDSignIn.sharedInstance().delegate = self
        GIDSignIn.sharedInstance().scopes = scopes


        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = UINavigationController(rootViewController: ViewController())
        window?.makeKeyAndVisible()

        return true
    }


    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {

        if let err = error {
            print("Failed to log into Google: ", err)

            return
        }

        print("Successfully logged into Google", user)
        //Allows information to be stored in Firebase Database
        let ref = Database.database().reference(fromURL: "https://tesseractscheduler.firebaseio.com/")

        guard let idToken = user.authentication.idToken else { return }
        guard let accessToken = user.authentication.accessToken else { return }
        LoginController().service.authorizer = user.authentication.fetcherAuthorizer()
        let credentials = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken)

        Auth.auth().signIn(with: credentials, completion: { (user, error) in
            if let err = error {
            print("Failed to create a Firebase User with Google account: ", err)
                return

            }

            //successfully authenticated user
            guard let uid = user?.uid else { return }
            print("Successfully logged into Firebase with Google", uid)



            //Creates database entry with users unique identifier, username, and email.  "null" provided to prevent errors.
            ref.updateChildValues(["UID": uid, "username": user?.displayName ?? "null", "Email": user?.email ?? "null"])

            //Pushes to next screen if login has occurred.
            if GIDSignIn.sharedInstance().hasAuthInKeychain(){
                //GIDSignIn.sharedInstance().clientID = "197204473417-56pqo0dhn8v2nf5v64aj7o64ui414rv7.apps.googleusercontent.com"
                self.window?.rootViewController = UINavigationController(rootViewController: LoginController())
            }
            LoginController().fetchEvents()
        })

    }




    func application(_ application: UIApplication, open url: URL, options:
        [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {




        GIDSignIn.sharedInstance().handle(url,
                                          sourceApplication: options[

                        UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation : options[UIApplicationOpenURLOptionsKey.annotation])

        return true
    }

LOGINCONTROLLER
import UIKit
import GoogleSignIn
import Firebase
import GoogleAPIClientForREST

class LoginController: UIViewController {


    let service = GTLRCalendarService()
    let output = UITextView()
    let appDelegate = (UIApplication.shared.delegate as? AppDelegate)



    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(didTapSignOut))
         view.backgroundColor = UIColor(red: 61/255, green: 91/255, blue: 151/255, alpha: 1)

        output.frame = view.bounds
        output.isEditable = false
        output.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0)
        output.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        output.isHidden = true
        view.addSubview(output);



        }

    func fetchEvents() {
        let query = GTLRCalendarQuery_EventsList.query(withCalendarId: "primary")
        query.maxResults = 10
        query.timeMin = GTLRDateTime(date: Date())
        query.singleEvents = true
        query.orderBy = kGTLRCalendarOrderByStartTime
        service.executeQuery(
            query,
            delegate: self,
            didFinish: #selector(displayResultWithTicket(ticket:finishedWithObject:error:)))
    }

    @objc func displayResultWithTicket(
        ticket: GTLRServiceTicket,
        finishedWithObject response : GTLRCalendar_Events,
        error : NSError?) {

        if let error = error {
            showAlert(title: "Error", message: error.localizedDescription)
            return
        }

        var outputText = ""
        if let events = response.items, !events.isEmpty {
            for event in events {
                let start = event.start!.dateTime ?? event.start!.date!
                let startString = DateFormatter.localizedString(
                    from: start.date,
                    dateStyle: .short,
                    timeStyle: .short)
                outputText += "\(startString) - \(event.summary!)\n"
            }
        } else {
            outputText = "No upcoming events found."
        }
        output.text = outputText
    }

    private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
        UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
    }
    //Shows an error alert with a specified output from the log.
    func showAlert(title : String, message: String) {
        let alert = UIAlertController(
            title: title,
            message: message,
            preferredStyle: UIAlertControllerStyle.alert
        )
        let ok = UIAlertAction(
            title: "OK",
            style: UIAlertActionStyle.default,
            handler: nil
        )
        alert.addAction(ok)
        presentViewController(alert: alert, animated: true, completion: nil)
    }

    //Communicated to navigation button to perform logout function.
    @objc func didTapSignOut(_ sender: AnyObject) {
            GIDSignIn.sharedInstance().signOut()
            print("Successfully logged out of Google.")
            showAlert(title: "Log Off", message: "Logout Successful!")
        appDelegate?.window?.rootViewController = UINavigationController(rootViewController: ViewController())

    }




        // Do any additional setup after loading the view.
    }

如果您还需要提供任何其他信息来帮助确定问题,请告诉我。我已经进行了相当广泛的搜索,但无法为我的特定问题找到解决方案。如果这是一个愚蠢的问题,我深表歉意:我对合并 APIs 还是相当陌生。

我不能确定是否有更有效的解决方法,但目前我已经能够通过剥离所有对 Firebase 的引用并忽略其实现的代码来避免此错误。我验证 Google 使用 Firebase 登录的方式导致出现此错误。删除 Firebase 后,这不再是问题。 El Tomato 的问题让我尝试了这种方法,到目前为止我至少能够取得进展。如果我在项目后期有时间,我可能会回来看看是否可以在不发生错误的情况下实现它们,但现在它是一个 non-vital 功能。