minifyEnabled in Android app breaks GoogleApi calls

692 views Asked by At

TLDR - Android app has problems with Google API when minifyEnabled is true.

There is an Android app that uses Google API for creating events and google meetings. I use pretty standard tools for working with those APIs - GoogleAuthorizationCodeFlow, com.google.api.services.calendar.Calendar, com.google.api.services.calendar.model.Event. I am using "Web server applications" auth way instead of "Installed applications" for no good reason but the fact I already made the first one work. All works fine in my debug mode, but when I go to release mode, problems arise.

  • GoogleClientSecrets becomes unable to process secrets.json console.developers.google.com gave me. Same file works fine in debug mode, but now GoogleClientSecrets.getDetails returns null. Funny fact - GoogleClientSecrets.toString/GoogleClientSecrets.toPrettyString show data from file, but it seems to be missing all quotes config file has. It eventually fixed (now I am creating secrets directly using clientId/clientSecret, without json file), but why problem appears first place?
  • after that fix, flow.newAuthorizationUrl().setRedirectUri(redirectUrl).build() gives me https://accounts.google.com/o/oauth2/auth instead of https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=<myClientId>&redirect_uri=<myRedirect>&response_type=code&scope=https://www.googleapis.com/auth/calendar. Most of "relative" part is skipped, although redirectUrl and clientId are read and saved correctly - but there is no trace of them in Url. This was fixed with adding -keep class com.google.api.client.googleapis.auth.oauth2.* to my proguard-rules.pro. Which is already looks like more of workaround, than real solution, but things get worse later.
  • after that fix, when I do
    Credential credential = getCredential(context);
    Calendar service = new Calendar.Builder(HTTP_TRANSPORT,
                            JSON_FACTORY,
                            credential)
                            .setApplicationName(APPLICATION_NAME)
                            .build();
    service.events().insert(calendarId, event)
                            .setConferenceDataVersion(1)
                            .setSupportsAttachments(true)
                            .execute();

with a perfectly good event that works fine without minification, then I get

c.f.b.a.b.c.b: 404 Not Found
{
   "errors" : [ {
     "domain" : "global",
     "reason" : "notFound",
     "message" : "Not Found"
   } ],
   "code" : 404,
   "message" : "Not Found"
}

This can be fixed with -keep class com.google.api.services.calendar.* { *; } in my proguard-rules.pro

  • after that fix, same attempt to insert event gives me
    W/System.err: java.lang.IllegalArgumentException: key creator
            at com.google.api.client.json.JsonParser.parseValue(JsonParser.java:889)
            at com.google.api.client.json.JsonParser.parse(JsonParser.java:382)
            at com.google.api.client.json.JsonParser.parse(JsonParser.java:355)
            at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:87)
            at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:81)
            at com.google.api.client.http.HttpResponse.parseAs(HttpResponse.java:459)
            at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)

After some tests, I noticed, that all of the above appears only when minifyEnabled is true. With minifyEnabled false, all works like a charm. So far I found 3 solutions

  • minifyEnabled false. I kind of like my files minified in release though
  • dontobfuscate and dontshrink in proguard-rules.pro. Helps, but reduces the effect of minifying.
  • keep class * { *; } in proguard-rules.pro. Helps, but reduces the effect of minifying.

I can't believe that a standard option like minifyEnabled would break something like GoogleAuthorization through standard tools of com.google.api.client.* on such a great scale. I can believe in me making some stupid and obvious mistakes, though. My last straw, for now, is going to "Installed" way from "Web server applications", but I don't exactly put big hopes here - if it was the main source of problems, why would it work without minification...

Why can the described behavior happen? What am I doing wrong?

1

There are 1 answers

1
Iván Garza Bermea On

It's not an uncommon practice to add rule exceptions to your proguard-rules.pro file whenever you find problems with obfuscation in your release build.

Working with ProGuard on its own is an entire topic, but don't think that adding exceptions to your app's obfuscation tool is undermining your app's security or whatnot. Some APIs and coding patterns simply require a few exceptions in order to work properly; e.g. data classes/models, and everything coming from the JNI layer always require to be de-obfuscated.

Here's a quick article on the topic if you're still not convinced.