diff --git a/build.gradle b/build.gradle index 45c50df5..07166569 100644 --- a/build.gradle +++ b/build.gradle @@ -53,6 +53,7 @@ configurations { dependencies { compileOnly "org.gradle:gradle-kotlin-dsl:1.0.4" + compileOnly "com.android.tools.build:gradle:3.5.0" compile 'com.google.guava:guava:27.0.1-jre' compile 'com.google.gradle:osdetector-gradle-plugin:1.6.2' diff --git a/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt b/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt index 00c75079..4b163a0d 100644 --- a/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt +++ b/src/main/kotlin/com/google/protobuf/gradle/ProtobufConfiguratorExts.kt @@ -1,5 +1,6 @@ package com.google.protobuf.gradle +import com.android.build.gradle.api.AndroidSourceSet import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.file.SourceDirectorySet @@ -31,8 +32,8 @@ fun Project.protobuf(action: ProtobufConfigurator.()->Unit) { } /** - * Applies the supplied action to the [ProtobufSourceDirectorySet] extension on - * a receiver of type [SourceSet] + * Applies the supplied action to the "proto" [SourceDirectorySet] extension on + * a receiver of type [SourceSet]. * * @since 0.8.7 * @usage @@ -60,6 +61,38 @@ fun SourceSet.proto(action: SourceDirectorySet.() -> Unit) { ?.apply(action) } +/** + * Applies the supplied action to the "proto" [SourceDirectorySet] extension on + * a receiver of type [AndroidSourceSet] for Android builds. + * + * @since 0.8.15 + * @usage + * ``` + * android { + * sourceSets { + * create("sample") { + * proto { + * srcDir("src/sample/protobuf") + * } + * } + * } + * } + * ``` + * + * @receiver [AndroidSourceSet] The Android source set for which the "proto" + * [SourceDirectorySet] extension will be configured + * + * @param action A configuration lambda to apply on a receiver of type [SourceDirectorySet] + * @return [Unit] + */ +fun AndroidSourceSet.proto(action: SourceDirectorySet.() -> Unit) { + (this as? ExtensionAware) + ?.extensions + ?.getByName("proto") + ?.let { it as? SourceDirectorySet } + ?.apply(action) +} + /** * Uses the supplied action to configure the [ExecutableLocator] for protoc. * diff --git a/src/test/groovy/com/google/protobuf/gradle/ProtobufKotlinDslPluginTest.groovy b/src/test/groovy/com/google/protobuf/gradle/ProtobufKotlinDslPluginTest.groovy index 6abe6c30..e9125d39 100644 --- a/src/test/groovy/com/google/protobuf/gradle/ProtobufKotlinDslPluginTest.groovy +++ b/src/test/groovy/com/google/protobuf/gradle/ProtobufKotlinDslPluginTest.groovy @@ -1,5 +1,7 @@ package com.google.protobuf.gradle +import static com.google.protobuf.gradle.ProtobufPluginTestHelper.buildAndroidProject + import groovy.transform.CompileDynamic import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner @@ -12,8 +14,8 @@ import spock.lang.Unroll */ @CompileDynamic class ProtobufKotlinDslPluginTest extends Specification { - // Current supported version is Gradle 5+. - private static final List GRADLE_VERSIONS = ["5.6", "6.0", "6.1"] + private static final List GRADLE_VERSIONS = ["5.6", "6.1.1", "6.5"] + private static final List ANDROID_PLUGIN_VERSION = ["3.5.0", "4.0.0", "4.1.0"] @Unroll void "testProjectKotlinDsl should be successfully executed (java-only project) [gradle #gradleVersion]"() { @@ -42,4 +44,33 @@ class ProtobufKotlinDslPluginTest extends Specification { where: gradleVersion << GRADLE_VERSIONS } + + @Unroll + void "testProjectAndroidKotlinDsl should be successfully executed [android #agpVersion, gradle #gradleVersion]"() { + given: "project from testProjectKotlinDsl" + File testProjectAndroidKotlinDslStaging = ProtobufPluginTestHelper.projectBuilder('testProjectAndroidKotlinDsl') + .copyDirs('testProjectAndroidKotlinDsl') + .build() + File testProjectLiteStaging = ProtobufPluginTestHelper.projectBuilder('testProjectLite') + .copyDirs('testProjectLite') + .build() + File mainProjectDir = ProtobufPluginTestHelper.projectBuilder('testProjectAndroidDslMain') + .copySubProjects(testProjectAndroidKotlinDslStaging, testProjectLiteStaging) + .withAndroidPlugin(agpVersion) + .build() + + when: "build is invoked" + BuildResult result = buildAndroidProject( + mainProjectDir, + gradleVersion, + "testProjectAndroidKotlinDsl:build" + ) + + then: "it succeed" + result.task(":testProjectAndroidKotlinDsl:build").outcome == TaskOutcome.SUCCESS + + where: + agpVersion << ANDROID_PLUGIN_VERSION + gradleVersion << GRADLE_VERSIONS + } } diff --git a/testProjectAndroidKotlinDsl/build.gradle.kts b/testProjectAndroidKotlinDsl/build.gradle.kts new file mode 100644 index 00000000..17f04916 --- /dev/null +++ b/testProjectAndroidKotlinDsl/build.gradle.kts @@ -0,0 +1,344 @@ +import com.android.build.gradle.api.BaseVariant +import com.google.protobuf.gradle.generateProtoTasks +import com.google.protobuf.gradle.id +import com.google.protobuf.gradle.ofBuildType +import com.google.protobuf.gradle.ofFlavor +import com.google.protobuf.gradle.ofNonTest +import com.google.protobuf.gradle.ofVariant +import com.google.protobuf.gradle.plugins +import com.google.protobuf.gradle.proto +import com.google.protobuf.gradle.protobuf +import com.google.protobuf.gradle.protoc + +plugins { + id("com.android.application") + id("com.google.protobuf") +} + +repositories { + maven("https://maven.google.com") + maven("https://plugins.gradle.org/m2/") +} + +android { + compileSdkVersion(26) + + defaultConfig { + applicationId = "io.grpc.helloworldexample" + minSdkVersion(7) + targetSdkVersion(23) + versionCode = 1 + versionName = "1.0" + } + + flavorDimensions("abi", "version") + + productFlavors { + create("freeapp") { + setDimension("version") + } + create("retailapp") { + setDimension("version") + } + create("x86") { + setDimension("abi") + } + create("arm") { + setDimension("abi") + } + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android.txt"), + "proguard-rules.pro" + ) + } + } + + sourceSets { + getByName("main") { + proto { + srcDir("src/main/protocolbuffers") + } + } + getByName("test") { + proto { + srcDir("src/test/protocolbuffers") + } + } + getByName("androidTest") { + proto { + srcDir("src/androidTest/protocolbuffers") + } + } + } + + 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") + isAbortOnError = 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 { + id("grpc") { + artifact = "io.grpc:protoc-gen-grpc-java:1.0.0-pre2" + } + id("javalite") { + artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" + } + } + generateProtoTasks { + all().forEach { task -> + task.plugins { + id("javalite") { } + } + } + ofNonTest().forEach { task -> + task.plugins { + id("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(":testProjectLite")) { + exclude(module = "protobuf-lite") + } + protobuf(files("lib/protos.jar")) + testCompile("junit:junit:4.12") +} + +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. + val test by tasks.existing + android.testVariants.forEach { testVariant -> + test { + dependsOn(testVariant.getJavaCompileProvider()) + } + } + test { + doLast { + val genProtoTasks = project.protobuf.protobuf.generateProtoTasks + + val genProtoTaskNames = setOf( + "generateArmFreeappDebugAndroidTestProto", + "generateArmFreeappDebugUnitTestProto", + "generateArmFreeappReleaseUnitTestProto", + "generateArmFreeappDebugProto", + "generateArmFreeappReleaseProto", + "generateArmRetailappDebugAndroidTestProto", + "generateArmRetailappDebugUnitTestProto", + "generateArmRetailappReleaseUnitTestProto", + "generateArmRetailappDebugProto", + "generateArmRetailappReleaseProto", + "generateX86FreeappDebugAndroidTestProto", + "generateX86FreeappDebugUnitTestProto", + "generateX86FreeappReleaseUnitTestProto", + "generateX86FreeappDebugProto", + "generateX86FreeappReleaseProto", + "generateX86RetailappDebugAndroidTestProto", + "generateX86RetailappDebugUnitTestProto", + "generateX86RetailappReleaseUnitTestProto", + "generateX86RetailappDebugProto", + "generateX86RetailappReleaseProto") + assert(genProtoTaskNames == genProtoTasks.all().map { it.name }.toSet()) + + val genProtoTaskNamesTests = setOf( + "generateArmFreeappDebugAndroidTestProto", + "generateArmFreeappDebugUnitTestProto", + "generateArmFreeappReleaseUnitTestProto", + "generateArmRetailappDebugAndroidTestProto", + "generateArmRetailappDebugUnitTestProto", + "generateArmRetailappReleaseUnitTestProto", + "generateX86FreeappDebugAndroidTestProto", + "generateX86FreeappDebugUnitTestProto", + "generateX86FreeappReleaseUnitTestProto", + "generateX86RetailappDebugAndroidTestProto", + "generateX86RetailappDebugUnitTestProto", + "generateX86RetailappReleaseUnitTestProto") + assert(genProtoTaskNamesTests == genProtoTasks.ofNonTest().map { it.name }.toSet()) + + + val genProtoTaskNamesNonTests = setOf( + "generateArmFreeappDebugProto", + "generateArmFreeappReleaseProto", + "generateArmRetailappDebugProto", + "generateArmRetailappReleaseProto", + "generateX86FreeappDebugProto", + "generateX86FreeappReleaseProto", + "generateX86RetailappDebugProto", + "generateX86RetailappReleaseProto") + assert(genProtoTaskNamesNonTests == genProtoTasks.ofNonTest().map { it.name }.toSet()) + + val genProtoTaskNamesFreeApp = setOf( + "generateArmFreeappDebugAndroidTestProto", + "generateArmFreeappDebugUnitTestProto", + "generateArmFreeappReleaseUnitTestProto", + "generateArmFreeappDebugProto", + "generateArmFreeappReleaseProto", + "generateX86FreeappDebugAndroidTestProto", + "generateX86FreeappDebugUnitTestProto", + "generateX86FreeappReleaseUnitTestProto", + "generateX86FreeappDebugProto", + "generateX86FreeappReleaseProto") + assert(genProtoTaskNamesFreeApp == genProtoTasks.ofFlavor("freeapp").map { it.name }.toSet()) + + val genProtoTaskNamesRetailApp = setOf( + "generateArmRetailappDebugAndroidTestProto", + "generateArmRetailappDebugUnitTestProto", + "generateArmRetailappReleaseUnitTestProto", + "generateArmRetailappDebugProto", + "generateArmRetailappReleaseProto", + "generateX86RetailappDebugAndroidTestProto", + "generateX86RetailappDebugUnitTestProto", + "generateX86RetailappReleaseUnitTestProto", + "generateX86RetailappDebugProto", + "generateX86RetailappReleaseProto") + assert(genProtoTaskNamesRetailApp == genProtoTasks.ofFlavor("retailapp").map { it.name }.toSet()) + + val genProtoTaskNamesX86 = setOf( + "generateX86FreeappDebugAndroidTestProto", + "generateX86FreeappDebugUnitTestProto", + "generateX86FreeappReleaseUnitTestProto", + "generateX86FreeappDebugProto", + "generateX86FreeappReleaseProto", + "generateX86RetailappDebugAndroidTestProto", + "generateX86RetailappDebugUnitTestProto", + "generateX86RetailappReleaseUnitTestProto", + "generateX86RetailappDebugProto", + "generateX86RetailappReleaseProto") + assert(genProtoTaskNamesX86 == genProtoTasks.ofFlavor("x86").map { it.name }.toSet()) + + val genProtoTaskNamesArm = setOf( + "generateArmFreeappDebugAndroidTestProto", + "generateArmFreeappDebugUnitTestProto", + "generateArmFreeappReleaseUnitTestProto", + "generateArmFreeappDebugProto", + "generateArmFreeappReleaseProto", + "generateArmRetailappDebugAndroidTestProto", + "generateArmRetailappDebugUnitTestProto", + "generateArmRetailappReleaseUnitTestProto", + "generateArmRetailappDebugProto", + "generateArmRetailappReleaseProto" + ) + assert(genProtoTaskNamesArm == genProtoTasks.ofFlavor("arm").map { it.name }.toSet()) + + val genProtoTaskNamesDebug = setOf( + "generateArmFreeappDebugAndroidTestProto", + "generateArmFreeappDebugUnitTestProto", + "generateArmFreeappDebugProto", + "generateArmRetailappDebugAndroidTestProto", + "generateArmRetailappDebugUnitTestProto", + "generateArmRetailappDebugProto", + "generateX86FreeappDebugAndroidTestProto", + "generateX86FreeappDebugUnitTestProto", + "generateX86FreeappDebugProto", + "generateX86RetailappDebugAndroidTestProto", + "generateX86RetailappDebugUnitTestProto", + "generateX86RetailappDebugProto") + assert(genProtoTaskNamesDebug == genProtoTasks.ofBuildType("debug").map { it.name }.toSet()) + + val genProtoTaskNamesRelease = setOf( + "generateArmFreeappReleaseProto", + "generateArmFreeappReleaseUnitTestProto", + "generateArmRetailappReleaseProto", + "generateArmRetailappReleaseUnitTestProto", + "generateX86FreeappReleaseProto", + "generateX86FreeappReleaseUnitTestProto", + "generateX86RetailappReleaseProto", + "generateX86RetailappReleaseUnitTestProto") + assert(genProtoTaskNamesRelease == genProtoTasks.ofBuildType("release").map { it.name }.toSet()) + + assert(setOf("generateX86FreeappDebugAndroidTestProto") == + genProtoTasks.ofVariant("x86FreeappDebugAndroidTest").map { it.name }.toSet()) + + android.applicationVariants.forEach { variant -> + assertJavaCompileHasProtoGeneratedDir(variant, listOf("javalite", "grpc")) + } + android.testVariants.forEach { variant -> + assertJavaCompileHasProtoGeneratedDir(variant, listOf("javalite")) + } + } + } +} + +fun assertJavaCompileHasProtoGeneratedDir(variant: BaseVariant, + codegenPlugins: Collection) { + assertJavaCompileHasProtoGeneratedDir(project, + variant.name, + variant.javaCompileProvider.get(), + codegenPlugins) +} + +fun assertJavaCompileHasProtoGeneratedDir( + project: Project, + variant: String, + compileJavaTask: JavaCompile, + codegenPlugins: Collection +) { + val baseDir = File("${project.buildDir}/generated/source/proto/$variant") + // The expected direct subdirectories under baseDir + val expectedDirs = codegenPlugins.map { codegenPlugin -> + File("${project.buildDir}/generated/source/proto/$variant/$codegenPlugin") + }.toSet() + + val actualDirs = mutableSetOf() + compileJavaTask.source.visit { + + // If the visited file is or is under a direct subdirectory of baseDir, add + // that subdirectory to actualDirs. + var file = this@visit.file + while (true) { + if (file.parentFile == baseDir) { + actualDirs.add(file) + } + if (file.parentFile == null) { + break + } + file = file.parentFile + } + } + assert(expectedDirs == actualDirs) +} diff --git a/testProjectAndroidKotlinDsl/lib/protos.jar b/testProjectAndroidKotlinDsl/lib/protos.jar new file mode 100644 index 00000000..18f117db Binary files /dev/null and b/testProjectAndroidKotlinDsl/lib/protos.jar differ diff --git a/testProjectAndroidKotlinDsl/proguard-rules.pro b/testProjectAndroidKotlinDsl/proguard-rules.pro new file mode 100644 index 00000000..3e659b91 --- /dev/null +++ b/testProjectAndroidKotlinDsl/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/thagikura/android-sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/testProjectAndroidKotlinDsl/settings.gradle.kts b/testProjectAndroidKotlinDsl/settings.gradle.kts new file mode 100644 index 00000000..e3c43499 --- /dev/null +++ b/testProjectAndroidKotlinDsl/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "testProjectAndroidKotlinDsl" +rootProject.buildFileName = "build.gradle.kts" diff --git a/testProjectAndroidKotlinDsl/src/androidTest/java/io/grpc/helloworldexample/MoreAndroidTestHelper.java b/testProjectAndroidKotlinDsl/src/androidTest/java/io/grpc/helloworldexample/MoreAndroidTestHelper.java new file mode 100644 index 00000000..b1db757e --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/androidTest/java/io/grpc/helloworldexample/MoreAndroidTestHelper.java @@ -0,0 +1,17 @@ +import com.google.protobuf.MessageLite; + +import java.util.ArrayList; +import java.util.List; + +public class MoreAndroidTestHelper { + public static List getDefaultInstances() { + ArrayList list = new ArrayList(); + // from src/main/protocolbuffers/more.proto + list.add(com.example.more.MoreMsg.getDefaultInstance()); + list.add(com.example.more.MoreFoo.getDefaultInstance()); + // from src/androidTest/porotocolbuffers/moresample.proto + list.add(com.example.more.MoreSampleMsg.getDefaultInstance()); + list.add(com.example.more.MoreSampleFoo.getDefaultInstance()); + return list; + } +} diff --git a/testProjectAndroidKotlinDsl/src/androidTest/java/io/grpc/helloworldexample/TestLibrary.java b/testProjectAndroidKotlinDsl/src/androidTest/java/io/grpc/helloworldexample/TestLibrary.java new file mode 100644 index 00000000..074a225a --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/androidTest/java/io/grpc/helloworldexample/TestLibrary.java @@ -0,0 +1,24 @@ +package io.grpc.helloworldexample; + +public class TestLibrary { + HelloworldActivity activity; + + // From src/androidTest/proto/sample.proto + com.example.tutorial.Msg msg; + + // From src/main/proto/helloworld.proto + Helloworld.HelloRequest request; + + // From dependency project (testProjectLite/testProjectAndroidLibrary): src/proto/messages.proto + io.grpc.testing.Messages.SimpleRequest simpleRequest; + + // From lib/protos.jar + com.google.protobuf.gradle.test.External.BlobMessage blobMessage; + + // TODO(zpencer): reflectively check that unit test protos are not visible + // This requires figuring out how to get androidTest to run. Currently the sources in androidTest + // are compiled, but test classes are not actually executed. + + TestLibrary() { + } +} diff --git a/testProjectAndroidKotlinDsl/src/androidTest/proto/sample.proto b/testProjectAndroidKotlinDsl/src/androidTest/proto/sample.proto new file mode 100644 index 00000000..70d912cb --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/androidTest/proto/sample.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +option java_package = "com.example.tutorial"; +option java_outer_classname = "OuterSample"; +option java_multiple_files = true; + +// From the main sourceSet +import "helloworld.proto"; + +message Msg { + string foo = 1; + SecondMsg blah = 2; +} + +message SecondMsg { + int32 blah = 1; + helloworld.HelloReply reply = 2; +} diff --git a/testProjectAndroidKotlinDsl/src/androidTest/protocolbuffers/moresample.proto b/testProjectAndroidKotlinDsl/src/androidTest/protocolbuffers/moresample.proto new file mode 100644 index 00000000..8a2da41b --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/androidTest/protocolbuffers/moresample.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "com.example.more"; +option java_outer_classname = "MoreSample"; +option java_multiple_files = true; + +message MoreSampleMsg { + string bar = 1; +} + +message MoreSampleFoo { + string stuff = 1; +} diff --git a/testProjectAndroidKotlinDsl/src/main/AndroidManifest.xml b/testProjectAndroidKotlinDsl/src/main/AndroidManifest.xml new file mode 100644 index 00000000..8c40f116 --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/testProjectAndroidKotlinDsl/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java b/testProjectAndroidKotlinDsl/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java new file mode 100644 index 00000000..b74bed0b --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java @@ -0,0 +1,90 @@ +package io.grpc.helloworldexample; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; +import android.text.TextUtils; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import io.grpc.ManagedChannel; +import io.grpc.helloworldexample.Helloworld.HelloReply; +import io.grpc.helloworldexample.Helloworld.HelloRequest; +import io.grpc.okhttp.OkHttpChannelBuilder; +import java.util.concurrent.TimeUnit; + +public class HelloworldActivity extends ActionBarActivity { + + private Button mSendButton; + private EditText mHostEdit; + private EditText mPortEdit; + private EditText mMessageEdit; + private TextView mResultText; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_helloworld); + mSendButton = (Button) findViewById(R.id.send_button); + mHostEdit = (EditText) findViewById(R.id.host_edit_text); + mPortEdit = (EditText) findViewById(R.id.port_edit_text); + mMessageEdit = (EditText) findViewById(R.id.message_edit_text); + mResultText = (TextView) findViewById(R.id.grpc_response_text); + } + + public void sendMessage(View view) { + ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)) + .hideSoftInputFromWindow(mHostEdit.getWindowToken(), 0); + mSendButton.setEnabled(false); + new GrpcTask().execute(); + } + + private class GrpcTask extends AsyncTask { + + private String mHost; + private String mMessage; + private int mPort; + private ManagedChannel mChannel; + + @Override + protected void onPreExecute() { + mHost = mHostEdit.getText().toString(); + mMessage = mMessageEdit.getText().toString(); + String portStr = mPortEdit.getText().toString(); + mPort = TextUtils.isEmpty(portStr) ? 0 : Integer.valueOf(portStr); + mResultText.setText(""); + } + + private String sayHello(ManagedChannel channel) { + GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel); + HelloRequest message = HelloRequest.newBuilder().setName(mMessage).build(); + HelloReply reply = stub.sayHello(message); + return reply.getMessage(); + } + + @Override + protected String doInBackground(Void... nothing) { + try { + mChannel = OkHttpChannelBuilder.forAddress(mHost, mPort).build(); + return sayHello(mChannel); + } catch (Exception e) { + + return "Failed... : " + e.getMessage(); + } + } + + @Override + protected void onPostExecute(String result) { + try { + mChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + mResultText.setText(result); + mSendButton.setEnabled(true); + } + } +} diff --git a/testProjectAndroidKotlinDsl/src/main/java/io/grpc/helloworldexample/MoreHelper.java b/testProjectAndroidKotlinDsl/src/main/java/io/grpc/helloworldexample/MoreHelper.java new file mode 100644 index 00000000..e6ef3804 --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/main/java/io/grpc/helloworldexample/MoreHelper.java @@ -0,0 +1,14 @@ +import com.google.protobuf.MessageLite; + +import java.util.ArrayList; +import java.util.List; + +public class MoreHelper { + public static List getDefaultInstances() { + ArrayList list = new ArrayList(); + // from src/main/protobuf/more.proto + list.add(com.example.more.MoreMsg.getDefaultInstance()); + list.add(com.example.more.MoreFoo.getDefaultInstance()); + return list; + } +} diff --git a/testProjectAndroidKotlinDsl/src/main/proto/helloworld.proto b/testProjectAndroidKotlinDsl/src/main/proto/helloworld.proto new file mode 100644 index 00000000..8de3aa8e --- /dev/null +++ b/testProjectAndroidKotlinDsl/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 testProject: src/nano/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/testProjectAndroidKotlinDsl/src/main/protocolbuffers/more.proto b/testProjectAndroidKotlinDsl/src/main/protocolbuffers/more.proto new file mode 100644 index 00000000..d986dbd2 --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/main/protocolbuffers/more.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +option java_package = "com.example.more"; +option java_outer_classname = "More"; +option java_multiple_files = true; + +message MoreMsg { + string bar = 1; +} + +message MoreFoo { + string stuff = 1; +} diff --git a/testProjectAndroidKotlinDsl/src/main/res/layout/activity_helloworld.xml b/testProjectAndroidKotlinDsl/src/main/res/layout/activity_helloworld.xml new file mode 100644 index 00000000..00ca04ce --- /dev/null +++ b/testProjectAndroidKotlinDsl/src/main/res/layout/activity_helloworld.xml @@ -0,0 +1,54 @@ + + + + + + + + + + +