Доступ к Google Drive API через Cordova

3 апреля, 2016
2 минут(ы) чтения

С Cordova трудно работать. Особенно когда используешь с ней сторонние web-сервисы. Так и теперь, типичный парсер использующий Google Spreadsheet занял у меня почти 2 недели.

Обо всём этом по-порядку.

При разработке решил хранить и модифицировать клиентские данные в одной совместной таблице на Spreadsheet. Короче, сделать выгрузку в CSV легко не получилось, поэтому заюзал Apps Script. С ним можно взаимодействовать со многими Google сервисами по REST-API. Apps Script, в целом, мне не понравился. Такая древняя технология, основанная на EcmaScript 3, с простеньким веб-редактором, дебаггером, версионностью и легкой интеграцией с консолью Google.

Google Console

Правильные шаги получения результата из Apps Script такие:

  1. Загрузить gapi либу;
  2. Показать окно с авторизацией;
  3. Ввести логин+пароль и получить токен;
  4. Использовать токен для доступа к данным.

Успешно оттестировав на браузере при портировании под Cordova получил ошибку:

Refused to display... бла-бла-бла ...in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

Оказалось gapi не работает с cordova. Путем долгого чтения док и стэковерфлоу все же нашел решение. Его листинг приложил ниже:

function googleOAuth(CLIENT_ID, SCOPES) {
  return new Promise((resolve, reject) => {
    if (!window.cordova) {
      window.gapi.auth.authorize({
        client_id: CLIENT_ID,
        scope: SCOPES,
        response_type: ‘token’,
        immediate: false
      }, (authResult) => {
        resolve(authResult);
      });
    } else {
      if (window.cordova.InAppBrowser) {
        const redirect_uri = ‘http://localhost/callback’;
        const browserRef = window.cordova.InAppBrowser.open(
          `https://accounts.google.com/o/oauth2/auth?client_id=${CLIENT_ID}` +
          `&redirect_uri=${redirect_uri}` +
          `&scope=${SCOPES.join(‘ ‘)}` +
          ‘&approval_prompt=force’ +
          ‘&response_type=token id_token’,
          ‘_blank’,
          ‘location=no,clearsessioncache=yes,clearcache=yes’
        );
        browserRef.addEventListener(‘loadstart’, (event) => {
          if ((event.url).indexOf(redirect_uri) === 0) {
            browserRef.removeEventListener(‘exit’, () => {
            });
            browserRef.close();
            let callbackResponse = (event.url).split(‘#’)[1];
            let responseParameters = (callbackResponse).split(‘&’);
            let parameterMap = [];
            for (let i = 0; i < responseParameters.length; i++) {
              parameterMap[responseParameters[i].split(‘=’)[0]] = responseParameters[i].split(‘=’)[1];
            }
            if (parameterMap.access_token !== undefined && parameterMap.access_token !== null) {
              resolve({
                access_token: parameterMap.access_token,
                expires_in: parameterMap.expires_in,
                id_token: parameterMap.id_token,
                token_type: parameterMap.token_type
              });
            } else {
              reject(‘Problem authenticating’);
            }
          }
        });
        browserRef.addEventListener(‘exit’, () => {
          reject(‘The sign in flow was canceled’);
        });
      } else {
        reject(‘Could not find InAppBrowser plugin’);
      }
    }
  });
}

Залив очередной билд на девайс получил уже другую ошибку. Теперь попросту не открывалось окно авторизации. Приложение ругалось на запросы через file:///
Пофиксил это установив плагин InAppBrowser.

Далее окно авторизации уже стало работать. Но с ошибкой. Не нравился мой callback-запрос.
В консоле убрал последний слэш в запросе http://localhost/callback

Далее приложение ругалось на невозможность выполнения запросов. Пофиксил это, установив плагин whitelist и добавил в config.xml следующее содержимое:

<access origin="*" launch-external="yes" />
<allow-navigation href="https://ssl.gstatic.com/*" />
<allow-navigation href="https://apis.google.com/*" />
<allow-navigation href="https://*.googleusercontent.com/*" />
<allow-navigation href="https://accounts.google.com/*" />
<allow-navigation href="https://www.googleapis.com/*" />
<allow-navigation href="https://*.googleapis.com/*" />
<allow-intent href="*" />
<allow-intent href="https://*.googleapis.com/*" />
<allow-intent href="https://apis.google.com/*" />

На всякий случай добавил вот такую мету в index.html, дабы не ругалось на безопасность:

<meta http-equiv="Content-Security-Policy"
content="default-src ; img-src 'self' data: blob: filesystem:; script-src 'self' 'unsafe-inline' 'unsafe-eval' ; style-src 'self' 'unsafe-inline' *">

Короче говоря, пока занимался такой вот тривиальной задачей так устал, что думал вообще останавливать запил игрули. Но спустя две недели я получил необходимый массив значений на девайсе. Но вот, честно сказать, никакой радости от этого я уже не испытываю.

Либу cordova-google-oauth2 выложил с лицензией MIT.

Денис Сергеевич Басковский

Философ, изобретатель и поэт.

Добавить комментарий Отменить ответ

массив удаление элемента
Предыдущая статья

Как удалить пустые элементы из массива

polymer starter kit
Следующая статья

Сборка Polymer Starter Kit

Exit mobile version