未配置Google Books API 403访问权限

时间:2014-01-04 20:11:45

标签: android google-api google-api-java-client google-books

我正在尝试联系Google Books API并执行标题搜索,该搜索只需要一个公共API密钥而不需要OAUTH2。我得到的是以下错误:

{
    "error": {
        "errors": [
        {
            "domain": "usageLimits",
            "reason": "accessNotConfigured",
            "message": "Access Not Configured"
        }
        ],
        "code": 403,
        "message": "Access Not Configured"
    }
}

在谷歌搜索了好几个小时之后,似乎很多其他人遇到了同样的问题,但使用其他Google API。到目前为止我做了什么:

  1. 在我的开发者控制台中注册了一个项目
  2. 启用图书API
  3. 签署我的申请以获取SHA1证书编号
  4. 选择在我的开发者控制台中获取Android的公共API密钥
  5. 将以下字符串粘贴到公共API密钥表单中,以获取密钥:“SHA1 number; com.package”,不带引号
  6. 将生成的密钥复制粘贴到我的代码中。
  7. 代码如下:

    private void callGoogleBooks(){
        String key = MY_KEY;
        String query = "https://www.googleapis.com/books/v1/volumes?q=flowers+inauthor:keyes&key=" + key;
        Log.d("google books", callApi(query));
    }
    
    public String callApi(String query){
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet getRequest = new HttpGet(query);
        HttpResponse httpResponse = null;
    
        try{
            httpResponse = httpClient.execute(getRequest);
        } catch(UnsupportedEncodingException e){
            Log.d("ERROR", e.getMessage());
        } catch(ClientProtocolException e){
            Log.d("ERROR", e.getMessage());
        } catch (IOException e){
            Log.d("ERROR", e.getMessage());
        }
    
        if(httpResponse != null){
            try{
                HttpEntity httpEntity = httpResponse.getEntity();
                InputStream is = httpEntity.getContent();
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(is, "utf-8"), 8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while((line = br.readLine()) != null){
                    sb.append(line + "\n");
                }
                is.close();
                String responseString = sb.toString();
                return responseString;
            } catch (Exception e){
                Log.d("ERROR", e.getMessage());
            }
        }
        return null;
    }
    
    • 有没有明显的错误?我需要以不同方式格式化或打包我的请求吗?
    • 我是否需要在清单文件中添加任何内容?
    • 在生成公共API密钥时指定包时,是否需要指定与我的应用程序结构中相同的包名?我在某处读到它必须是唯一的,但将其更改为不太可能是重复的内容会导致相同的错误。

    该错误显然与“usageLimits”有关,但我甚至不接近我测试项目中每天允许的1000次调用的1%。

    我还尝试在不使用上述代码的情况下实现Google Books Java Sample,获取相同的错误消息。我也试过禁用并重新启用Books API,没有任何运气。

    提前致谢。

2 个答案:

答案 0 :(得分:2)

这对我有用

String link = "https://www.googleapis.com/books/v1/volumes?q="+params;
InputStream is = null;
try 
{
    int timeoutConnection = 10000;
    URL url = new URL(link);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setConnectTimeout(timeoutConnection);
    con.setReadTimeout(timeoutConnection);
    con.setRequestProperty("key", "API_KEY");
    if(con.getResponseCode() != HttpURLConnection.HTTP_OK){
        publishProgress("Error conneting.");
    }
    is=con.getInputStream();
}

来自这个帖子:Google Books API for Android - Access Not Configured

答案 1 :(得分:1)

问题是在为Android应用设置API密钥限制时,您指定了包名称和SHA-1证书指纹。因此,您的API密钥仅接受来自您的应用程序的请求,其中包含包名称和SHA-1证书指纹。

那么Google如何知道您的ANDROID APP发送的请求?您必须使用以下键在每个请求的标题中添加您的应用程序包名称和SHA证书:

键:"X-Android-Package",值:您的应用包名称

键:"X-Android-Cert",值:apk的SHA-1证书

首先,获取您的应用SHA签名(您需要Guava库):

/**
 * Gets the SHA1 signature, hex encoded for inclusion with Google Cloud Platform API requests
 *
 * @param packageName Identifies the APK whose signature should be extracted.
 * @return a lowercase, hex-encoded
 */
public static String getSignature(@NonNull PackageManager pm, @NonNull String packageName) {
    try {
        PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
        if (packageInfo == null
                || packageInfo.signatures == null
                || packageInfo.signatures.length == 0
                || packageInfo.signatures[0] == null) {
            return null;
        }
        return signatureDigest(packageInfo.signatures[0]);
    } catch (PackageManager.NameNotFoundException e) {
        return null;
    }
}

private static String signatureDigest(Signature sig) {
    byte[] signature = sig.toByteArray();
    try {
        MessageDigest md = MessageDigest.getInstance("SHA1");
        byte[] digest = md.digest(signature);
        return BaseEncoding.base16().lowerCase().encode(digest);
    } catch (NoSuchAlgorithmException e) {
        return null;
    }
}

然后,将包名称和SHA证书签名添加到请求标头:

java.net.URL url = new URL(REQUEST_URL);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try {
    connection.setDoInput(true);
    connection.setDoOutput(true);

    connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
    connection.setRequestProperty("Accept", "application/json");

    // add package name to request header
    String packageName = mActivity.getPackageName();
    connection.setRequestProperty("X-Android-Package", packageName);
    // add SHA certificate to request header
    String sig = getSignature(mActivity.getPackageManager(), packageName);
    connection.setRequestProperty("X-Android-Cert", sig);
    connection.setRequestMethod("POST");

    // ADD YOUR REQUEST BODY HERE
    // ....................
} catch (Exception e) {
    e.printStackTrace();
} finally {
    connection.disconnect();
}

希望这有帮助! :)