3

I'm trying to contact the Google Books API and perform a title search, which only requires a public API key and no OAUTH2. All I get is the following error:

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

After having googled around for hours, it seems many others have the same problem but with other Google APIs. What I've done so far:

  1. Registered a project in my Developer Console
  2. Enabled the Books API
  3. Signed my application to get the SHA1 certificate number
  4. Chosen to get a public API key for Android in my Developer Console
  5. Pasted the following string into the public API key form, in order to get the key: "SHA1 number;com.package", without quotes
  6. Copy pasted the generated key into my code.

The code looks as follows:

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;
}
  • Are there any obvious errors? Do I need to format or package my request differently?
  • Do I need to add anything to the manifest file?
  • When specifying the package when generating the public API key, do I need to specify the same package name as in my app structure? I read somewhere that it has to be unique, but changing it to something less likely to be a duplication resulted in the same error.

The error apparently has to do with "usageLimits", but I'm not even close to 1% of the 1000 calls allowed per day in my test project.

I've also tried to implement the Google Books Java Sample without using the code above, getting the same error message. I've also tried disabling and re-enabling the Books API, without any luck.

Thanks in advance.

4

2 回答 2

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

来自此线程:适用于 Android 的 Google Books API - 未配置访问

于 2014-06-23T11:51:21.177 回答
1

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

那么谷歌如何知道该请求是从您的 ANDROID 应用程序发送的呢?您必须使用以下键在每个请求的标头中添加您的应用程序包名称和 SHA 证书:

Key: "X-Android-Package", value: 你的应用包名

Key: "X-Android-Cert", value: 你的 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();
}

希望这有帮助!:)

于 2017-03-17T13:52:48.193 回答