aboutsummaryrefslogtreecommitdiffhomepage
path: root/grpc-common/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'grpc-common/java/android')
-rw-r--r--grpc-common/java/android/.gitignore21
-rw-r--r--grpc-common/java/android/README.md41
-rw-r--r--grpc-common/java/android/app/.gitignore1
-rw-r--r--grpc-common/java/android/app/build.gradle34
-rw-r--r--grpc-common/java/android/app/proguard-rules.pro17
-rw-r--r--grpc-common/java/android/app/src/main/AndroidManifest.xml22
-rw-r--r--grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/GreeterGrpc.java179
-rw-r--r--grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/Helloworld.java175
-rw-r--r--grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java90
-rw-r--r--grpc-common/java/android/app/src/main/res/layout/activity_helloworld.xml54
-rw-r--r--grpc-common/java/android/app/src/main/res/mipmap-hdpi/ic_launcher.pngbin0 -> 3418 bytes
-rw-r--r--grpc-common/java/android/app/src/main/res/mipmap-mdpi/ic_launcher.pngbin0 -> 2206 bytes
-rw-r--r--grpc-common/java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 4842 bytes
-rw-r--r--grpc-common/java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 7718 bytes
-rw-r--r--grpc-common/java/android/app/src/main/res/values/strings.xml3
-rw-r--r--grpc-common/java/android/build.gradle20
-rw-r--r--grpc-common/java/android/gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--grpc-common/java/android/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xgrpc-common/java/android/gradlew164
-rw-r--r--grpc-common/java/android/gradlew.bat90
-rw-r--r--grpc-common/java/android/settings.gradle1
21 files changed, 918 insertions, 0 deletions
diff --git a/grpc-common/java/android/.gitignore b/grpc-common/java/android/.gitignore
new file mode 100644
index 0000000000..6345b76a48
--- /dev/null
+++ b/grpc-common/java/android/.gitignore
@@ -0,0 +1,21 @@
+.gradle
+/local.properties
+/gradle.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+.idea/
+
+*.iml
+*.apk
+*.ap_
+*.dex
+*.class
+bin/
+gen/
+.gradle/
+/*/build/
+local.properties
+proguard/
+*.log
diff --git a/grpc-common/java/android/README.md b/grpc-common/java/android/README.md
new file mode 100644
index 0000000000..9de65a0267
--- /dev/null
+++ b/grpc-common/java/android/README.md
@@ -0,0 +1,41 @@
+gRPC Hello World Tutorial (Android Java)
+========================
+
+BACKGROUND
+-------------
+For this sample, we've already generated the server and client stubs from [helloworld.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto).
+
+PREREQUISITES
+-------------
+- [Java gRPC](https://github.com/grpc/grpc-java)
+
+- [Android Tutorial](https://developer.android.com/training/basics/firstapp/index.html) if you're new to Android development
+
+- We only have Android gRPC client in this example. Please follow examples in other languages to build and run a gRPC server.
+
+INSTALL
+-------
+**1 Clone the gRPC Java git repo**
+```sh
+$ git clone https://github.com/grpc/grpc-java
+```
+
+**2 Install gRPC Java, as described in [How to Build](https://github.com/grpc/grpc-java#how-to-build)**
+```sh
+$ # from this dir
+$ cd grpc-java
+$ # follow the instructions in 'How to Build'
+```
+
+**3 Prepare the app**
+- Clone this git repo
+```sh
+$ git clone https://github.com/grpc/grpc-common
+
+```
+
+**4 Install the app**
+```sh
+$ cd grpc-common/java/android
+$ ./gradlew installDebug
+```
diff --git a/grpc-common/java/android/app/.gitignore b/grpc-common/java/android/app/.gitignore
new file mode 100644
index 0000000000..796b96d1c4
--- /dev/null
+++ b/grpc-common/java/android/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/grpc-common/java/android/app/build.gradle b/grpc-common/java/android/app/build.gradle
new file mode 100644
index 0000000000..aedf4fe92a
--- /dev/null
+++ b/grpc-common/java/android/app/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 21
+ buildToolsVersion "21.1.2"
+
+ defaultConfig {
+ applicationId "io.grpc.helloworldexample"
+ minSdkVersion 7
+ targetSdkVersion 21
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile 'com.android.support:appcompat-v7:21.0.3'
+ compile 'com.google.code.findbugs:jsr305:3.0.0'
+ compile 'com.squareup.okhttp:okhttp:2.2.0'
+ compile 'com.google.guava:guava:18.0'
+
+ // You need to build the https://github.com/grpc/grpc-java
+ // to obtain these libraries below.
+ compile 'io.grpc:grpc-core:0.1.0-SNAPSHOT'
+ compile 'io.grpc:grpc-protobuf-nano:0.1.0-SNAPSHOT'
+ compile 'io.grpc:grpc-okhttp:0.1.0-SNAPSHOT'
+ compile 'io.grpc:grpc-stub:0.1.0-SNAPSHOT'
+}
diff --git a/grpc-common/java/android/app/proguard-rules.pro b/grpc-common/java/android/app/proguard-rules.pro
new file mode 100644
index 0000000000..3e659b91f3
--- /dev/null
+++ b/grpc-common/java/android/app/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/grpc-common/java/android/app/src/main/AndroidManifest.xml b/grpc-common/java/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..8c40f11684
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="io.grpc.helloworldexample" >
+
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/Base.V7.Theme.AppCompat.Light" >
+ <activity
+ android:name=".HelloworldActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/GreeterGrpc.java b/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/GreeterGrpc.java
new file mode 100644
index 0000000000..817c9fde8f
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/GreeterGrpc.java
@@ -0,0 +1,179 @@
+package io.grpc.helloworldexample;
+
+import java.io.IOException;
+
+import static io.grpc.stub.Calls.asyncUnaryCall;
+import static io.grpc.stub.Calls.blockingUnaryCall;
+import static io.grpc.stub.Calls.createMethodDescriptor;
+import static io.grpc.stub.Calls.unaryFutureCall;
+import static io.grpc.stub.ServerCalls.asyncUnaryRequestCall;
+import static io.grpc.stub.ServerCalls.createMethodDefinition;
+
+public class GreeterGrpc {
+
+ private static final io.grpc.stub.Method<Helloworld.HelloRequest,
+ Helloworld.HelloReply> METHOD_SAY_HELLO =
+ io.grpc.stub.Method.create(
+ io.grpc.MethodType.UNARY, "SayHello",
+ io.grpc.protobuf.nano.NanoUtils.<Helloworld.HelloRequest>marshaller(
+ new io.grpc.protobuf.nano.Parser<Helloworld.HelloRequest>() {
+ @Override
+ public Helloworld.HelloRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+ return Helloworld.HelloRequest.parseFrom(input);
+ }
+ }),
+ io.grpc.protobuf.nano.NanoUtils.<Helloworld.HelloReply>marshaller(
+ new io.grpc.protobuf.nano.Parser<Helloworld.HelloReply>() {
+ @Override
+ public Helloworld.HelloReply parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException {
+ return Helloworld.HelloReply.parseFrom(input);
+ }
+ }));
+
+ public static GreeterStub newStub(io.grpc.Channel channel) {
+ return new GreeterStub(channel, CONFIG);
+ }
+
+ public static GreeterBlockingStub newBlockingStub(
+ io.grpc.Channel channel) {
+ return new GreeterBlockingStub(channel, CONFIG);
+ }
+
+ public static GreeterFutureStub newFutureStub(
+ io.grpc.Channel channel) {
+ return new GreeterFutureStub(channel, CONFIG);
+ }
+
+ public static final GreeterServiceDescriptor CONFIG =
+ new GreeterServiceDescriptor();
+
+ public static class GreeterServiceDescriptor extends
+ io.grpc.stub.AbstractServiceDescriptor<GreeterServiceDescriptor> {
+ public final io.grpc.MethodDescriptor<Helloworld.HelloRequest,
+ Helloworld.HelloReply> sayHello;
+
+ private GreeterServiceDescriptor() {
+ sayHello = createMethodDescriptor(
+ "helloworld.Greeter", METHOD_SAY_HELLO);
+ }
+
+ private GreeterServiceDescriptor(
+ java.util.Map<java.lang.String, io.grpc.MethodDescriptor<?, ?>> methodMap) {
+ sayHello = (io.grpc.MethodDescriptor<Helloworld.HelloRequest,
+ Helloworld.HelloReply>) methodMap.get(
+ CONFIG.sayHello.getName());
+ }
+
+ @java.lang.Override
+ protected GreeterServiceDescriptor build(
+ java.util.Map<java.lang.String, io.grpc.MethodDescriptor<?, ?>> methodMap) {
+ return new GreeterServiceDescriptor(methodMap);
+ }
+
+ @java.lang.Override
+ public com.google.common.collect.ImmutableList<io.grpc.MethodDescriptor<?, ?>> methods() {
+ return com.google.common.collect.ImmutableList.<io.grpc.MethodDescriptor<?, ?>>of(
+ sayHello);
+ }
+ }
+
+ public static interface Greeter {
+
+ public void sayHello(Helloworld.HelloRequest request,
+ io.grpc.stub.StreamObserver<Helloworld.HelloReply> responseObserver);
+ }
+
+ public static interface GreeterBlockingClient {
+
+ public Helloworld.HelloReply sayHello(Helloworld.HelloRequest request);
+ }
+
+ public static interface GreeterFutureClient {
+
+ public com.google.common.util.concurrent.ListenableFuture<Helloworld.HelloReply> sayHello(
+ Helloworld.HelloRequest request);
+ }
+
+ public static class GreeterStub extends
+ io.grpc.stub.AbstractStub<GreeterStub, GreeterServiceDescriptor>
+ implements Greeter {
+ private GreeterStub(io.grpc.Channel channel,
+ GreeterServiceDescriptor config) {
+ super(channel, config);
+ }
+
+ @java.lang.Override
+ protected GreeterStub build(io.grpc.Channel channel,
+ GreeterServiceDescriptor config) {
+ return new GreeterStub(channel, config);
+ }
+
+ @java.lang.Override
+ public void sayHello(Helloworld.HelloRequest request,
+ io.grpc.stub.StreamObserver<Helloworld.HelloReply> responseObserver) {
+ asyncUnaryCall(
+ channel.newCall(config.sayHello), request, responseObserver);
+ }
+ }
+
+ public static class GreeterBlockingStub extends
+ io.grpc.stub.AbstractStub<GreeterBlockingStub, GreeterServiceDescriptor>
+ implements GreeterBlockingClient {
+ private GreeterBlockingStub(io.grpc.Channel channel,
+ GreeterServiceDescriptor config) {
+ super(channel, config);
+ }
+
+ @java.lang.Override
+ protected GreeterBlockingStub build(io.grpc.Channel channel,
+ GreeterServiceDescriptor config) {
+ return new GreeterBlockingStub(channel, config);
+ }
+
+ @java.lang.Override
+ public Helloworld.HelloReply sayHello(Helloworld.HelloRequest request) {
+ return blockingUnaryCall(
+ channel.newCall(config.sayHello), request);
+ }
+ }
+
+ public static class GreeterFutureStub extends
+ io.grpc.stub.AbstractStub<GreeterFutureStub, GreeterServiceDescriptor>
+ implements GreeterFutureClient {
+ private GreeterFutureStub(io.grpc.Channel channel,
+ GreeterServiceDescriptor config) {
+ super(channel, config);
+ }
+
+ @java.lang.Override
+ protected GreeterFutureStub build(io.grpc.Channel channel,
+ GreeterServiceDescriptor config) {
+ return new GreeterFutureStub(channel, config);
+ }
+
+ @java.lang.Override
+ public com.google.common.util.concurrent.ListenableFuture<Helloworld.HelloReply> sayHello(
+ Helloworld.HelloRequest request) {
+ return unaryFutureCall(
+ channel.newCall(config.sayHello), request);
+ }
+ }
+
+ public static io.grpc.ServerServiceDefinition bindService(
+ final Greeter serviceImpl) {
+ return io.grpc.ServerServiceDefinition.builder("helloworld.Greeter")
+ .addMethod(createMethodDefinition(
+ METHOD_SAY_HELLO,
+ asyncUnaryRequestCall(
+ new io.grpc.stub.ServerCalls.UnaryRequestMethod<
+ Helloworld.HelloRequest,
+ Helloworld.HelloReply>() {
+ @java.lang.Override
+ public void invoke(
+ Helloworld.HelloRequest request,
+ io.grpc.stub.StreamObserver<Helloworld.HelloReply> responseObserver) {
+ serviceImpl.sayHello(request, responseObserver);
+ }
+ }))).build();
+ }
+}
diff --git a/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/Helloworld.java b/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/Helloworld.java
new file mode 100644
index 0000000000..28da5a91d3
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/Helloworld.java
@@ -0,0 +1,175 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+
+package io.grpc.helloworldexample;
+
+@SuppressWarnings("hiding")
+public interface Helloworld {
+
+ public static final class HelloRequest extends
+ com.google.protobuf.nano.MessageNano {
+
+ private static volatile HelloRequest[] _emptyArray;
+ public static HelloRequest[] emptyArray() {
+ // Lazily initializes the empty array
+ if (_emptyArray == null) {
+ synchronized (
+ com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {
+ if (_emptyArray == null) {
+ _emptyArray = new HelloRequest[0];
+ }
+ }
+ }
+ return _emptyArray;
+ }
+
+ // optional string name = 1;
+ public java.lang.String name;
+
+ public HelloRequest() {
+ clear();
+ }
+
+ public HelloRequest clear() {
+ name = "";
+ cachedSize = -1;
+ return this;
+ }
+
+ @Override
+ public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)
+ throws java.io.IOException {
+ if (!this.name.equals("")) {
+ output.writeString(1, this.name);
+ }
+ super.writeTo(output);
+ }
+
+ @Override
+ protected int computeSerializedSize() {
+ int size = super.computeSerializedSize();
+ if (!this.name.equals("")) {
+ size += com.google.protobuf.nano.CodedOutputByteBufferNano
+ .computeStringSize(1, this.name);
+ }
+ return size;
+ }
+
+ @Override
+ public HelloRequest mergeFrom(
+ com.google.protobuf.nano.CodedInputByteBufferNano input)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ return this;
+ default: {
+ if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ this.name = input.readString();
+ break;
+ }
+ }
+ }
+ }
+
+ public static HelloRequest parseFrom(byte[] data)
+ throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {
+ return com.google.protobuf.nano.MessageNano.mergeFrom(new HelloRequest(), data);
+ }
+
+ public static HelloRequest parseFrom(
+ com.google.protobuf.nano.CodedInputByteBufferNano input)
+ throws java.io.IOException {
+ return new HelloRequest().mergeFrom(input);
+ }
+ }
+
+ public static final class HelloReply extends
+ com.google.protobuf.nano.MessageNano {
+
+ private static volatile HelloReply[] _emptyArray;
+ public static HelloReply[] emptyArray() {
+ // Lazily initializes the empty array
+ if (_emptyArray == null) {
+ synchronized (
+ com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {
+ if (_emptyArray == null) {
+ _emptyArray = new HelloReply[0];
+ }
+ }
+ }
+ return _emptyArray;
+ }
+
+ // optional string message = 1;
+ public java.lang.String message;
+
+ public HelloReply() {
+ clear();
+ }
+
+ public HelloReply clear() {
+ message = "";
+ cachedSize = -1;
+ return this;
+ }
+
+ @Override
+ public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)
+ throws java.io.IOException {
+ if (!this.message.equals("")) {
+ output.writeString(1, this.message);
+ }
+ super.writeTo(output);
+ }
+
+ @Override
+ protected int computeSerializedSize() {
+ int size = super.computeSerializedSize();
+ if (!this.message.equals("")) {
+ size += com.google.protobuf.nano.CodedOutputByteBufferNano
+ .computeStringSize(1, this.message);
+ }
+ return size;
+ }
+
+ @Override
+ public HelloReply mergeFrom(
+ com.google.protobuf.nano.CodedInputByteBufferNano input)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ return this;
+ default: {
+ if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ this.message = input.readString();
+ break;
+ }
+ }
+ }
+ }
+
+ public static HelloReply parseFrom(byte[] data)
+ throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {
+ return com.google.protobuf.nano.MessageNano.mergeFrom(new HelloReply(), data);
+ }
+
+ public static HelloReply parseFrom(
+ com.google.protobuf.nano.CodedInputByteBufferNano input)
+ throws java.io.IOException {
+ return new HelloReply().mergeFrom(input);
+ }
+ }
+} \ No newline at end of file
diff --git a/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java b/grpc-common/java/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java
new file mode 100644
index 0000000000..b6d734f9a9
--- /dev/null
+++ b/grpc-common/java/android/app/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 java.util.concurrent.TimeUnit;
+
+import io.grpc.ChannelImpl;
+import io.grpc.helloworldexample.Helloworld.HelloReply;
+import io.grpc.helloworldexample.Helloworld.HelloRequest;
+import io.grpc.transport.okhttp.OkHttpChannelBuilder;
+
+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<Void, Void, String> {
+ private String mHost;
+ private String mMessage;
+ private int mPort;
+ private ChannelImpl 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(ChannelImpl channel) {
+ GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
+ HelloRequest message = new HelloRequest();
+ message.name = mMessage;
+ HelloReply reply = stub.sayHello(message);
+ return reply.message;
+ }
+
+ @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().awaitTerminated(1, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ mResultText.setText(result);
+ mSendButton.setEnabled(true);
+ }
+ }
+} \ No newline at end of file
diff --git a/grpc-common/java/android/app/src/main/res/layout/activity_helloworld.xml b/grpc-common/java/android/app/src/main/res/layout/activity_helloworld.xml
new file mode 100644
index 0000000000..00ca04ce65
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/res/layout/activity_helloworld.xml
@@ -0,0 +1,54 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <EditText
+ android:id="@+id/host_edit_text"
+ android:layout_weight="2"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:hint="Enter Host" />
+ <EditText
+ android:id="@+id/port_edit_text"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"
+ android:hint="Enter Port" />
+ </LinearLayout>
+
+
+ <EditText
+ android:id="@+id/message_edit_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="Enter message to send" />
+
+ <Button
+ android:id="@+id/send_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="sendMessage"
+ android:text="Send Grpc Request" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
+ android:textSize="16dp"
+ android:text="Response:" />
+
+ <TextView
+ android:id="@+id/grpc_response_text"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:textSize="16dp" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/grpc-common/java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/grpc-common/java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..cde69bccce
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/grpc-common/java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/grpc-common/java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..c133a0cbd3
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/grpc-common/java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/grpc-common/java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..bfa42f0e7b
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/grpc-common/java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/grpc-common/java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..324e72cdd7
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/grpc-common/java/android/app/src/main/res/values/strings.xml b/grpc-common/java/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..64cb312d52
--- /dev/null
+++ b/grpc-common/java/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">GrpcHelloworldExample</string>
+</resources>
diff --git a/grpc-common/java/android/build.gradle b/grpc-common/java/android/build.gradle
new file mode 100644
index 0000000000..1bf89c9a52
--- /dev/null
+++ b/grpc-common/java/android/build.gradle
@@ -0,0 +1,20 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.1.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ mavenLocal()
+ }
+}
diff --git a/grpc-common/java/android/gradle/wrapper/gradle-wrapper.jar b/grpc-common/java/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000..8c0fb64a86
--- /dev/null
+++ b/grpc-common/java/android/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/grpc-common/java/android/gradle/wrapper/gradle-wrapper.properties b/grpc-common/java/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000..0c71e760dc
--- /dev/null
+++ b/grpc-common/java/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/grpc-common/java/android/gradlew b/grpc-common/java/android/gradlew
new file mode 100755
index 0000000000..91a7e269e1
--- /dev/null
+++ b/grpc-common/java/android/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/grpc-common/java/android/gradlew.bat b/grpc-common/java/android/gradlew.bat
new file mode 100644
index 0000000000..aec99730b4
--- /dev/null
+++ b/grpc-common/java/android/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/grpc-common/java/android/settings.gradle b/grpc-common/java/android/settings.gradle
new file mode 100644
index 0000000000..e7b4def49c
--- /dev/null
+++ b/grpc-common/java/android/settings.gradle
@@ -0,0 +1 @@
+include ':app'