Google Книги API 403 Доступ не настроен
Я пытаюсь связаться с API Google Книг и выполнить поиск по названию, для которого требуется только открытый ключ API, а не OAUTH2. Все, что я получаю, это следующая ошибка:
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured"
}
],
"code": 403,
"message": "Access Not Configured"
}
}
Похоже, что после нескольких часов гуглил, у многих других возникает такая же проблема, но с другими API Google. Что я сделал до сих пор:
- Зарегистрировал проект в моей консоли разработчика
- Включил API книг
- Подпись моей заявки на получение номера сертификата SHA1
- Выбран, чтобы получить открытый ключ API для Android в моей консоли разработчика
- Вставьте следующую строку в форму ключа открытого API, чтобы получить ключ: "номер SHA1;com.package", без кавычек
- Скопируйте вставленный сгенерированный ключ в мой код.
Код выглядит следующим образом:
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 нужно ли указывать то же имя пакета, что и в структуре моего приложения? Я где-то читал, что он должен быть уникальным, но изменение его на что-то менее вероятное дублирование привело к той же ошибке.
Ошибка, по-видимому, связана с "useLimits", но я даже не приблизился к 1% из 1000 вызовов, разрешенных в день в моем тестовом проекте.
Я также пытался реализовать пример Java-книги Google Книги, не используя приведенный выше код, получая то же сообщение об ошибке. Я также безуспешно пытался отключить и снова включить API книг.
Заранее спасибо.
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 Книги API для Android - доступ не настроен
Проблема заключается в том, что при настройке ограничения ключа API для приложения Android вы указали имя пакета и отпечаток сертификата SHA-1. Поэтому ваш ключ API будет принимать запрос только от вашего приложения с указанным именем пакета и отпечатком сертификата SHA-1.
Итак, как Google узнает, что запрос отправлен с вашего Android-приложения? Вы ДОЛЖНЫ добавить имя пакета вашего приложения и сертификат SHA в заголовок каждого запроса со следующими ключами:
Ключ: "X-Android-Package"
, значение: имя вашего приложения
Ключ: "X-Android-Cert"
, значение: SHA-1 сертификат вашего apk
Сначала получите подпись 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();
}
Надеюсь, это поможет!:)