From a06c7ad1b6d499664a04883fcc072cad8e236c0f Mon Sep 17 00:00:00 2001 From: Chengyuan Zhang Date: Wed, 18 Nov 2020 10:42:14 -0800 Subject: [PATCH] Support packaging and extracting protos in Android aar (take 2) (#443) Fixes the issue of ExtractIncludeProto tasks failing to match dependencies, which was caused by the previous commit trying to extract included protos for each Android source set instead for each variant. Android projects should extract included protos from each variant's compileClasspath as variants are compilation units for Android projects. So we will not create compileProtoPath configurations for Android source sets. This change includes an integration test for covering packaging/extracting protos in AAR. --- .../protobuf/gradle/ProtobufPlugin.groovy | 38 ++- .../gradle/ProtobufAndroidPluginTest.groovy | 31 ++ .../grpc/helloworldexample/TestLibrary.java | 2 +- .../io/grpc/helloworldexample/UnitTest.java | 2 +- .../build_base.gradle | 274 ++++++++++++++++++ .../lib/protos.jar | Bin 0 -> 269 bytes .../proguard-rules.pro | 17 ++ .../src/androidTest/proto/sample.proto | 23 ++ .../src/main/AndroidManifest.xml | 22 ++ .../src/main/proto/helloworld.proto | 55 ++++ .../main/res/layout/activity_helloworld.xml | 54 ++++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3418 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2206 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4842 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7718 bytes .../src/main/res/values/strings.xml | 3 + .../src/test/proto/unittest.proto | 23 ++ testProjectAndroidLibrary/build.gradle | 91 ++++++ testProjectAndroidLibrary/settings.gradle | 1 + .../src/main/AndroidManifest.xml | 5 + .../src/main/proto/messages.proto | 138 +++++++++ 21 files changed, 772 insertions(+), 7 deletions(-) create mode 100644 testProjectAndroidDependentBase/build_base.gradle create mode 100644 testProjectAndroidDependentBase/lib/protos.jar create mode 100644 testProjectAndroidDependentBase/proguard-rules.pro create mode 100644 testProjectAndroidDependentBase/src/androidTest/proto/sample.proto create mode 100644 testProjectAndroidDependentBase/src/main/AndroidManifest.xml create mode 100644 testProjectAndroidDependentBase/src/main/proto/helloworld.proto create mode 100644 testProjectAndroidDependentBase/src/main/res/layout/activity_helloworld.xml create mode 100644 testProjectAndroidDependentBase/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 testProjectAndroidDependentBase/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 testProjectAndroidDependentBase/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 testProjectAndroidDependentBase/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 testProjectAndroidDependentBase/src/main/res/values/strings.xml create mode 100644 testProjectAndroidDependentBase/src/test/proto/unittest.proto create mode 100644 testProjectAndroidLibrary/build.gradle create mode 100644 testProjectAndroidLibrary/settings.gradle create mode 100644 testProjectAndroidLibrary/src/main/AndroidManifest.xml create mode 100644 testProjectAndroidLibrary/src/main/proto/messages.proto diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy index a824914a..ed576d90 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy @@ -38,6 +38,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.LibraryElements import org.gradle.api.file.FileCollection import org.gradle.api.file.SourceDirectorySet @@ -130,8 +131,15 @@ class ProtobufPlugin implements Plugin { project.afterEvaluate { // All custom source sets, configurations created by other plugins, // and Android variants are only available at this point. - getSourceSets().each { sourceSet -> - createCompileProtoPathConfiguration(sourceSet.name) + + // Java projects will extract included protos from a 'compileProtoPath' + // configuration of each source set, while Android projects will + // extract included protos from {@code variant.compileConfiguration} + // of each variant. + if (!Utils.isAndroidProject(project)) { + getSourceSets().each { sourceSet -> + createCompileProtoPathConfiguration(sourceSet.name) + } } addProtoTasks() project.protobuf.runTaskConfigClosures() @@ -173,6 +181,7 @@ class ProtobufPlugin implements Plugin { * The extract-include-protos task of each source set will extract protobuf files from * dependencies in this configuration. * + *

For Java projects only. *

This works around 'java-library' plugin not exposing resources to consumers for compilation. */ private void createCompileProtoPathConfiguration(String sourceSetName) { @@ -267,6 +276,7 @@ class ProtobufPlugin implements Plugin { * Creates Protobuf tasks for a variant in an Android project. */ private void addTasksForVariant(final Object variant, boolean isTestVariant) { + // GenerateProto task, one per variant (compilation unit). Task generateProtoTask = addGenerateProtoTask(variant.name, variant.sourceSets) generateProtoTask.setVariant(variant, isTestVariant) generateProtoTask.flavors = ImmutableList.copyOf(variant.productFlavors.collect { it.name } ) @@ -275,19 +285,37 @@ class ProtobufPlugin implements Plugin { } generateProtoTask.doneInitializing() + // ExtractIncludeProto task, one per variant (compilation unit). + // Proto definitions from an AAR dependencies are in its JAR resources. + Attribute artifactType = Attribute.of("artifactType", String) + FileCollection classPathConfig = variant.compileConfiguration.incoming.artifactView { + attributes { + it.attribute(artifactType, "jar") + } + }.files + FileCollection testClassPathConfig = + variant.hasProperty("testedVariant") ? + variant.testedVariant.compileConfiguration.incoming.artifactView { + attributes { + it.attribute(artifactType, "jar") + } + }.files : null + setupExtractIncludeProtosTask(generateProtoTask, variant.name, classPathConfig, testClassPathConfig) + + // ExtractProto task, one per source set. if (project.android.hasProperty('libraryVariants')) { + // Include source proto files in the compiled archive, so that proto files from + // dependent projects can import them. Task processResourcesTask = variant.getProcessJavaResourcesProvider().get() processResourcesTask.from(generateProtoTask.sourceFiles) { include '**/*.proto' } variant.sourceSets.each { - setupExtractIncludeProtosTask(generateProtoTask, it.name) Task extractTask = setupExtractProtosTask(generateProtoTask, it.name) processResourcesTask.dependsOn(extractTask) } } else { variant.sourceSets.each { - setupExtractIncludeProtosTask(generateProtoTask, it.name) setupExtractProtosTask(generateProtoTask, it.name) } } @@ -384,7 +412,7 @@ class ProtobufPlugin implements Plugin { // dependencies. if (Utils.isTest(sourceSetOrVariantName)) { inputFiles.from getSourceSets()['main'].proto - inputFiles.from testedCompileClasspathConfiguration ?: project.configurations['compile'] + inputFiles.from testedCompileClasspathConfiguration } } else { // In Java projects, the compileClasspath of the 'test' sourceSet includes all the diff --git a/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy b/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy index 20f47a09..7ce61573 100644 --- a/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy +++ b/src/test/groovy/com/google/protobuf/gradle/ProtobufAndroidPluginTest.groovy @@ -110,6 +110,37 @@ class ProtobufAndroidPluginTest extends Specification { gradleVersion << GRADLE_VERSION.takeRight(1) } + @Unroll + void "testProjectAndroidDependent [android #agpVersion, gradle #gradleVersion, kotlin #kotlinVersion]"() { + given: "project from testProjectAndroidLibrary, testProjectAndroid" + File testProjectStaging = ProtobufPluginTestHelper.projectBuilder('testProject') + .copyDirs('testProjectBase', 'testProject') + .build() + File testProjectLibraryStaging = ProtobufPluginTestHelper.projectBuilder('testProjectAndroidLibrary') + .copyDirs('testProjectAndroidLibrary') + .build() + File testProjectAndroidStaging = ProtobufPluginTestHelper.projectBuilder('testProjectAndroid') + .copyDirs('testProjectAndroidDependentBase', 'testProjectAndroid') + .build() + File mainProjectDir = ProtobufPluginTestHelper.projectBuilder('testProjectAndroidDependentMain') + .copySubProjects(testProjectStaging, testProjectLibraryStaging, testProjectAndroidStaging) + .withAndroidPlugin(agpVersion) + .build() + when: "build is invoked" + BuildResult result = buildAndroidProject( + mainProjectDir, + gradleVersion, + "testProjectAndroid:build" + ) + + then: "it succeed" + result.task(":testProjectAndroid:build").outcome == TaskOutcome.SUCCESS + + where: + agpVersion << ANDROID_PLUGIN_VERSION + gradleVersion << GRADLE_VERSION + } + @Unroll void "testProjectAndroidKotlin [android #agpVersion, gradle #gradleVersion, kotlin #kotlinVersion]"() { given: "project from testProject, testProjectLite & testProjectAndroid" diff --git a/testProjectAndroid/src/androidTest/java/io/grpc/helloworldexample/TestLibrary.java b/testProjectAndroid/src/androidTest/java/io/grpc/helloworldexample/TestLibrary.java index 51d02bd6..074a225a 100644 --- a/testProjectAndroid/src/androidTest/java/io/grpc/helloworldexample/TestLibrary.java +++ b/testProjectAndroid/src/androidTest/java/io/grpc/helloworldexample/TestLibrary.java @@ -9,7 +9,7 @@ public class TestLibrary { // From src/main/proto/helloworld.proto Helloworld.HelloRequest request; - // From testProjectLite: src/nano/proto/messages.proto + // From dependency project (testProjectLite/testProjectAndroidLibrary): src/proto/messages.proto io.grpc.testing.Messages.SimpleRequest simpleRequest; // From lib/protos.jar diff --git a/testProjectAndroid/src/test/java/io/grpc/helloworldexample/UnitTest.java b/testProjectAndroid/src/test/java/io/grpc/helloworldexample/UnitTest.java index 3c0c0322..1a3114ef 100644 --- a/testProjectAndroid/src/test/java/io/grpc/helloworldexample/UnitTest.java +++ b/testProjectAndroid/src/test/java/io/grpc/helloworldexample/UnitTest.java @@ -15,7 +15,7 @@ public final class UnitTest { // From src/main/proto/helloworld.proto private Helloworld.HelloRequest request; - // From testProjectLite: src/nano/proto/messages.proto + // From dependency project (testProjectLite/testProjectAndroidLibrary): src/proto/messages.proto private io.grpc.testing.Messages.SimpleRequest simpleRequest; // From lib/protos.jar diff --git a/testProjectAndroidDependentBase/build_base.gradle b/testProjectAndroidDependentBase/build_base.gradle new file mode 100644 index 00000000..fd327a65 --- /dev/null +++ b/testProjectAndroidDependentBase/build_base.gradle @@ -0,0 +1,274 @@ +repositories { + maven { url 'https://maven.google.com' } + maven { url "https://plugins.gradle.org/m2/" } +} + +buildscript { + repositories { + maven { url 'https://maven.google.com' } + maven { url "https://plugins.gradle.org/m2/" } + } +} + +android { + compileSdkVersion 26 + buildToolsVersion "26.0.1" + + defaultConfig { + applicationId "io.grpc.helloworldexample" + minSdkVersion 7 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + + flavorDimensions 'abi', 'version' + + productFlavors { + freeapp { + dimension 'version' + } + retailapp { + dimension 'version' + } + x86 { + dimension 'abi' + } + arm { + dimension 'abi' + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 + } + + packagingOptions { + exclude 'io/grpc/testing/integration/empty.proto' + exclude 'io/grpc/testing/integration/test.proto' + exclude 'io/grpc/testing/integration/messages.proto' + exclude 'tmp/stuff.proto' + } + + // https://github.com/square/okio/issues/58 + lintOptions { + warning 'InvalidPackage' + abortOnError false + } + + dexOptions { + javaMaxHeapSize "1g" + threadCount 1 // reduce predex thread count to limit memory usage + } +} + +protobuf { + protoc { + artifact = 'com.google.protobuf:protoc:3.0.0' + } + plugins { + grpc { + artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2' + } + javalite { + artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0' + } + } + generateProtoTasks { + all()*.plugins { + javalite { } + } + ofNonTest()*.plugins { + grpc { + // Options added to --grpc_out + option 'lite' + } + } + } +} + +dependencies { + compile 'com.android.support:appcompat-v7:23.4.0' + compile 'com.squareup.okhttp:okhttp:2.7.5' + compile 'javax.annotation:javax.annotation-api:1.2' + compile 'com.google.protobuf:protobuf-lite:3.0.0' + compile 'io.grpc:grpc-core:1.0.0-pre2' + compile 'io.grpc:grpc-stub:1.0.0-pre2' + compile 'io.grpc:grpc-okhttp:1.0.0-pre2' + compile('io.grpc:grpc-protobuf-lite:1.0.0-pre2') { + // Otherwise Android compile will complain "Multiple dex files define ..." + exclude module: "protobuf-lite" + } + compile(project(':testProjectAndroidLibrary')) { + exclude module: "protobuf-lite" + } + protobuf files('lib/protos.jar') + testCompile 'junit:junit:4.12' +} + +def assertJavaCompileHasProtoGeneratedDir(Object variant, Collection codegenPlugins) { + rootProject.assertJavaCompileHasProtoGeneratedDir(project, variant.name, variant.javaCompileProvider.get(), codegenPlugins) +} + +afterEvaluate { + // 'gradle test' will run the unit tests, which is still experimental in + // Android plugin, and would do nothing with our setup. We make 'test' to + // trigger the "androidTest" Java compile tasks. + android.testVariants.each { testVariant -> + test.dependsOn testVariant.javaCompileProvider + } + + test.doLast { + assert [ + 'generateArmFreeappDebugAndroidTestProto', + 'generateArmFreeappDebugUnitTestProto', + 'generateArmFreeappReleaseUnitTestProto', + 'generateArmFreeappDebugProto', + 'generateArmFreeappReleaseProto', + 'generateArmRetailappDebugAndroidTestProto', + 'generateArmRetailappDebugUnitTestProto', + 'generateArmRetailappReleaseUnitTestProto', + 'generateArmRetailappDebugProto', + 'generateArmRetailappReleaseProto', + 'generateX86FreeappDebugAndroidTestProto', + 'generateX86FreeappDebugUnitTestProto', + 'generateX86FreeappReleaseUnitTestProto', + 'generateX86FreeappDebugProto', + 'generateX86FreeappReleaseProto', + 'generateX86RetailappDebugAndroidTestProto', + 'generateX86RetailappDebugUnitTestProto', + 'generateX86RetailappReleaseUnitTestProto', + 'generateX86RetailappDebugProto', + 'generateX86RetailappReleaseProto', + ] as Set == protobuf.generateProtoTasks.all().collect({ it.name }) as Set + + assert [ + 'generateArmFreeappDebugAndroidTestProto', + 'generateArmFreeappDebugUnitTestProto', + 'generateArmFreeappReleaseUnitTestProto', + 'generateArmRetailappDebugAndroidTestProto', + 'generateArmRetailappDebugUnitTestProto', + 'generateArmRetailappReleaseUnitTestProto', + 'generateX86FreeappDebugAndroidTestProto', + 'generateX86FreeappDebugUnitTestProto', + 'generateX86FreeappReleaseUnitTestProto', + 'generateX86RetailappDebugAndroidTestProto', + 'generateX86RetailappDebugUnitTestProto', + 'generateX86RetailappReleaseUnitTestProto', + ] as Set == protobuf.generateProtoTasks.ofTest().collect({ it.name }) as Set + + assert [ + 'generateArmFreeappDebugProto', + 'generateArmFreeappReleaseProto', + 'generateArmRetailappDebugProto', + 'generateArmRetailappReleaseProto', + 'generateX86FreeappDebugProto', + 'generateX86FreeappReleaseProto', + 'generateX86RetailappDebugProto', + 'generateX86RetailappReleaseProto', + ] as Set == protobuf.generateProtoTasks.ofNonTest().collect({ it.name }) as Set + + assert [ + 'generateArmFreeappDebugAndroidTestProto', + 'generateArmFreeappDebugUnitTestProto', + 'generateArmFreeappReleaseUnitTestProto', + 'generateArmFreeappDebugProto', + 'generateArmFreeappReleaseProto', + 'generateX86FreeappDebugAndroidTestProto', + 'generateX86FreeappDebugUnitTestProto', + 'generateX86FreeappReleaseUnitTestProto', + 'generateX86FreeappDebugProto', + 'generateX86FreeappReleaseProto', + ] as Set == protobuf.generateProtoTasks.ofFlavor('freeapp').collect({ it.name }) as Set + + assert [ + 'generateArmRetailappDebugAndroidTestProto', + 'generateArmRetailappDebugUnitTestProto', + 'generateArmRetailappReleaseUnitTestProto', + 'generateArmRetailappDebugProto', + 'generateArmRetailappReleaseProto', + 'generateX86RetailappDebugAndroidTestProto', + 'generateX86RetailappDebugUnitTestProto', + 'generateX86RetailappReleaseUnitTestProto', + 'generateX86RetailappDebugProto', + 'generateX86RetailappReleaseProto', + ] as Set == protobuf.generateProtoTasks.ofFlavor('retailapp').collect({ it.name }) as Set + + assert [ + 'generateX86FreeappDebugAndroidTestProto', + 'generateX86FreeappDebugUnitTestProto', + 'generateX86FreeappReleaseUnitTestProto', + 'generateX86FreeappDebugProto', + 'generateX86FreeappReleaseProto', + 'generateX86RetailappDebugAndroidTestProto', + 'generateX86RetailappDebugUnitTestProto', + 'generateX86RetailappReleaseUnitTestProto', + 'generateX86RetailappDebugProto', + 'generateX86RetailappReleaseProto', + ] as Set == protobuf.generateProtoTasks.ofFlavor('x86').collect({ it.name }) as Set + + assert [ + 'generateArmFreeappDebugAndroidTestProto', + 'generateArmFreeappDebugUnitTestProto', + 'generateArmFreeappReleaseUnitTestProto', + 'generateArmFreeappDebugProto', + 'generateArmFreeappReleaseProto', + 'generateArmRetailappDebugAndroidTestProto', + 'generateArmRetailappDebugUnitTestProto', + 'generateArmRetailappReleaseUnitTestProto', + 'generateArmRetailappDebugProto', + 'generateArmRetailappReleaseProto', + ] as Set == protobuf.generateProtoTasks.ofFlavor('arm').collect({ it.name }) as Set + + assert [ + 'generateArmFreeappDebugAndroidTestProto', + 'generateArmFreeappDebugUnitTestProto', + 'generateArmFreeappDebugProto', + 'generateArmRetailappDebugAndroidTestProto', + 'generateArmRetailappDebugUnitTestProto', + 'generateArmRetailappDebugProto', + 'generateX86FreeappDebugAndroidTestProto', + 'generateX86FreeappDebugUnitTestProto', + 'generateX86FreeappDebugProto', + 'generateX86RetailappDebugAndroidTestProto', + 'generateX86RetailappDebugUnitTestProto', + 'generateX86RetailappDebugProto' + ] as Set == protobuf.generateProtoTasks.ofBuildType('debug').collect({ it.name }) as Set + + assert [ + 'generateArmFreeappReleaseProto', + 'generateArmFreeappReleaseUnitTestProto', + 'generateArmRetailappReleaseProto', + 'generateArmRetailappReleaseUnitTestProto', + 'generateX86FreeappReleaseProto', + 'generateX86FreeappReleaseUnitTestProto', + 'generateX86RetailappReleaseProto', + 'generateX86RetailappReleaseUnitTestProto', + ] as Set == protobuf.generateProtoTasks.ofBuildType('release').collect({ it.name }) as Set + + assert ['generateX86FreeappDebugAndroidTestProto'] as Set == + protobuf.generateProtoTasks.ofVariant('x86FreeappDebugAndroidTest').collect({ it.name }) as Set + + // "androidTest" sourceSet is not a flavor + assert [] as Set == protobuf.generateProtoTasks.ofFlavor('androidTest').collect({ it.name }) as Set + + // "unitTest" sourceset is not a flavor + assert [] as Set == protobuf.generateProtoTasks.ofFlavor('unitTest').collect({ it.name }) as Set + + android.applicationVariants.each { variant -> + assertJavaCompileHasProtoGeneratedDir(variant, ['javalite', 'grpc']) + } + + android.testVariants.each { variant -> + assertJavaCompileHasProtoGeneratedDir(variant, ['javalite']) + } + } +} diff --git a/testProjectAndroidDependentBase/lib/protos.jar b/testProjectAndroidDependentBase/lib/protos.jar new file mode 100644 index 0000000000000000000000000000000000000000..18f117dbd896c0d122afc603ba3ba081cccc9720 GIT binary patch literal 269 zcmWIWW@Zs#U|`^2nC1J=?a+jV+tEN?1`zWx$S|Z#4 z3I*ZP3T_5Q7I$_g29^$C1_teQXS6-n1Z)Tm(9$@if6_c`)3Zlf9zN&%eEdT_&Yi#N zeg3@vdC#lN-fB~qy<94;x{Tqc>dK?44pVooJbF}Ns-NXg&wT-9rqi38f>Z+XRnLWV+inOWRhdX + + + + + + + + + + + + + + diff --git a/testProjectAndroidDependentBase/src/main/proto/helloworld.proto b/testProjectAndroidDependentBase/src/main/proto/helloworld.proto new file mode 100644 index 00000000..ad69b84c --- /dev/null +++ b/testProjectAndroidDependentBase/src/main/proto/helloworld.proto @@ -0,0 +1,55 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +// From testProjectAndroidLibrary: src/proto +import "messages.proto"; + +option java_package = "io.grpc.helloworldexample"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; + // Uses message type from messages.proto + grpc.testing.SimpleContext context = 2; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/testProjectAndroidDependentBase/src/main/res/layout/activity_helloworld.xml b/testProjectAndroidDependentBase/src/main/res/layout/activity_helloworld.xml new file mode 100644 index 00000000..00ca04ce --- /dev/null +++ b/testProjectAndroidDependentBase/src/main/res/layout/activity_helloworld.xml @@ -0,0 +1,54 @@ + + + + + + + + + + +