Showing posts with label gradle. Show all posts
Showing posts with label gradle. Show all posts

Thursday, March 16, 2017

Lint stuck after upgrading gradle plugin to 2.3.0

app:lint hangs after I upgraded the gradle plugin to 2.3.0.

Unexpected failure during lint analysis (this is a bug in lint or one of the libraries it depends on)

It complains about ProblemReporter.isClassPathCorrect(ProblemReporter.java:4761) and other places in ProblemReporter, but I was not able to pinpoint the problem.

Turns out this is caused by libraries that uses old lint APIs, in my case Timber and Butterknife. Once I updated those dependencies, lint finishes.

Thanks Josh Burton for sharing his solution with me!

Monday, January 16, 2017

Java compatibility in build.gradle

I got an email from Google asking me to update Fit Cat for Android Wear 2.0, so I tried to compile that app after I haven't touched it for a few months.

Since Android Studio evolves so quickly, I wasn't exactly surprised when I got an error:

Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.
This is caused by library dependencies that have been
compiled using Java 8 or above.

It asked me to add sourceCompatitbility and targetCompatitbility to Java submodules. What does that mean? After a lot of searching plus trial and error I found the answer.

In your top-level build.gradle, add this:

allprojects {
  tasks.withType(JavaCompile) {
    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7
  }
}

Monday, February 2, 2015

gce2retrofit, a gradle plugin

I am working on an Android app that uses Retrofit to talk to a Google Cloud Endpoints (GCE) server. Initially I was writing the Retrofit interfaces and models by hand, but then I found out that GCE servers serve a discovery document describing all its endpoints in JSON. So I started working on a tool to generate the Retrofit Java files automatically from the JSON document.

JavaWriter

I used JavaWriter (predecessor to JavaPoet) for code generation because I have this vague idea that if I do it in Java I can make it a gradle plugin. My first iteration is a jar file that can be run from the command-line, taking the discovery JSON file as an argument, and writes the Java files to the src/main/java directory to be checked in. This is a major time saver since I don't have to manually write all the Retrofit classes and interfaces every time the server updates.

Gradle plugin

To make it even easier, I want the code generation to be a part of the build process. I want the GCE discovery JSON file to be the source of truth, generating the Retrofit Java files when it gets updated. I have never written a Gradle plugin before, so I went through the tutorial to get a basic understanding.

I had difficulty getting Android Studio to recognize the generated files until I found another code generation gradle plugin that works with Android: Paraphrase.

Points to note

In the gradle task:

  • Use @InputDirectory to specify what triggers an incremental build.
  • Use @OutputDirectory to create the output directory on demand.

In the gradle plugin:

  • Use project.plugins.hasPlugin to determine if it is a Java project or an Android project.
  • Use variant.registerJavaGeneratingTask to make Android Studio recognize the generated files.

Push to Sonatype Nexus

Once my plugin is ready I need to publish it. I want to push a snapshot first, so I looked into Sonatype Nexus. There seems to be many different ways to do it, and I was at analysis paralysis for weeks. Finally I turned to Twitter and Google+ to ask for help, and pushed the snapshot with the maven and com.bmuschko.nexus plugins.

Try it

If you use Google Cloud Endpoint with Retrofit, please try the plugin and file issues if you encounter any. Instructions and source code here: https://github.com/chiuki/gce2retrofit.