4

I made a simple protobuf+gRPC server/client example with Python, and wanted now to complete it with an Android Java client. However, I struggled through the documentation and got it mostly working (.proto compiles in Android Studio), BUT now I get Errors in the output *Grpc.java file (i.e. if I fix it it will just be overwritten by the compiler):

error: package io.grpc.protobuf does not exist
error: package com.google.protobuf.Descriptors does not exist

Since I get errors from io.gprc's and com.google's protobuf, I suspect a definition conflict in my gradle, but I cannot find/resolve it (went through several "tutorials" and it seemed common to use a mix of grpc and google sources).

Here is my build.gradle:


android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "***.grpcclient"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }


}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
    implementation 'io.grpc:grpc-okhttp:1.25.0'
    //implementation 'io.grpc:grpc-protobuf-lite:1.25.0'

    implementation 'com.google.protobuf:protobuf-javalite:3.8.0'
    implementation 'io.grpc:grpc-stub:1.25.0'
    implementation 'org.glassfish:javax.annotation:10.0-b28'
}

apply plugin: 'com.google.protobuf'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
    }
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.8.0'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.25.0'
        }
    }
    generateProtoTasks {
        all().each { task ->

                task.builtins {
                    java {
                        option "lite"
                    }
                    python { }
                }
                task.plugins {
                    grpc {outputSubDir = 'java'}
                }

        }
    }
}

Any help is appreciated!

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
André
  • 142
  • 1
  • 15

2 Answers2

4

Android uses Protobuf Lite, which is a subset of the normal implementation and optimized for Android. You correctly tried to depend on io.grpc:grpc-protobuf-lite:1.25.0. This provides the io.grpc.protobuf.lite package.

You also correctly configured protoc to generate protobuf-lite messages. However, the grpc plugin is generating "full" protobuf services. That's why you're seeing references to io.grpc.protobuf and classes missing in protobuf like com.google.protobuf.Descriptors.

protobuf {
    ...
    generateProtoTasks {
        all().each { task ->
                ...
                task.plugins {
                    grpc {
                        outputSubDir = 'java'
                        option 'lite' // Needed this line
                    }
                }
        }
    }
}

Since you are using protoc with the 'lite' option, instead of using the older protoc-gen-javalite plugin, you are using the correct protobuf-javalite dependency for protobuf. However, grpc-java 1.25.0 depends on protobuf-lite which will collide. This is discussed some in Issue 6405 and will be fixed in grpc-java 1.26.0. But for the moment you'll need to exclude the protobuf-lite dependency brought in by grpc-protobuf-lite.

dependencies {
    ...
    implementation ('io.grpc:grpc-protobuf-lite:1.25.0') {
        // Exclude will not be necessary starting in grpc 1.26
        exclude group: 'com.google.protobuf', module: 'protobuf-lite'
    }
}
Eric Anderson
  • 24,057
  • 5
  • 55
  • 76
  • Thanks Eric! That worked perfectly. I am glad I was on the right track, but would never have guessed this in 100 years... You are a life-saver! – André Nov 20 '19 at 09:57
2

My working build.gradle:


dependencies {

   implementation 'com.squareup.okhttp:okhttp:2.7.5'
    implementation 'javax.annotation:javax.annotation-api:1.3.2'
    implementation 'io.grpc:grpc-core:1.27.1'
    implementation 'io.grpc:grpc-stub:1.27.1'
    implementation 'io.grpc:grpc-okhttp:1.27.1'
    implementation('io.grpc:grpc-protobuf-lite:1.27.1') {
        exclude module: "protobuf-lite"
    }
}

protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.11.4'
    }
    plugins {
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.27.1'
        }
        javalite {
            artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
        }
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    option 'lite'
                }
            }

            task.plugins {
                grpc {
                    // Options added to --grpc_out
                    option 'lite'
                }
            }
        }
    }
}
Morteza Rastgoo
  • 6,772
  • 7
  • 40
  • 61