7
votes

I have been searching everywhere on the Internet for Google Translate API usage but I wasn't able find descent tutorial or explanation. So, here is what I have done:

In my Google API Console I have generated a key under Public API access with my SHA1 Fingerprint using this answer. Here is how my API console looks like: Google console

In Android studio I build and send my request using OkHttp library with this code:

OkHttpClient client = new OkHttpClient();
    String apiKey = "My API key";
    String apiLangSource = "en";
    String apiLangTarget = "de";
    String apiWord = "Hello";
    String googleApiUrl = "https://www.googleapis.com/language/translate/v2?key=" + apiKey + "&source=" + apiLangSource + "&target=" + apiLangTarget + "&q=" + apiWord;
    Request request = new Request.Builder().url(googleApiUrl).build();

    Log.d(TAG, "API STRING" + googleApiUrl);

    Call call = client.newCall(request);

    call.enqueue(new Callback() {
        @Override
        public void onFailure(Request request, IOException e) {
            Log.d(TAG , "HTTP CALL FAIL");
        }

        @Override
        public void onResponse(Response response) throws IOException {
            Log.d(TAG , response.body().string());

        }
    });

It runs fine but on response I get:

{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "ipRefererBlocked",
"message": "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed.",
"extendedHelp": "https://console.developers.google.com"
}
],
"code": 403,
"message": "There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed."
}
}


What is the problem here? Is my API set up correctly? Am I making the call correctly (I've seen some libraries but with guide)? Is this reasonable way of using this library? What exacty does this mean?

"There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed."

I think there are some demo calls available for free and this isn't the problem here.

1
I guess your API configuration isn't well finished.U can see in response restriction configured on your API key and the request does not matchAnoop M Maddasseri
When I remove the fingerprint and package it works. So it's really authentication error. How does google verify my fingerprint and package?BabbevDan
I am encountering the same problem. @DannyBabbev, did you find a solution for this?Flo
I haven't found a solution.BabbevDan

1 Answers

2
votes

Problem is when setting up your API key restriction for android app, you specified the package name and SHA-1 certificate fingerprint. Therefore your API key will only accept request from your app with package name and SHA-1 certificate fingerprint specified.

So how google know that request's sent FROM YOUR ANDROID APP? You MUST add your app's package name and SHA-1 in the header of each request with following keys:

Key: "X-Android-Package", value: your app package name

Key: "X-Android-Cert", value: SHA-1 certificate of your apk

FIRST, get your app SHA signature (you will need Guava library):

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

Then, add package name and SHA certificate signature to request header:

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

Hope this help! :)