1

我正在尝试在不使用 Google 客户端库的情况下连接到 Google 任务。以下代码返回 403 禁止错误。只是不确定我错过了什么。任何指导将不胜感激。

try {
                Bundle options = new Bundle();
                AccountManager manager = (AccountManager) getSystemService(ACCOUNT_SERVICE);
                Account[] list = manager.getAccountsByType("com.google");
                Account acct = list[0];
                manager.invalidateAuthToken("com.google", null);
                AccountManagerFuture<Bundle> acc = manager.getAuthToken(
                        acct,
                        "oauth2:https://www.googleapis.com/auth/tasks",
                        options, true, null, null);

                Bundle bundle = acc.getResult();
                String token = bundle
                        .getString(AccountManager.KEY_AUTHTOKEN);
                Log.i("Token: ", token); // token does have value

                String url = "https://www.googleapis.com/tasks/v1/users/@me/lists?key=long_winded_api_key_from_console_here";
                HttpGet getRequest = new HttpGet(url);
                getRequest.addHeader("client_id",
                        "clientID_from_console_here.apps.googleusercontent.com");
                getRequest.addHeader("Authorization", "OAuth " + token);

                HttpClient httpclient = new DefaultHttpClient();

                String responseBody = httpclient.execute(getRequest,
                        new BasicResponseHandler()); // exception raised here

                httpclient.execute(getRequest, new BasicResponseHandler());

                Log.i("###", responseBody); // cannot get the response here

            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } // exception raised here
            catch (OperationCanceledException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (AuthenticatorException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
4

2 回答 2

0

以下链接显示了如何开始使用 Android 中的 Google Drive API。它允许用户选择一个帐户,获得他们的同意,然后获取一个凭据对象,该对象可用于通过 Google 客户端库进行 API 访问:

https://developers.google.com/drive/quickstart-android

在您的情况下,您正在尝试使用 Tasks API,但是身份验证部分应该相同:

在第 2 步中,改为启用 Tasks API。

第 4 步展示了如何获取特定范围的访问令牌:

credential = GoogleAccountCredential.usingOAuth2(this, DriveScopes.DRIVE);
startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);

将范围更改为任务 API 范围:https://www.googleapis.com/auth/tasks

然后我会建议使用 Google 客户端库,例如 Drive 示例。

如果出于某种原因您不想使用客户端库,而是更喜欢自己制作 HTTP 请求,那么您想要的授权标头应该如下所示(现在无法测试):

getRequest.addHeader("Authorization", "Bearer " + credential.getToken());
于 2013-05-24T16:41:53.403 回答
0

我不确定这是否是原因,因为您似乎执行了与我相同的步骤,但您可能想尝试使用“管理您的任务”而不是 “oauth2:https ://www.googleapis.com /身份验证/任务。这可能是403的原因。

这是我在没有客户端库的情况下连接的方式。此处提供完整资源: apiTalker

首先我得到访问令牌:

public static final String AUTH_TOKEN_TYPE = "Manage your tasks";

public static String getAuthToken(AccountManager accountManager,
        Account account, String authTokenType, boolean notifyAuthFailure) {

    Log.d(TAG, "getAuthToken");
    String authToken = "";
    try {
        // Might be invalid in the cache
        authToken = accountManager.blockingGetAuthToken(account,
                authTokenType, notifyAuthFailure);
        accountManager.invalidateAuthToken("com.google", authToken);

        authToken = accountManager.blockingGetAuthToken(account,
                authTokenType, notifyAuthFailure);
    }
    catch (OperationCanceledException e) {
    }
    catch (AuthenticatorException e) {
    }
    catch (IOException e) {
    }
    return authToken;
}

连接并列出可用的任务列表:

public static final String BASE_URL = "https://www.googleapis.com/tasks/v1/users/@me/lists";

public static String AuthUrlEnd() {
    return "key=" + Config.GTASKS_API_KEY;
}

public static String AllLists(final String pageToken) {
    String result = BASE_URL + "?";

    if (pageToken != null && !pageToken.isEmpty()) {
        result += "pageToken=" + pageToken + "&";
    }

    result += AuthUrlEnd();
    return result;
}

public String getListOfLists(ArrayList<GoogleTaskList> list)
        throws ClientProtocolException, IOException, JSONException {
    String eTag = "";
    String pageToken = null;
    do {
        HttpGet httpget = new HttpGet(AllLists(pageToken));
        httpget.setHeader("Authorization", "OAuth " + authToken);

        // Log.d(TAG, "request: " + AllLists());
        AndroidHttpClient.modifyRequestToAcceptGzipResponse(httpget);

        try {
            JSONObject jsonResponse = (JSONObject) new JSONTokener(
                    parseResponse(client.execute(httpget))).nextValue();

            // Log.d(TAG, jsonResponse.toString());
            if (jsonResponse.isNull(NEXTPAGETOKEN)) {
                pageToken = null;
            }
            else {
                pageToken = jsonResponse.getString(NEXTPAGETOKEN);
            }
            // No lists
            if (jsonResponse.isNull("items")) {
                break;
            }

            eTag += jsonResponse.getString("etag");

            JSONArray lists = jsonResponse.getJSONArray("items");

            int size = lists.length();
            int i;

            // Lists will not carry etags, must fetch them individually if
            // that
            // is desired
            for (i = 0; i < size; i++) {
                JSONObject jsonList = lists.getJSONObject(i);
                //Log.d("nononsenseapps", jsonList.toString(2));
                list.add(new GoogleTaskList(jsonList, accountName));
            }
        }
        catch (PreconditionException e) {
            // // Can not happen in this case since we don't have any etag!
            // } catch (NotModifiedException e) {
            // // Can not happen in this case since we don't have any etag!
            // }
        }
    } while (pageToken != null);

    return eTag;
}

这是我解析响应的方式:

public static String parseResponse(HttpResponse response)
        throws ClientProtocolException, PreconditionException {
    String page = "";
    BufferedReader in = null;

    Log.d(TAG, "HTTP Response Code: "
            + response.getStatusLine().getStatusCode());

    if (response.getStatusLine().getStatusCode() == 403) {
        // Invalid authtoken
        throw new ClientProtocolException("Status: 403, Invalid authcode");
    }

    else if (response.getStatusLine().getStatusCode() == 412) { //
        /*
         * Precondition failed. Object has been modified on server, can't do
         * update
         */
        throw new PreconditionException(
                "Etags don't match, can not perform update. Resolve the conflict then update without etag");
    }

    /*
     * else if (response.getStatusLine().getStatusCode() == 304) { throw new
     * NotModifiedException(); }
     */
    else if (response.getStatusLine().getStatusCode() == 400) {
        // Warning: can happen for a legitimate case
        // This happens if you try to delete the default list.
        // Resolv it by considering the delete successful. List will still
        // exist on server, but all tasks will be deleted from it.
        // A successful delete returns an empty response.
        // Make a log entry about it anyway though
        Log.d(TAG,
                "Response was 400. Either we deleted the default list in app or did something really bad");
        throw new PreconditionException(
                "Tried to delete default list, undelete it");
    }
    else if (response.getStatusLine().getStatusCode() == 204) {
        // Successful delete of a tasklist. return empty string as that is
        // expected from delete

        Log.d(TAG, "Response was 204: Successful delete");
        return "";
    }
    else {

        try {
            if (response.getEntity() != null) {
                // Only call getContent ONCE
                InputStream content = AndroidHttpClient
                        .getUngzippedContent(response.getEntity());
                if (content != null) {
                    in = new BufferedReader(new InputStreamReader(content));
                    StringBuffer sb = new StringBuffer("");
                    String line = "";
                    String NL = System.getProperty("line.separator");
                    while ((line = in.readLine()) != null) {
                        sb.append(line + NL);
                    }
                    in.close();
                    page = sb.toString();
                    //
                    // System.out.println(page);
                }
            }
        }
        catch (IOException e) {
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    return page;
}
于 2013-09-27T11:23:42.837 回答