Android: проблема с доступом к задачам Google с помощью OAuth - PullRequest
3 голосов
/ 18 ноября 2010

Поскольку у задач Google нет общедоступного API, я хочу написать обходной путь и запросить данные, такие как браузер, а затем проанализировать результаты для дальнейшего отображения.

Для доступа к данным я реализовал аутентификацию OAuth с помощью Google, чтобы получить доступ к этомуurl: https://mail.google.com/

Для OAuth я использовал библиотеку подписи и она хорошо работает.

Проблема в том, что я пытаюсь получить доступ к https://mail.google.com/tasks/ig с подписанным запросомон возвращает мне страницу входа вместо желаемого списка с задачами.

Чтобы быть более конкретным, вот мой код:

public class GoogleOAuthActivity extends Activity {
    private static final String TAG = GoogleOAuthActivity.class.getSimpleName();
    private CommonsHttpOAuthProvider provider;
    private CommonsHttpOAuthConsumer consumer;

    @Override
    @SuppressWarnings("unchecked")
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        provider = new CommonsHttpOAuthProvider(OAuthPrefs.GET_REQUEST_TOKEN_URL, OAuthPrefs.GET_ACCESS_TOKEN_URL,
                OAuthPrefs.TOKEN_AUTHORIZATION_URL);
        consumer = new CommonsHttpOAuthConsumer(OAuthPrefs.CONSUMER_KEY, OAuthPrefs.CONSUMER_SECRET);
        consumer.setMessageSigner(new HmacSha1MessageSigner());

        Log.v(TAG, "Starting google authentication activity");
        new RequestGoogleOAuth(this, provider, consumer).execute();
    }

    @Override
    @SuppressWarnings("unchecked")
    public void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        final Uri uri = intent.getData();
        if (uri != null && uri.getScheme().equals(OAuthPrefs.CALLBACK_SCHEME)) {
            Log.v("OAUTH MAIN", "STARTING STAGE TWO");
            new ConfirmGoogleOAuthTask(this, provider, consumer).execute(uri);
            finish();
        }
    }

}

Первый этап OAuth

public class RequestGoogleOAuth extends OAuthGoogleTask {
    public static final String TAG = RequestGoogleOAuth.class.getSimpleName();

    public RequestGoogleOAuth(Context context, CommonsHttpOAuthProvider provider, CommonsHttpOAuthConsumer consumer) {
        super(context, provider, consumer);
    }

    protected Object doInBackground(Object... params) {
        final String TAG = getClass().getName();
        try {
            final String url = provider.retrieveRequestToken(consumer, OAuthPrefs.CALLBACK_URL);
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
                    & Intent.FLAG_ACTIVITY_NO_HISTORY & Intent.FLAG_FROM_BACKGROUND);
            context.startActivity(intent);
            Log.v(TAG, "Request google authentication");
        } catch (Exception e) {
            Log.e(TAG, "ERROR during google authentication request", e);
        }
        return null;
    }
}

второй этап OAuth и попытка доступа к задачам Google

public class ConfirmGoogleOAuthTask extends OAuthGoogleTask {
    public ConfirmGoogleOAuthTask(Context context, CommonsHttpOAuthProvider provider, CommonsHttpOAuthConsumer consumer) {
        super(context, provider, consumer);
    }

    @Override
    public Object doInBackground(Object... params) {
        final Uri uri = (Uri) params[0];
        final String TAG = getClass().getName();

        final SharedPreferences prefs = context.getSharedPreferences(OAuthPrefs.PREF_NAME, Context.MODE_PRIVATE);
        final String oauthVerifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

        try {
            provider.retrieveAccessToken(consumer, oauthVerifier);
            final Editor edit = prefs.edit();
            edit.putString(OAuth.OAUTH_TOKEN, consumer.getToken());
            edit.putString(OAuth.OAUTH_TOKEN_SECRET, consumer.getTokenSecret());
            edit.commit();

            CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(OAuthPrefs.CONSUMER_KEY, OAuthPrefs.CONSUMER_SECRET);
            consumer.setMessageSigner(new HmacSha1MessageSigner());
            consumer.setTokenWithSecret(consumer.getToken(), consumer.getTokenSecret());

            HttpClient httpClient = HttpUtils.createHttpClient();
            HttpGet httpGet = new HttpGet(consumer.sign("https://mail.google.com/tasks/ig"));
            HttpResponse response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            Log.d(TAG, "Status code = " + statusCode);
            if (statusCode == HttpStatus.SC_OK) {
                String xml = ConvertUtils.convertStreamToString(response.getEntity().getContent(), true);
                Log.d(TAG, "XML = " + xml);
            }

            Log.v(TAG, "Successfully receive access token");
        } catch (Exception e) {
            Log.e(TAG, "ERROR during request for access token", e);
        }
        return null;
    }
}

В этой строке:

String xml = ConvertUtils.convertStreamToString(response.getEntity().getContent(), true);
                    Log.d(TAG, "XML = " + xml);

Я вижу, что я получаю "страницу входа"

Я думаю, чтопричина в том, что Google не предоставляет доступ к этой службе, и даже если я уже прошел проверку подлинности с помощью OAuth, он ограничивает мой доступ к этому ресурсу (даже если я определил область действия как https://mail.google.com/)., я не уверен, как это реализоватьсейчас, но, похоже, я нНужно имитировать браузер точно, как он взаимодействует с Google (получить и отправить соответствующие куки).Но я спрашиваю, потому что я не уверен, как быть в этой ситуации, потому что, как я уже упоминал, API задач Google не имеет публичного API (мыло, отдых или любой другой), поэтому для меня не очевидно, как реализовать клиент для этогоособенность ...

Если у кого-то есть примеры, где приложение получает доступ к ресурсам Google без публичного API, я буду очень рад это увидеть.

Спасибо, надеюсь, кто-нибудь знает ответ!

Ответы [ 2 ]

5 голосов
/ 23 января 2011

[обновлено 5/11, чтобы рекомендовать API, 4/6 использовать обычный ClientLogin вместо файлов cookie]

теперь есть Google Tasks API ! используйте это вместо этого, это намного проще, и ваш код будет более понятным. рассмотреть оставшуюся часть этого ответа только для потомков.

к сожалению, вы на правильном пути. пока еще нет API для задач Google, OAuth или чего-то еще, поэтому вам придется немного разобраться с HTML. : / afaik, это то, что все остальные сторонние задачи клиенты делают прямо сейчас. Однако ClientLogin работает для аутентификации, так что это как минимум.

вот код сценария оболочки, который делает это: http://privacylog.blogspot.com/2010/09/updated-google-tasks-api.html. подробности ниже.

сначала, POST до www.google.com/accounts/ClientLogin, как описано в http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request, чтобы получить токен авторизации. используйте goanna_mobile в качестве имени службы. (это важно!)

затем GET <a href="https://mail.google.com/tasks/m" rel="nofollow">https://mail.google.com/tasks/m</a> и передайте заголовок Authorization:GoogleLogin с токеном авторизации, который вы получили выше. Вы вернете HTML. извлечь идентификаторы из отдельных списков задач. они имеют форму 04291568652951293844: 0: 0.

Затем вы отправите POST с телом в кодировке JSON на https://mail.google.com/tasks/r/d, чтобы получить содержимое каждого списка. Вот пример тела:

r={action_list:
   [{action_type: get_all,
     action_id: 5,
     list_id: 0429158965...:0:0,
     get_deleted: false,
     date_start: 1969-12-31,
     get_archived: true
    }],
   client_version: 1256686
  }

важные заметки:

  • latest_sync_point: 0, чтобы получить все задачи
  • = в r = is not url, закодированный в r% 3D
  • включает заголовок «AT: 1». без этого задачи возвращает 401 несанкционированных.

вывод больше в формате JSON, например ::1010*

{latest_sync_point: 1263000002293000, response_time:1263077227, results:[], tasks:
  [{id: 04291589652955....:0:38,
    last_modified: 1263000002281,
    name: foo bar
    notes: ,
    type: TASK,
    deleted: false,
    list_id: [0429158965...:0:0],
    completed: false
   },
   {id: 0429158965295...:0:37,
    last_modified: 1262929947949,
    name: baz
    notes: ,
    type: TASK,
    deleted:false,
    list_id: [0429158965295...:0:0],
    completed: false
   },
   ...
1 голос
/ 07 июня 2011

У них есть API уже несколько недель. Проверьте здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...