2010-11-18 94 views
3

由于Google任务没有公开API,我想要像浏览器一样编写解决方法和请求数据,然后解析结果以进一步显示。Android:使用OAuth访问Google任务时出现问题

访问数据,我已经实现与谷歌OAuth认证访问此网址: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的阶段,并尝试访问谷歌的任务

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; 
    } 
} 

在这line:

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

我可以看到,我收到“登录页”

我想原因是,谷歌不提供访问该服务,甚至我已经通过OAuth认证它限制了我的这个资源访问(即使我已将范围定义为https://mail.google.com/)。我不知道如何实现它,但它看起来像我需要模拟浏览器究竟如何与谷歌互动(检索和发送适当的coockies)。但我问,因为我不知道如何处理这种情况,因为正如我所提到的谷歌任务API没有公共API(肥皂,休息或任何其他),所以这对我来说并不明显如何为此实现客户端功能...

如果有人有应用程序访问谷歌资源没有公共API的例子,我会很高兴看到这一点。

谢谢,嗨,有人知道答案!

回答

5

[更新5/11推荐的API,4/6正常使用的ClientLogin来代替饼干]

有现在Google Tasks API!相反,使用它会容易得多,并且您的代码将更易于维护。只考虑为子孙后代的其余部分。

不幸的是,你在正确的轨道上。目前还没有用于谷歌任务的API,OAuth或其他,所以你必须做一些HTML抓取。 :/ afaik,这就是客户现在执行的所有其他第三方任务。不过,ClientLogin确实可以用于身份验证,所以至少是这样。

这是一些shell脚本代码,它可以这样做:http://privacylog.blogspot.com/2010/09/updated-google-tasks-api.html。详情如下。

第一个,POST到​​,如http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#Request中所述,以获得认证令牌。使用goanna_mobile作为服务名称。 (这个很重要!)

然后,GET https://mail.google.com/tasks/m并将Authorization:GoogleLogin标头与上面收到的验证令牌一起传递。你会得到HTML回来。提取各个任务列表的ID。他们的形式是04291568652951293844:0:0。

然后,您将发送带有JSON编码体的POST到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中的= =是 URL编码在r%3D
  • 包括标题'AT:1'。没有它任务返回401未经授权。

输出更加JSON,如:

{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 
    }, 
    ... 
+0

是的,现在有一个API ......限于每5000要求除非你愿意付钱。无论是来自您的应用程序的收入都可以支付成本,还是JSON仍然是您的选择。 – RedGlyph 2013-03-19 21:13:24

1

他们确实有,因为几个星期的API现在检查here

相关问题