Accédez à Google Agenda depuis l'application iOS

Cette fois, je souhaite accéder à Google Agenda depuis l'application iOS via l'API Google Calenear.

Environnement: Xcode 12.0, Swift 5

Préparation

Tout d'abord, accédez à Google Cloud Platform et activez l'API Google Calendar. Ensuite, obtenez l'ID client OAuth pour l'authentification OAuth. Suivez la procédure décrite dans «Enregistrement d'un ID client» dans l'article suivant pour demander un ID client.

J'ai accédé à l'API Google Agenda avec Swift4

Bibliothèque externe à utiliser

L'API Google elle-même est une API REST, mais il est difficile de l'appeler directement, je vais donc utiliser une bibliothèque externe. Cette fois, nous utiliserons les bibliothèques suivantes.

・ Authentification Google AppAuth GTMAppAuth

・ Accès à Google Agenda GoogleAPIClientForREST/Calendar

Toutes les bibliothèques ci-dessus peuvent être installées sur CocoaPods. Écrivez le Podfile comme indiqué ci-dessous et exécutez l'installation du pod pour l'installer.

platform :ios, '14.0'

target 'GoogleCalendarSample' do
  use_frameworks!

  pod 'AppAuth'
  pod 'GTMAppAuth'
  pod 'GoogleAPIClientForREST/Calendar'

end

Authentification

Maintenant, nous allons mettre en œuvre le processus d'authentification Google à l'aide d'AppAuth et de GTMAppAuth.

Tout d'abord, ajoutez la classe OIDExternalUserAgentSession à AppDelegate.

AppDelegate.swift


import UIKit
import AppAuth
import GTMAppAuth

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var currentAuthorizationFlow: OIDExternalUserAgentSession?

---------------- (Ce qui suit est omis) ----------------

Décrivez ensuite le traitement suivant à l'écran pour l'authentification Google.

import UIKit
import AppAuth
import GTMAppAuth
import GoogleAPIClientForREST

---------------- (Omission) ----------------

private var authorization: GTMAppAuthFetcherAuthorization?
private let clientID = "xxxxxxxxxxxxxxxxxxxx"
private let reverseClientID = "xxxxxxxxxxxxxxxxxxxx"
typealias showAuthorizationDialogCallBack = ((Error?) -> Void)

private func showAuthorizationDialog(callBack: @escaping showAuthorizationDialogCallBack) {
    let scopes = ["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly","https://www.googleapis.com/auth/calendar.events","https://www.googleapis.com/auth/calendar.events.readonly"]
        
    let configuration = GTMAppAuthFetcherAuthorization.configurationForGoogle()
    let redirectURL = URL.init(string: reverseClientID + ":/oauthredirect")
        
    let request = OIDAuthorizationRequest.init(configuration: configuration,
                                                   clientId: clientID,
                                                   scopes: scopes,
                                                   redirectURL: redirectURL!,
                                                   responseType: OIDResponseTypeCode,
                                                   additionalParameters: nil)
        
    let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
    appDelegate.currentAuthorizationFlow = OIDAuthState.authState(
        byPresenting: request,
        presenting: self,
        callback: { (authState, error) in
            if let error = error {
                NSLog("\(error)")
            } else {
                if let authState = authState {
                    self.authorization = GTMAppAuthFetcherAuthorization.init(authState: authState)
                    GTMAppAuthFetcherAuthorization.save(self.authorization!, toKeychainForName: "authorization")
                }
            }
            callBack(error)
    })
}

Les variables suivantes décrivent l'ID obtenu lors de l'obtention de l'ID client OAuth. Entrez l'ID client OAuth 2.0 dans clientID et l'ID client inversé dans reverseClientID.

private let clientID = "xxxxxxxxxxxxxxxxxxxx"
private let reverseClientID = "xxxxxxxxxxxxxxxxxxxx"

Définissez les autorisations requises cette fois dans les étendues de tableau. Cette fois, nous demandons à l'autorité de rechercher et de modifier le calendrier Google.

let scopes = ["https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly","https://www.googleapis.com/auth/calendar.events","https://www.googleapis.com/auth/calendar.events.readonly"]

Lorsque la méthode authState de la classe OIDAuthState est exécutée, la boîte de dialogue d'authentification Google suivante s'affiche. Google認証ダイアログ Si l'utilisateur entre correctement l'adresse gmail et le mot de passe dans la boîte de dialogue et que l'authentification est terminée, la fonction Callback de la méthode authState génère et enregistre la classe GTMAppAuthFetcherAuthorization. Il n'est pas nécessaire de réafficher la boîte de dialogue d'authentification tant que cette classe GTMAppAuthFetcherAuthorization reste.

Rechercher des événements

Ensuite, je voudrais accéder à Google Agenda à l'aide de GoogleAPIClientForREST. Tout d'abord, je décrirai le processus d'obtention d'un événement existant à partir de Google Agenda. Si vous transmettez la date et l'heure de début et la date et l'heure de fin à la méthode get, il s'agit d'un programme qui recherche dans le calendrier Google des événements entre la date et l'heure de début et la date et l'heure de fin.

import UIKit
import AppAuth
import GTMAppAuth
import GoogleAPIClientForREST

---------------- (Omission) ----------------

private var authorization: GTMAppAuthFetcherAuthorization?
private let clientID = "xxxxxxxxxxxxxxxxxxxx"
private let reverseClientID = "xxxxxxxxxxxxxxxxxxxx"
typealias showAuthorizationDialogCallBack = ((Error?) -> Void)
struct GoogleCalendaraEvent {
    var id: String
    var name: String
    var startDate: Date?
    var endDate: Date?
}
private var googleCalendarEventList: [GoogleCalendaraEvent] = []

private func showAuthorizationDialog(callBack: @escaping showAuthorizationDialogCallBack) {
---------------- (Omission) ----------------
}

private func get(startDateTime: Date, endDateTime: Date) {
    if GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization") != nil {
        self.authorization = GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization")!
    }
        
    if self.authorization == nil {
        showAuthorizationDialog(callBack: {(error) -> Void in
            if error == nil {
                self.getCalendarEvents(startDateTime: startDateTime, endDateTime: endDateTime)
            }
        })
    } else {
        self.getCalendarEvents(startDateTime: startDateTime, endDateTime: endDateTime)
    }
}
    
private func getCalendarEvents(startDateTime: Date, endDateTime: Date) {
    let calendarService = GTLRCalendarService()
    calendarService.authorizer = self.authorization
    calendarService.shouldFetchNextPages = true
        
    let query = GTLRCalendarQuery_EventsList.query(withCalendarId: "primary")
    query.timeMin = GTLRDateTime(date: startDateTime)
    query.timeMax = GTLRDateTime(date: endDateTime)
        
    calendarService.executeQuery(query, completionHandler: { (ticket, event, error) -> Void in
        if let error = error {
            NSLog("\(error)")
        } else {
            if let event = event as? GTLRCalendar_Events, let items = event.items {
                self.googleCalendarEventList.removeAll()
                for item in items {
                    let id: String = item.identifier ?? ""
                    let name: String = item.summary ?? ""
                    let startDate: Date? = item.start?.dateTime?.date
                    let endDate: Date? = item.end?.dateTime?.date
                    self.googleCalendarEventList.append(GoogleCalendaraEvent(id: id, name: name, startDate: startDate, endDate: endDate))
                }
            }
        }
    })
}

Tout d'abord, vérifiez si l'authentification Google est terminée. Vérifiez si la classe GTMAppAuthFetcherAuthorization est enregistrée, et si elle n'est pas enregistrée, appelez la fonction showAuthorizationDialog créée précédemment pour afficher la boîte de dialogue d'authentification Google et obtenir la classe GTMAppAuthFetcherAuthorization. Si la classe GTMAppAuthFetcherAuthorization a été enregistrée, utilisez-la telle quelle.

Ensuite, utilisez GoogleAPIClientForREST pour obtenir l'événement à partir du calendrier Googl. Tout d'abord, générez une classe GTLRCalendarService pour accéder au calendrier Goole et définissez la classe GTMAppAuthFetcherAuthorization dans la propriété d'autorisation.

let calendarService = GTLRCalendarService()
calendarService.authorizer = self.authorization
calendarService.shouldFetchNextPages = true

Ensuite, générez la classe GTLRCalendarQuery_EventsList pour rechercher des événements dans Google Agenda et définissez la date et l'heure de début et la date et l'heure de fin comme conditions de recherche.

let query = GTLRCalendarQuery_EventsList.query(withCalendarId: "primary")
query.timeMin = GTLRDateTime(date: startDateTime)
query.timeMax = GTLRDateTime(date: endDateTime)

Ensuite, prenez cette classe GTLRCalendarQuery_EventsList comme argument et exécutez la méthode executeQuery de la classe GTLRCalendarService pour obtenir l'événement à partir de Google Calendar. Lorsque l'événement peut être acquis, la classe GTLRCalendar_Events est renvoyée par la fonction Callback de la méthode executeQuery, de sorte que les informations d'événement sont acquises à partir d'ici.

if let event = event as? GTLRCalendar_Events, let items = event.items {
    self.googleCalendarEventList.removeAll()
    for item in items {
        let id: String = item.identifier ?? ""
        let name: String = item.summary ?? ""
        let startDate: Date? = item.start?.dateTime?.date
        let endDate: Date? = item.end?.dateTime?.date
        self.googleCalendarEventList.append(GoogleCalendaraEvent(id: id, name: name, startDate: startDate, endDate: endDate))
    }
}

L'identifiant (ID unique de l'événement) est particulièrement important. Cet identifiant est la clé lors de la modification ou de la suppression d'événements.

Ajouter un évènement

Ensuite, je souhaite ajouter un événement à Google Agenda. C'est un programme qui crée un événement dans Google Agenda en transmettant le nom de l'événement, la date et l'heure de début et la date et l'heure de fin à la méthode d'ajout.

import UIKit
import AppAuth
import GTMAppAuth
import GoogleAPIClientForREST

---------------- (Omission) ----------------

private var authorization: GTMAppAuthFetcherAuthorization?
typealias showAuthorizationDialogCallBack = ((Error?) -> Void)

private func showAuthorizationDialog(callBack: @escaping showAuthorizationDialogCallBack) {
---------------- (Omission) ----------------
}

private func add(eventName: String, startDateTime: Date, endDateTime: Date) {
        
    if GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization") != nil {
        self.authorization = GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization")!
    }
        
    if self.authorization == nil {
        showAuthorizationDialog(callBack: {(error) -> Void in
            if error == nil {
                self.addCalendarEvent(eventName: eventName, startDateTime: startDateTime, endDateTime: endDateTime)
            }
        })
    } else {
        self.addCalendarEvent(eventName: eventName, startDateTime: startDateTime, endDateTime: endDateTime)
    }
}
    
private func addCalendarEvent(eventName: String, startDateTime: Date, endDateTime: Date) {
        
    let calendarService = GTLRCalendarService()
    calendarService.authorizer = self.authorization
    calendarService.shouldFetchNextPages = true
    
    let event = GTLRCalendar_Event()
    event.summary = eventName
        
    let gtlrDateTimeStart: GTLRDateTime = GTLRDateTime(date: startDateTime)
    let startEventDateTime: GTLRCalendar_EventDateTime = GTLRCalendar_EventDateTime()
    startEventDateTime.dateTime = gtlrDateTimeStart
    event.start = startEventDateTime
        
    let gtlrDateTimeEnd: GTLRDateTime = GTLRDateTime(date: endDateTime)
    let endEventDateTime: GTLRCalendar_EventDateTime = GTLRCalendar_EventDateTime()
    endEventDateTime.dateTime = gtlrDateTimeEnd
    event.end = endEventDateTime

    let query = GTLRCalendarQuery_EventsInsert.query(withObject: event, calendarId: "primary")
    calendarService.executeQuery(query, completionHandler: { (ticket, event, error) -> Void in
        if let error = error {
            NSLog("\(error)")
        }
    })
}

Le processus jusqu'à la génération de la classe GTLRCalendarService est le même que dans le cas de la recherche, nous expliquerons donc à partir de la partie suivante. Générez la classe GTLRCalendar_Event pour définir les informations de l'événement à ajouter. Cette fois, le nom de l'événement, la date et l'heure de début et la date et l'heure de fin sont définis, de sorte que chacun est défini dans la propriété summary, la propriété start et la propriété end de la classe GTLRCalendar_Event.

let event = GTLRCalendar_Event()
event.summary = eventName
        
let gtlrDateTimeStart: GTLRDateTime = GTLRDateTime(date: startDateTime)
let startEventDateTime: GTLRCalendar_EventDateTime = GTLRCalendar_EventDateTime()
startEventDateTime.dateTime = gtlrDateTimeStart
event.start = startEventDateTime
        
let gtlrDateTimeEnd: GTLRDateTime = GTLRDateTime(date: endDateTime)
let endEventDateTime: GTLRCalendar_EventDateTime = GTLRCalendar_EventDateTime()
endEventDateTime.dateTime = gtlrDateTimeEnd
event.end = endEventDateTime

Si vous ajoutez un nouvel identifiant, l'identifiant unique de l'événement sera automatiquement attribué par Google Agenda, vous n'avez donc pas besoin de le définir ici.

Ensuite, générez une classe GTLRCalendarQuery_EventsInsert pour ajouter un nouvel élément au calendrier Google avec la classe GTLRCalendar_Event comme argument, et exécutez la méthode executeQuery de la classe GTLRCalendarService pour ajouter un nouvel événement au calendrier Google.

Événement de changement

Ensuite, modifions les informations de l'événement existant. C'est un programme qui modifie les informations d'événement de l'identifiant correspondant dans le calendrier Google lorsque l'identifiant d'événement, le nom de l'événement, la date et l'heure de début, la date et l'heure de fin sont transmis à la méthode de mise à jour.

import UIKit
import AppAuth
import GTMAppAuth
import GoogleAPIClientForREST

---------------- (Omission) ----------------

private var authorization: GTMAppAuthFetcherAuthorization?
typealias showAuthorizationDialogCallBack = ((Error?) -> Void)

private func showAuthorizationDialog(callBack: @escaping showAuthorizationDialogCallBack) {
---------------- (Omission) ----------------
}

private func update(eventId: String, eventName: String, startDateTime: Date, endDateTime: Date) {
        
    if GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization") != nil {
        self.authorization = GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization")!
    }
        
    if self.authorization == nil {
        showAuthorizationDialog(callBack: {(error) -> Void in
            if error == nil {
                self.updateCalendarEvent(eventId: eventId, eventName: eventName, startDateTime: startDateTime, endDateTime: endDateTime)
            }
        })
    } else {
        self.updateCalendarEvent(eventId: eventId, eventName: eventName, startDateTime: startDateTime, endDateTime: endDateTime)
    }
}
    
private func updateCalendarEvent(eventId: String, eventName: String, startDateTime: Date, endDateTime: Date) {
    let calendarService = GTLRCalendarService()
    calendarService.authorizer = self.authorization
    calendarService.shouldFetchNextPages = true
        
    let event = GTLRCalendar_Event()
    event.identifier = eventId
    event.summary = eventName
        
    let gtlrDateTimeStart: GTLRDateTime = GTLRDateTime(date: startDateTime)
    let startEventDateTime: GTLRCalendar_EventDateTime = GTLRCalendar_EventDateTime()
    startEventDateTime.dateTime = gtlrDateTimeStart
    event.start = startEventDateTime
        
    let gtlrDateTimeEnd: GTLRDateTime = GTLRDateTime(date: endDateTime)
    let endEventDateTime: GTLRCalendar_EventDateTime = GTLRCalendar_EventDateTime()
    endEventDateTime.dateTime = gtlrDateTimeEnd
    event.end = endEventDateTime

    let query = GTLRCalendarQuery_EventsUpdate.query(withObject: event, calendarId: "primary", eventId: eventId)
    calendarService.executeQuery(query, completionHandler: { (ticket, event, error) -> Void in
        if let error = error {
            NSLog("\(error)")
        }
    })
}

Pour les mises à jour, définissez l'ID de l'événement dans la propriété identifier de la classe GTLRCalendar_Event. Définissez ensuite la valeur que vous souhaitez modifier en propriété de la classe GTLRCalendar_Event. Après cela, générez une classe GTLRCalendarQuery_EventsUpdate pour mettre à jour les événements de Google Agenda avec la classe GTLRCalendar_Event comme argument, et exécutez la méthode executeQuery de la classe GTLRCalendarService avec cela comme argument.

Supprimer l'événement

Enfin, supprimez l'événement dans Google Agenda. C'est un programme qui supprime l'événement correspondant du calendrier Google lorsque l'identifiant de l'événement est passé à la méthode de suppression.

import UIKit
import AppAuth
import GTMAppAuth
import GoogleAPIClientForREST

---------------- (Omission) ----------------

private var authorization: GTMAppAuthFetcherAuthorization?
typealias showAuthorizationDialogCallBack = ((Error?) -> Void)

private func showAuthorizationDialog(callBack: @escaping showAuthorizationDialogCallBack) {
---------------- (Omission) ----------------
}

private func delete(eventId: String) {
        
    if GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization") != nil {
        self.authorization = GTMAppAuthFetcherAuthorization(fromKeychainForName: "authorization")!
    }
        
    if self.authorization == nil {
        showAuthorizationDialog(callBack: {(error) -> Void in
            if error == nil {
                self.deleteCalendarEvent(eventId: eventId)
            }
        })
    } else {
        self.deleteCalendarEvent(eventId: eventId)
    }
}
    
private func deleteCalendarEvent(eventId: String) {
    let calendarService = GTLRCalendarService()
    calendarService.authorizer = self.authorization
    calendarService.shouldFetchNextPages = true
        
    let query = GTLRCalendarQuery_EventsDelete.query(withCalendarId: "primary", eventId: eventId)
    calendarService.executeQuery(query, completionHandler: { (ticket, event, error) -> Void in
        if let error = error {
            NSLog("\(error)")
        }
    })
}

La suppression peut être effectuée en générant la classe GTLRCalendarQuery_EventsDelete avec l'identificateur d'événement comme argument et en exécutant la méthode executeQuery de GTLRCalendarService avec cela comme argument.

Exemple de programme

L'exemple de programme créé cette fois-ci est disponible sur GitHub. https://github.com/naosekig/GoogleCalendarSample

Références

CocoaDocs.org - GoogleAPIClientForRest Qiita: j'ai accédé à l'API Google Agenda avec Swift4

Recommended Posts

Accédez à Google Agenda depuis l'application iOS
Importez le calendrier obtenu à partir de "Schedule-kun" dans Google Agenda
Générez des rapports quotidiens à partir de Google Agenda
Comment accéder à la banque de données de l'extérieur
Obtenez des vacances avec l'API Google Agenda
Accédez aux variables définies dans le script depuis REPL
Accédez à Google Agenda depuis l'application iOS
Lire l'article Auto-apprentissage profond à partir d'étiquettes bruyantes
Recevez le dernier rendez-vous de Google Agenda et notifiez-le sur LINE tous les matins
Accéder à bitcoind depuis python