На данный момент у Embarcadero действует акция, которую можно назвать примерно так: «Купи RAD Studio XE4 и получи новых компонентов и программ на 300$«. В числе прочего, по этой акции разработчик получает в свое распоряжение новый пакет компонентов от TMS Software — TMS Cloud 2.0…правда исключительно под работу в FMX, но тем не менее.
Так как в последние несколько лет основная моя работа в Delphi так или иначе связана с различными онлайн-сервисами, облаками, календарями и т.д., то TMS Cloud, конечно, я решил попробовать в действии, оценить их удобство, скорость и качество работы и т.д. Всяко лучше купить за 150 евро готовую пачку компонентов для работы с онлайн-сервисами на любой вкус и цвет, чем дубасить код под каждый сервис по нескольку недель, а потом долго и упорно его отлаживать. И всё, что удастся проверить, оценить я буду выкладывать в блоге для Вашего ознакомления. Сегодня я буду рассматривать работу с компонентом, предназначенными для работы с Google Calendar. Именно с этого сервиса начиналось когда-то мое знакомство с Google API вообще.
Состав пакета TMS Cloud
После установки Вам становятся доступны 36 компонентов для доступа и работы с различными онлайн-сервисами, в том числе:
- Google Calendar
- Google Contacts
- Google URLShortner
- Google Drive
- Dropbox
- SkyDrive
- Picasa
- Windows Live
- iCloud и т.д.
В общем, довольно внушительный список поддерживаемых сервисов. На первый взгляд, этого пакета компонентов должно быть достаточно, чтобы реализовать поддержку практически любого из более менее известный онлайн-сервисов. Посмотрим, что мы можем сделать, используя эти компоненты. Начнем с сервисов от Google.
Несколько общих моментов по использованию TMS Cloud при работе с Google
Прежде, чем начнем работать непосредственно с компонентами, стоит уделить немного внимания тому, как организована работа с сервисами от Google в TMS Cloud.
Во-первых, т.к. в настоящее время Google активно «пересаживает» всех разработчиков с интерфейса ClienLogin для авторизации на более продвинутый OAuth 2.0. (и вместе с этим по-тихоньку монетизирует свои API), то компоненты от TMS Software используют для авторизации пользователя именно OAuth 2.0. Так что, если хотите использовать TMS Cloud, то так или иначе Вам придётся изучить несколько мануалов по OAuth 2.0. Ну или прочитать пост «Google API в Delphi. OAuth для Delphi-приложений» в моем блоге, чтобы иметь хотя бы небольшое представление об OAuth 2.0 от Google.
Во-вторых, чтобы сервер Google Вас не разочаровывал всякими ошибками типа «Доступ запрещен» при попытке авторизации, не забудьте в Google-консоли включить соответствующие API. Делается это элементарно:
- Заходим в консоль
- Переходим на страницы «Services» и напротив каждого из необходимых нам API ставим переключатель в значение «On»
Например, «включенный» Calendar API у Вас будет выглядеть следующим образом:
В-третьих, т.к. все компоненты для Google используют OAuth 2.0., то у компонентов будут повторяться некоторые свойства и, чтобы каждый раз про них не рассказывать заново, я их просто приведу ниже.
App: TCloudApp
Настройки приложения для API. В этот набор свойств входят следующие:
Key: string;//ClientID Вашего приложения Name: string;//название Вашего приложения Secret: string;//Client Secret Вашего приложения
Значения всех трех свойств можно найти на странице «API Access» в Консоли Google.
AuthBrowser: TWebBrowser;
Веб-браузер в котором будет отображаться страничка с просьбой предоставить пользователю доступ к своему аккаунту.
AuthFormSettings: TAuthFormSettings
Настройки формы авторизации. В эту группу входят следующие свойства:
Caption: string;//заголовок окна авторизации Height: integer;//высота окна авторизации Width: integer;//ширина окна авторизации
PersistTokens:TPersistTokens
Настройки хранения ключей доступа (доступно хранение в реестре и INI-файле)
Scopes: TStrings
Точки доступа к API
Теперь можно приступать непосредственно к работе с компонентами. Ну и, раз уж выше показан пример подключения Calendar API, то с соответствующего компонента и начнем.
Работа с Google Calendar
Создадим небольшое тестовое приложение, в котором попробуем реализовать следующие функции:
- Чтение списка календарей и работа с календарями (создание/редактирование/удаление)
- Чтение событий в определенном календаре
- Работа с событиями календаря (редактирование/удаление/создание)
В принципе, уже этих трех функций будет достаточно, чтобы впоследствии собрать простенькое, но уже не тестовое приложение для работы с Google Calendar.
Работа с календарями
Для начала, бросим на главную форму приложения компонент TAdvGCalendar, зададим необходимые значения для свойства App, и бросим на форму 2 TComboBox, 2 TLabel и кнопку (TButton) как показано на рисунке:
Теперь напишем такой обработчик OnClick кнопки:
procedure TForm5.Button1Click(Sender: TObject); begin AdvGCalendar1.DoAuth; end;
Этим самым мы запустим процесс авторизации пользователя. Теперь посмотрим на события компонента TAdvGCalendar.
OnReceivedAccessToken: TNotifyEvent
Это событие вызывается каждый раз при получении нового токена доступа к API.
OnAuthFormClose: TNotifyEvent
Вызывается в случае, если была произведена попытка закрыть окно авторизации.
OnAccessDenied: TNotifyEvent
Вызывается в том случае, если была произведена попытка выполнить метод API доступ к которому не был получен при авторизации. Например, это событие сработает, если мы запросим доступ только на чтение списка календарей и событий и попытаемся создать новый календарь в аккаунте пользователя. Или попытаемся выполнить метод API, используя при этом недействительный ключ доступа (токен).
Напишем такой обработки события OnReceivedAccessToken:
procedure TForm5.AdvGCalendar1ReceivedAccessToken(Sender: TObject); var I: Integer; begin lbToken.Caption:=AdvGCalendar1.TokensAsString; AdvGCalendar1.GetCalendars; cbCalendars.Items.Clear; for I := 0 to AdvGCalendar1.Calendars.Count-1 do cbCalendars.Items.Add(AdvGCalendar1.Calendars[i].Summary); end;
Здесь мы вызываем метод GetCalendars компонента AdvGCalendar1 и загружаем список календарей из аккаунта пользователя. После чего заполняем список cbCalendars:TComboBox названиями календарей.
Все календари хранятся в свойстве-коллекции:
Calendars: TGCalendars
Посмотрим какие свойства календарей нам доступны для работы. Всё, что у нас есть из свойств календаря Google — это:
ID: string
Идентификатор календаря
Summary: string
Название календаря
Description: string
Описание календаря.
Не густо. А как узнать, кто владелец Календаря? Как узнать цвет метки календаря в аккаунте? Где информация о том, что Календарь скрыт или, наоборот, выделен в списке календарей в аккаунте? В общем, скажу прямо — возможности по работе с объектом календаря в компонентах TMS Cloud весьма и весьма ограниченные. Более того, используя компонент, почему-то невозможно ни создать ни отредактировать календарь — нет таких методов. Добавление, редактирование и удаление элементов коллекции Calendars ни к чему не привело — список календарей аккаунта так и остался без изменений. Раз так, то двигаемся далее — попробуем поработать с событиями
Работа с событиями календаря
Начнем снова с загрузки. Пишем обработчик OnChange у cbCalendars:
procedure TForm5.cbCalendarsChange(Sender: TObject); var I: Integer; begin AdvGCalendar1.GetCalendar(AdvGCalendar1.Calendars[cbCalendars.ItemIndex].ID,999999); cbEvents.Items.Clear; for I := 0 to AdvGCalendar1.Items.Count-1 do cbEvents.Items.Add(AdvGCalendar1.Items[i].Summary); end;
Здесь мы используем метод GetCalendar для загрузки событий из определенного календаря. Этот метод может вызываться со следующими параметрами:
GetCalendar(ID: string; FromDate, ToDate: TDate); overload; GetCalendar(FromDate, ToDate: TDate); overload; GetCalendar(ID: string); overload;
где ID — это идентификатор нужного нам календаря. Посмотрим на свойства объекта событий календаря, которые нам доступны:
ID: string; //идентификатор события. ETag: string; //ETag события. CalendarID: string; //идентификатор календаря в котором находится событие. Summary: string; //Название события Description: string;//Описание календаря. StartTime: TDateTime;//Время начала события EndTime: TDateTime; //время окончания события IsAllDay: Boolean;//True если событие длиться весь день Location: string;//Место события Visibility: TVisbility; //"Видимость события". Может принимать одно из значений (viDefault, viPrivate, viPublic) Recurrence: string; //Содержит строку правил для повторяющегося события RecurringID: string; //идентификатор родительского события, если текущее событие является одним из элементов цепочки повторяющегося события Sequence: integer;//Содержит количество изменение события Attendees: TGAttendees; //список участников события Summary: string; //имя участника Email: string; //email участника Status: TResponseStatus; //статус участника
Здесь уже информации по-больше. Хотя опять же непонятно, почему не стали делать поддержку напоминаний о событии, хотя бы по Email — в API реализован воплне удобный объект для этого и парситься он легче легкого хоть из XML, хоть из JSON. Ладно, о достоинствах и недостатках компонента с моей точки зрения Вы прочтете чуть ниже, а пока попробуем выполнить операции создания, реадактирования и удаления событий.
Для начала попробуем создать новое событие. Для этого нам понадобиться в приложении новая форма, на которую необходимо поместить компоненты как показано на рисунке:
Теперь в uses модуля новой формы подключаем следующие модуль TMS Cloud Pack: CloudGoogle, CloudGCalendar, а также модуль главной формы.
Теперь на событие OnShow формы пишем такой обработчик:
procedure TfNewEvent.FormShow(Sender: TObject); begin cbCalendar.Items.Clear; cbCalendar.Items.Assign(fmain.cbCalendars.Items); end;
А на OnClick кнопки такой:
procedure TfNewEvent.btnCreateEventClick(Sender: TObject); var Event: TGCalendarItem; begin Event:=TGCalendarItem.Create(fmain.AdvGCalendar1.Items); Event.CalendarID:=fmain.AdvGCalendar1.Calendars[cbCalendar.ItemIndex].ID; Event.Summary:=edName.Text; Event.Location:=edLocation.Text; Event.IsAllDay:=cbAllDay.Checked; if not Event.IsAllDay then begin Event.StartTime:=Int(dtStartDate.Date)+Frac(dtStartTime.Time); Event.EndTime:=Int(dtEndDate.Date)+Frac(dtEndTime.Time); end; fmain.AdvGCalendar1.Add(Event); end;
Теперь возвращаемся в модуль главной формы, бросаем на форму еще одну кнопку клик по которой будет вызывать только что созданную формочку, т.е. обработчик у кнопки будет выглядеть так:
procedure Tfmain.Button2Click(Sender: TObject); begin fNewEvent.ShowModal end;
Теперь попробуем запустить приложение и создать какое-нибудь событие. Если у нового события свойство
IsAllDay = True
то никаких проблем нет. Однако, попробуем создать событие с определенной датой/временем. Например, я задал следующее время начала и окончания события:StartTime = 19.06.2013 21:45
EndTime = 19.06.2013 22:45
Смотрим, что получается в Календаре:
Почему при создании события не учитывается часовой пояс? API прекрасно выдает информацию не только по часовому поясу для календаря, но и по часовому поясу каждого из событий.
Соответственно раз такая проблема (с датой/временем) выявилась на создании события, то этаже проблема вылезет наружу и при каждом редактировании события. Ну, а удаление события делается довольно просто:
fmain.AdvGCalendar1.Delete(Event);
С этим методом никаких проблем обнаружено не было (да там, собственно, и негде особенно ошибаться).
Подведем небольшой итог по компоненту.
Достоинства компонента:
- Очень простой процесс авторизации (это же достоинство будет, видимо, присутствовать и у всех остальных компонентов из пакета)
- Удобные и простые методы работы с событиями.
Недостатки:
- Нет поддержки цветов в календарях.
- Невозможно управлять списком календарей (удалять, редактировать, удалять календари)
- Неправильная работа (а точнее её отсутствие) с часовыми поясами.
- Реализованы далеко не все возможности API
- Невозможно получить информацию о владельце календаря
- Нет поддержки создания напоминаний для событий
Если пройтись по всему API Google Calendar, то список недостатков можно понавыписывать ещё на пунктов …дцать. Я лишь поясню немного почему я выделил именно эти пять недостатков.
Работа с цветами. Это, конечно, не такой уж и серьезный недостаток — не каждому как и мне необходимо делать полную поддержку API, в т.ч. и смену цветов календарей на клиенте и синхронизацию цветов в событиях и т.д. И вполне возможно, что разработчики компонента сильно не «заморачивались» над цветами, решив что «и так сойдет». Но дело в том, что компонент (к гадалке не ходи) использует последнюю версию API и там считать цвет календаря не просто, а ЭЛЕМЕНТАРНО. Достаточно в парсинге JSON считать одно единственное значение. Так почему бы не реализовать эту возможность.
Управление календарями. Тут вообще крайне странно. Ведь при работе с календарями используются абсолютно те же HTTP-запросы. А собрать JSON-объект с описанием календаря на порядок проще, чем с описанием события. Забыли? Решили, что разработчик никогда в жизни не захочет создавать календари с помощью своего клиента? Короче, странно и немного обидно, что компонент не поддерживает таких функций.
Работа с часовыми поясами. Без комментариев. Если мне придётся заморачиваться над тем, чтобы переводить свое местное время в UTC и ручками записывать это значение в свойство компонента только и исключительно лишь потому, что разработчики TMS Cloud поленились/забыли/решили не делать (нужно подчеркнуть) полноценную поддержку свойства TimeZone (а это свойство передается в JSON-объекта от сервера), то сорри, мне такого счастья за 200+$ не требуется. Собрать отправку/получение строки с JSON по Сети, пусть даже и с поддержкой авторизации по OAuth 2.0 можно и за бесплатно.
Возможности API.Берем на вскидку — метод GetCalendars (получение списка календарей). API позволяет запросить, например, только видимые в аккаунте календари или календари владельцем которых я являюсь. Сделать это в Delphi опять же очень просто — добавить в URL один параметр и все будет работать прекрасно. В компоненте же мы берем либо все сразу, либо ничего.
Вот пример запроса, который делается компонентом:
GET https://www.googleapis.com/calendar/v3/users/me/calendarList
А вот как сделать, чтобы присылались только те календари, владельцем которых я являюсь:
GET https://www.googleapis.com/calendar/v3/users/me/calendarList?minAccessRole=owner
Так трудно было добавить? И сразу бы убрали следующую проблему.
Владельцы календаря. На первый взгляд этот недостаток можно посчитать незначительным, но на самом деле отсутствие возможности узнать кто владелец календаря может привести к проблемам в работе программы. Например, ваша программа может ни с того ни с сего отказаться добавлять в какой-либо календарь событие. Или наоборот — удалять. Эти проблемы можно отлавливать при работе компонента, но опять же, зачем ловить что-то, когда компонент может реализовать эту возможность? API это позволяет сделать и сделать отлично — читаем свойство AccessRole и всё — одна операция чтения одной строки! Календари владельцем которых я не являюсь должны либо вообще не читаться компонентом, либо я обязан 100% знать кто владелец.
Напоминалки. Недостаток из той же оперы, что и поддержка владельцев, цветов и т.д. Если заявлена работа с событиями, то уж базовые-то возможности должны поддерживаться. Уж пофиг на всякие там расшаривания календарей с другими пользователями или получение информации по всяким там гаджетам в календаре — это дело специфическое и не каждому разработчику Delphi нужно, но напоминалки-то сделать можно было…
В общем конечный мой вывод по компоненту таков — я бы не рекомендовал его использовать для серьезной работы с Календарями Google. Сложилось впечатление, что делали компонент второпях, на скорую руку и лишь бы что-то было.
Надеюсь, что следующий компонент для работы с Google API, который я буду рассматривать, окажется более качественным.
Книжная полка
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
|
||
Название: О чем не пишут в книгах по Delphi
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
|
[…] предыдущей части обзора компонентов TMS Cloud Pack я рассматривал работу с Google Calendar […]