Java – Build Java libraries that rely on the Android project Gradle

Build Java libraries that rely on the Android project Gradle… here is a solution to the problem.

Build Java libraries that rely on the Android project Gradle

I have an Android project that defines various data types serialized via Protocol Buffers. I would like to have a separate Java project capable of deserializing these data types on the server.

My project structure is as follows:

Android Library
  - Data
      - TypeA 
      - TypeB
      - ...

Java Server
  - Parser (depends on . Data)

In this example, all classes in the Data package handle their own encoding (marshal) processing.

When trying to build the Java server, it successfully compiled the Android project, but ultimately failed, and Gradle said that the referenced package could not be found.

Note that if I only introduce other Java libraries, I can successfully build a Java server with cross-project dependencies, which leads me to believe that this is a Java-> Android dependency issue, not a Gradle configuration issue.

One possible solution I’ve considered is to extract all these data types from an Android project and put them in a separate Java library. The problem with this, however, is that some of these classes only provide a way to convert Android-specific classes (SensorEvent, Location, etc.) to types that can be used with ProtoBuf. One solution I’ve been thinking about is as follows:

Data Types
  - TypeA
  - TypeB
  - ...

Android Library
  - Data
    - AndroidTypeA (Class with Android Specific constructor that can be cast to the parent type)
    - AndroidTypeB
    - ...

Java Server
  - Parser ( Depends on the Data Types module )  

While this does fix my problem, it doesn’t seem like the best solution.

Is there a way to accomplish this task only through Gradle?


This is an abbreviated version of my build.gradle file.

Android Library:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 21
    buildToolsVersion "21.0.2"

defaultConfig {
        applicationId "com.foo.bar.androidlib"
        ...
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    ...
    compile 'com.google.protobuf:protobuf-java:2.6.1'
}

Java Server:

apply plugin: 'java'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.google.protobuf:protobuf-java:2.6.1'
    compile project(':androidlib')
}

Edit:

In particular, Gradle gives the following error:

error: package com.foo.bar.androidlib does not exist

Solution

In Gradle, you can’t have Java libraries that depend on Android libraries. This is because the Android plugin in Gradle is not based on and is not compatible with the Java plugin, so Java does not understand its source set and cannot use it well in other ways.

I don’t think you can solve this problem with the Gradle config alone, and even if you could, it might make your build incredibly complex and brittle. Your best bet is to make your Java stuff only depend on Java stuff, isolate the protobuf dependencies that are common there, and let the Android side depend on Java. You outline some of the methods of the Android version of the class; This might work, but I don’t know enough about what you’re doing to comment on it in detail.

Related Problems and Solutions