aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiao Hang <rocking@google.com>2016-07-25 14:59:43 -0700
committerXiao Hang <rocking@google.com>2016-08-03 14:47:10 -0700
commit239d6ea299f812bd6a4fe9f5546b107aee753761 (patch)
treec8b92de26e43bbb5da8130f6ca58568f5c4740a0
parent7d464fcb0214235130efa10d464eea3a0a29a360 (diff)
downloadgrpc-grpc-java-239d6ea299f812bd6a4fe9f5546b107aee753761.tar.gz
Add android route guide example and move helloworld example to its own dir
-rw-r--r--examples/android/helloworld/.gitignore (renamed from examples/android/.gitignore)0
-rw-r--r--examples/android/helloworld/README.md (renamed from examples/android/README.md)0
-rw-r--r--examples/android/helloworld/app/build.gradle (renamed from examples/android/app/build.gradle)0
-rw-r--r--examples/android/helloworld/app/proguard-rules.pro (renamed from examples/android/app/proguard-rules.pro)0
-rw-r--r--examples/android/helloworld/app/src/main/AndroidManifest.xml (renamed from examples/android/app/src/main/AndroidManifest.xml)0
-rw-r--r--examples/android/helloworld/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java (renamed from examples/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java)0
-rw-r--r--examples/android/helloworld/app/src/main/proto/helloworld.proto (renamed from examples/android/app/src/main/proto/helloworld.proto)0
-rw-r--r--examples/android/helloworld/app/src/main/res/layout/activity_helloworld.xml (renamed from examples/android/app/src/main/res/layout/activity_helloworld.xml)0
-rw-r--r--examples/android/helloworld/app/src/main/res/mipmap-hdpi/ic_launcher.png (renamed from examples/android/app/src/main/res/mipmap-hdpi/ic_launcher.png)bin3418 -> 3418 bytes
-rw-r--r--examples/android/helloworld/app/src/main/res/mipmap-mdpi/ic_launcher.png (renamed from examples/android/app/src/main/res/mipmap-mdpi/ic_launcher.png)bin2206 -> 2206 bytes
-rw-r--r--examples/android/helloworld/app/src/main/res/mipmap-xhdpi/ic_launcher.png (renamed from examples/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png)bin4842 -> 4842 bytes
-rw-r--r--examples/android/helloworld/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (renamed from examples/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png)bin7718 -> 7718 bytes
-rw-r--r--examples/android/helloworld/app/src/main/res/values/strings.xml (renamed from examples/android/app/src/main/res/values/strings.xml)0
-rw-r--r--examples/android/helloworld/build.gradle (renamed from examples/android/build.gradle)0
-rw-r--r--examples/android/helloworld/gradle/wrapper/gradle-wrapper.jar (renamed from examples/android/gradle/wrapper/gradle-wrapper.jar)bin53638 -> 53638 bytes
-rw-r--r--examples/android/helloworld/gradle/wrapper/gradle-wrapper.properties (renamed from examples/android/gradle/wrapper/gradle-wrapper.properties)0
-rwxr-xr-xexamples/android/helloworld/gradlew (renamed from examples/android/gradlew)0
-rw-r--r--examples/android/helloworld/gradlew.bat (renamed from examples/android/gradlew.bat)0
-rw-r--r--examples/android/helloworld/settings.gradle (renamed from examples/android/settings.gradle)0
-rw-r--r--examples/android/routeguide/.gitignore21
-rw-r--r--examples/android/routeguide/app/.gitignore (renamed from examples/android/app/.gitignore)0
-rw-r--r--examples/android/routeguide/app/build.gradle67
-rw-r--r--examples/android/routeguide/app/proguard-rules.pro15
-rw-r--r--examples/android/routeguide/app/src/main/AndroidManifest.xml22
-rw-r--r--examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideActivity.java432
-rw-r--r--examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideUtil.java67
-rw-r--r--examples/android/routeguide/app/src/main/proto/route_guide.proto131
-rw-r--r--examples/android/routeguide/app/src/main/res/layout/activity_routeguide.xml81
-rw-r--r--examples/android/routeguide/app/src/main/res/mipmap-hdpi/ic_launcher.pngbin0 -> 3418 bytes
-rw-r--r--examples/android/routeguide/app/src/main/res/mipmap-mdpi/ic_launcher.pngbin0 -> 2206 bytes
-rw-r--r--examples/android/routeguide/app/src/main/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 4842 bytes
-rw-r--r--examples/android/routeguide/app/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 7718 bytes
-rw-r--r--examples/android/routeguide/app/src/main/res/mipmap-xxxhdpi/ic_launcher.pngbin0 -> 10486 bytes
-rw-r--r--examples/android/routeguide/app/src/main/res/values/colors.xml7
-rw-r--r--examples/android/routeguide/app/src/main/res/values/strings.xml3
-rw-r--r--examples/android/routeguide/app/src/main/res/values/styles.xml12
-rw-r--r--examples/android/routeguide/build.gradle25
-rw-r--r--examples/android/routeguide/gradle/wrapper/gradle-wrapper.jarbin0 -> 53638 bytes
-rw-r--r--examples/android/routeguide/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xexamples/android/routeguide/gradlew164
-rw-r--r--examples/android/routeguide/gradlew.bat90
-rw-r--r--examples/android/routeguide/settings.gradle1
42 files changed, 1144 insertions, 0 deletions
diff --git a/examples/android/.gitignore b/examples/android/helloworld/.gitignore
index 6345b76a4..6345b76a4 100644
--- a/examples/android/.gitignore
+++ b/examples/android/helloworld/.gitignore
diff --git a/examples/android/README.md b/examples/android/helloworld/README.md
index b5be842eb..b5be842eb 100644
--- a/examples/android/README.md
+++ b/examples/android/helloworld/README.md
diff --git a/examples/android/app/build.gradle b/examples/android/helloworld/app/build.gradle
index 43a0fd5cd..43a0fd5cd 100644
--- a/examples/android/app/build.gradle
+++ b/examples/android/helloworld/app/build.gradle
diff --git a/examples/android/app/proguard-rules.pro b/examples/android/helloworld/app/proguard-rules.pro
index 3b2e11a79..3b2e11a79 100644
--- a/examples/android/app/proguard-rules.pro
+++ b/examples/android/helloworld/app/proguard-rules.pro
diff --git a/examples/android/app/src/main/AndroidManifest.xml b/examples/android/helloworld/app/src/main/AndroidManifest.xml
index 8c40f1168..8c40f1168 100644
--- a/examples/android/app/src/main/AndroidManifest.xml
+++ b/examples/android/helloworld/app/src/main/AndroidManifest.xml
diff --git a/examples/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java b/examples/android/helloworld/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java
index 85e86eab8..85e86eab8 100644
--- a/examples/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java
+++ b/examples/android/helloworld/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java
diff --git a/examples/android/app/src/main/proto/helloworld.proto b/examples/android/helloworld/app/src/main/proto/helloworld.proto
index 0bee1fcfc..0bee1fcfc 100644
--- a/examples/android/app/src/main/proto/helloworld.proto
+++ b/examples/android/helloworld/app/src/main/proto/helloworld.proto
diff --git a/examples/android/app/src/main/res/layout/activity_helloworld.xml b/examples/android/helloworld/app/src/main/res/layout/activity_helloworld.xml
index 7627079c9..7627079c9 100644
--- a/examples/android/app/src/main/res/layout/activity_helloworld.xml
+++ b/examples/android/helloworld/app/src/main/res/layout/activity_helloworld.xml
diff --git a/examples/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/android/helloworld/app/src/main/res/mipmap-hdpi/ic_launcher.png
index cde69bccc..cde69bccc 100644
--- a/examples/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
+++ b/examples/android/helloworld/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/android/helloworld/app/src/main/res/mipmap-mdpi/ic_launcher.png
index c133a0cbd..c133a0cbd 100644
--- a/examples/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
+++ b/examples/android/helloworld/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/examples/android/helloworld/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index bfa42f0e7..bfa42f0e7 100644
--- a/examples/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
+++ b/examples/android/helloworld/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/android/helloworld/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 324e72cdd..324e72cdd 100644
--- a/examples/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
+++ b/examples/android/helloworld/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/app/src/main/res/values/strings.xml b/examples/android/helloworld/app/src/main/res/values/strings.xml
index 64cb312d5..64cb312d5 100644
--- a/examples/android/app/src/main/res/values/strings.xml
+++ b/examples/android/helloworld/app/src/main/res/values/strings.xml
diff --git a/examples/android/build.gradle b/examples/android/helloworld/build.gradle
index 493f43970..493f43970 100644
--- a/examples/android/build.gradle
+++ b/examples/android/helloworld/build.gradle
diff --git a/examples/android/gradle/wrapper/gradle-wrapper.jar b/examples/android/helloworld/gradle/wrapper/gradle-wrapper.jar
index 5ccda13e9..5ccda13e9 100644
--- a/examples/android/gradle/wrapper/gradle-wrapper.jar
+++ b/examples/android/helloworld/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/examples/android/gradle/wrapper/gradle-wrapper.properties b/examples/android/helloworld/gradle/wrapper/gradle-wrapper.properties
index ae20da0b8..ae20da0b8 100644
--- a/examples/android/gradle/wrapper/gradle-wrapper.properties
+++ b/examples/android/helloworld/gradle/wrapper/gradle-wrapper.properties
diff --git a/examples/android/gradlew b/examples/android/helloworld/gradlew
index 27309d923..27309d923 100755
--- a/examples/android/gradlew
+++ b/examples/android/helloworld/gradlew
diff --git a/examples/android/gradlew.bat b/examples/android/helloworld/gradlew.bat
index f6d5974e7..f6d5974e7 100644
--- a/examples/android/gradlew.bat
+++ b/examples/android/helloworld/gradlew.bat
diff --git a/examples/android/settings.gradle b/examples/android/helloworld/settings.gradle
index e7b4def49..e7b4def49 100644
--- a/examples/android/settings.gradle
+++ b/examples/android/helloworld/settings.gradle
diff --git a/examples/android/routeguide/.gitignore b/examples/android/routeguide/.gitignore
new file mode 100644
index 000000000..6345b76a4
--- /dev/null
+++ b/examples/android/routeguide/.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/examples/android/app/.gitignore b/examples/android/routeguide/app/.gitignore
index 796b96d1c..796b96d1c 100644
--- a/examples/android/app/.gitignore
+++ b/examples/android/routeguide/app/.gitignore
diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle
new file mode 100644
index 000000000..806fbc41a
--- /dev/null
+++ b/examples/android/routeguide/app/build.gradle
@@ -0,0 +1,67 @@
+apply plugin: 'com.android.application'
+apply plugin: 'com.google.protobuf'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "24.0.0"
+
+ defaultConfig {
+ applicationId "io.grpc.routeguideexample"
+ minSdkVersion 23
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+}
+
+protobuf {
+ protoc {
+ artifact = 'com.google.protobuf:protoc:3.0.0-beta-3'
+ }
+ plugins {
+ grpc {
+ artifact = 'io.grpc:protoc-gen-grpc-java:1.1.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ }
+ }
+ generateProtoTasks {
+ all().each { task ->
+ task.builtins {
+ // Javanano is installed by default, but needs to be removed to use protobuf lite..
+ remove javanano
+ java {
+ // Options added to --java_out
+ option 'lite'
+ }
+ }
+
+ task.plugins {
+ grpc {
+ // Options added to --grpc_out
+ option 'lite'
+ }
+ }
+ }
+ }
+}
+
+dependencies {
+ compile 'com.android.support:appcompat-v7:23.+'
+ compile 'com.google.code.findbugs:jsr305:3.0.0'
+ compile 'com.google.guava:guava:18.0'
+ compile 'com.squareup.okhttp:okhttp:2.2.0'
+
+ // You need to build grpc-java to obtain these libraries below.
+ compile 'io.grpc:grpc-okhttp:1.1.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ compile 'io.grpc:grpc-protobuf-lite:1.1.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ compile 'io.grpc:grpc-stub:1.1.0-SNAPSHOT' // CURRENT_GRPC_VERSION
+ compile 'javax.annotation:javax.annotation-api:1.2'
+}
diff --git a/examples/android/routeguide/app/proguard-rules.pro b/examples/android/routeguide/app/proguard-rules.pro
new file mode 100644
index 000000000..34ff0b3a7
--- /dev/null
+++ b/examples/android/routeguide/app/proguard-rules.pro
@@ -0,0 +1,15 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /usr/local/google/home/rocking/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:
+
+-dontwarn sun.misc.Unsafe
+-dontwarn com.google.common.**
+-dontwarn okio.**
+
diff --git a/examples/android/routeguide/app/src/main/AndroidManifest.xml b/examples/android/routeguide/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..d557afc08
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="io.grpc.routeguideexample">
+
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@mipmap/ic_launcher"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity
+ android:name=".RouteGuideActivity"
+ 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/examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideActivity.java b/examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideActivity.java
new file mode 100644
index 000000000..432e338ff
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideActivity.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2016, 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.
+ */
+
+package io.grpc.routeguideexample;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.text.TextUtils;
+import android.text.method.ScrollingMovementMethod;
+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.ManagedChannelBuilder;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
+import io.grpc.routeguideexample.RouteGuideGrpc.RouteGuideBlockingStub;
+import io.grpc.routeguideexample.RouteGuideGrpc.RouteGuideStub;
+import io.grpc.stub.StreamObserver;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class RouteGuideActivity extends AppCompatActivity {
+ private static final Logger logger = Logger.getLogger(RouteGuideActivity.class.getName());
+ private EditText mHostEdit;
+ private EditText mPortEdit;
+ private Button mStartRouteGuideButton;
+ private Button mExitRouteGuideButton;
+ private Button mGetFeatureButton;
+ private Button mListFeaturesButton;
+ private Button mRecordRouteButton;
+ private Button mRouteChatButton;
+ private TextView mResultText;
+
+ private ManagedChannel mChannel;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_routeguide);
+ mHostEdit = (EditText) findViewById(R.id.host_edit_text);
+ mPortEdit = (EditText) findViewById(R.id.port_edit_text);
+ mStartRouteGuideButton = (Button) findViewById(R.id.start_route_guide_button);
+ mExitRouteGuideButton = (Button) findViewById(R.id.exit_route_guide_button);
+ mGetFeatureButton = (Button) findViewById(R.id.get_feature_button);
+ mListFeaturesButton = (Button) findViewById(R.id.list_features_button);
+ mRecordRouteButton = (Button) findViewById(R.id.record_route_button);
+ mRouteChatButton = (Button) findViewById(R.id.route_chat_button);
+ mResultText = (TextView) findViewById(R.id.result_text);
+ mResultText.setMovementMethod(new ScrollingMovementMethod());
+ disableButtons();
+ }
+
+ public void startRouteGuide(View view) {
+ String host = mHostEdit.getText().toString();
+ String portStr = mPortEdit.getText().toString();
+ int port = TextUtils.isEmpty(portStr) ? 0 : Integer.valueOf(portStr);
+ ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
+ .hideSoftInputFromWindow(mHostEdit.getWindowToken(), 0);
+ mChannel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build();
+ mHostEdit.setEnabled(false);
+ mPortEdit.setEnabled(false);
+ mStartRouteGuideButton.setEnabled(false);
+ enableButtons();
+ }
+
+ public void exitRouteGuide(View view) {
+ mChannel.shutdown();
+ disableButtons();
+ mHostEdit.setEnabled(true);
+ mPortEdit.setEnabled(true);
+ mStartRouteGuideButton.setEnabled(true);
+ }
+
+ public void getFeature(View view) {
+ new GrpcTask(new GetFeatureRunnable()).execute();
+ }
+
+ public void listFeatures(View view) {
+ new GrpcTask(new ListFeaturesRunnable()).execute();
+ }
+
+ public void recordRoute(View view) {
+ new GrpcTask(new RecordRouteRunnable()).execute();
+ }
+
+ public void routeChat(View view) {
+ new GrpcTask(new RouteChatRunnable()).execute();
+ }
+
+ private void disableButtons() {
+ mGetFeatureButton.setEnabled(false);
+ mListFeaturesButton.setEnabled(false);
+ mRecordRouteButton.setEnabled(false);
+ mRouteChatButton.setEnabled(false);
+ mExitRouteGuideButton.setEnabled(false);
+ }
+
+ private void enableButtons() {
+ mExitRouteGuideButton.setEnabled(true);
+ mGetFeatureButton.setEnabled(true);
+ mListFeaturesButton.setEnabled(true);
+ mRecordRouteButton.setEnabled(true);
+ mRouteChatButton.setEnabled(true);
+ }
+
+ private class GrpcTask extends AsyncTask<Void, Void, String> {
+ private final GrpcRunnable mGrpc;
+
+ GrpcTask(GrpcRunnable grpc) {
+ this.mGrpc = grpc;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ mResultText.setText("");
+ disableButtons();
+ }
+
+ @Override
+ protected String doInBackground(Void... nothing) {
+ try {
+ String logs = mGrpc.run(RouteGuideGrpc.newBlockingStub(mChannel),
+ RouteGuideGrpc.newStub(mChannel));
+ return "Success!" + System.lineSeparator() + logs;
+ } catch (Exception e) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ return "Failed... : " + System.lineSeparator() + sw;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(String result) {
+ mResultText.setText(result);
+ enableButtons();
+ }
+ }
+
+ private interface GrpcRunnable {
+ /**
+ * Perform a grpc and return all the logs.
+ */
+ String run(RouteGuideBlockingStub blockingStub, RouteGuideStub asyncStub) throws Exception;
+ }
+
+ private class GetFeatureRunnable implements GrpcRunnable {
+ @Override
+ public String run(RouteGuideBlockingStub blockingStub, RouteGuideStub asyncStub)
+ throws Exception {
+ return getFeature(409146138, -746188906, blockingStub);
+ }
+
+ /**
+ * Blocking unary call example. Calls getFeature and prints the response.
+ */
+ private String getFeature(int lat, int lon, RouteGuideBlockingStub blockingStub)
+ throws StatusRuntimeException {
+ StringBuffer logs = new StringBuffer();
+ appendLogs(logs, "*** GetFeature: lat={0} lon={1}", lat, lon);
+
+ Point request = Point.newBuilder().setLatitude(lat).setLongitude(lon).build();
+
+ Feature feature;
+ feature = blockingStub.getFeature(request);
+ if (RouteGuideUtil.exists(feature)) {
+ appendLogs(logs, "Found feature called \"{0}\" at {1}, {2}",
+ feature.getName(),
+ RouteGuideUtil.getLatitude(feature.getLocation()),
+ RouteGuideUtil.getLongitude(feature.getLocation()));
+ } else {
+ appendLogs(logs, "Found no feature at {0}, {1}",
+ RouteGuideUtil.getLatitude(feature.getLocation()),
+ RouteGuideUtil.getLongitude(feature.getLocation()));
+ }
+ return logs.toString();
+ }
+ }
+
+ private class ListFeaturesRunnable implements GrpcRunnable {
+ @Override
+ public String run(RouteGuideBlockingStub blockingStub, RouteGuideStub asyncStub)
+ throws Exception {
+ return listFeatures(400000000, -750000000, 420000000, -730000000, blockingStub);
+ }
+
+ /**
+ * Blocking server-streaming example. Calls listFeatures with a rectangle of interest.
+ * Prints each response feature as it arrives.
+ */
+ private String listFeatures(int lowLat, int lowLon, int hiLat, int hiLon,
+ RouteGuideBlockingStub blockingStub) throws StatusRuntimeException {
+ StringBuffer logs = new StringBuffer("Result: ");
+ appendLogs(logs, "*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}",
+ lowLat, lowLon, hiLat, hiLon);
+
+ Rectangle request = Rectangle.newBuilder()
+ .setLo(Point.newBuilder().setLatitude(lowLat).setLongitude(lowLon).build())
+ .setHi(Point.newBuilder().setLatitude(hiLat).setLongitude(hiLon).build())
+ .build();
+ Iterator<Feature> features;
+ features = blockingStub.listFeatures(request);
+
+ while (features.hasNext()) {
+ Feature feature = features.next();
+ appendLogs(logs, feature.toString());
+ }
+ return logs.toString();
+ }
+ }
+
+ private class RecordRouteRunnable implements GrpcRunnable {
+ private Throwable failed;
+
+ @Override
+ public String run(RouteGuideBlockingStub blockingStub, RouteGuideStub asyncStub)
+ throws Exception {
+ List<Point> points = new ArrayList<Point>();
+ points.add(Point.newBuilder()
+ .setLatitude(407838351).setLongitude(-746143763).build());
+ points.add(Point.newBuilder()
+ .setLatitude(408122808).setLongitude(-743999179).build());
+ points.add(Point.newBuilder()
+ .setLatitude(413628156).setLongitude(-749015468).build());
+ return recordRoute(points, 5, asyncStub);
+ }
+
+ /**
+ * Async client-streaming example. Sends {@code numPoints} randomly chosen points from
+ * {@code features} with a variable delay in between. Prints the statistics when they are
+ * sent from the server.
+ */
+ private String recordRoute(List<Point> points, int numPoints, RouteGuideStub asyncStub)
+ throws InterruptedException, RuntimeException {
+ final StringBuffer logs = new StringBuffer();
+ appendLogs(logs, "*** RecordRoute");
+
+ final CountDownLatch finishLatch = new CountDownLatch(1);
+ StreamObserver<RouteSummary> responseObserver = new StreamObserver<RouteSummary>() {
+ @Override
+ public void onNext(RouteSummary summary) {
+ appendLogs(logs, "Finished trip with {0} points. Passed {1} features. "
+ + "Travelled {2} meters. It took {3} seconds.", summary.getPointCount(),
+ summary.getFeatureCount(), summary.getDistance(),
+ summary.getElapsedTime());
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ failed = t;
+ finishLatch.countDown();
+ }
+
+ @Override
+ public void onCompleted() {
+ appendLogs(logs, "Finished RecordRoute");
+ finishLatch.countDown();
+ }
+ };
+
+ StreamObserver<Point> requestObserver = asyncStub.recordRoute(responseObserver);
+ try {
+ // Send numPoints points randomly selected from the points list.
+ Random rand = new Random();
+ for (int i = 0; i < numPoints; ++i) {
+ int index = rand.nextInt(points.size());
+ Point point = points.get(index);
+ appendLogs(logs, "Visiting point {0}, {1}", RouteGuideUtil.getLatitude(point),
+ RouteGuideUtil.getLongitude(point));
+ requestObserver.onNext(point);
+ // Sleep for a bit before sending the next one.
+ Thread.sleep(rand.nextInt(1000) + 500);
+ if (finishLatch.getCount() == 0) {
+ // RPC completed or errored before we finished sending.
+ // Sending further requests won't error, but they will just be thrown away.
+ break;
+ }
+ }
+ } catch (RuntimeException e) {
+ // Cancel RPC
+ requestObserver.onError(e);
+ throw e;
+ }
+ // Mark the end of requests
+ requestObserver.onCompleted();
+
+ // Receiving happens asynchronously
+ if (!finishLatch.await(1, TimeUnit.MINUTES)) {
+ throw new RuntimeException(
+ "Could not finish rpc within 1 minute, the server is likely down");
+ }
+
+ if (failed != null) {
+ throw new RuntimeException(failed);
+ }
+ return logs.toString();
+ }
+ }
+
+ private class RouteChatRunnable implements GrpcRunnable {
+ private Throwable failed;
+
+ @Override
+ public String run(RouteGuideBlockingStub blockingStub, RouteGuideStub asyncStub)
+ throws Exception {
+ return routeChat(asyncStub);
+ }
+
+ /**
+ * Bi-directional example, which can only be asynchronous. Send some chat messages, and
+ * print any chat messages that are sent from the server.
+ */
+ private String routeChat(RouteGuideStub asyncStub) throws InterruptedException,
+ RuntimeException {
+ final StringBuffer logs = new StringBuffer();
+ appendLogs(logs, "*** RouteChat");
+ final CountDownLatch finishLatch = new CountDownLatch(1);
+ StreamObserver<RouteNote> requestObserver =
+ asyncStub.routeChat(new StreamObserver<RouteNote>() {
+ @Override
+ public void onNext(RouteNote note) {
+ appendLogs(logs, "Got message \"{0}\" at {1}, {2}", note.getMessage(),
+ note.getLocation().getLatitude(),
+ note.getLocation().getLongitude());
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ failed = t;
+ finishLatch.countDown();
+ }
+
+ @Override
+ public void onCompleted() {
+ appendLogs(logs,"Finished RouteChat");
+ finishLatch.countDown();
+ }
+ });
+
+ try {
+ RouteNote[] requests =
+ {newNote("First message", 0, 0), newNote("Second message", 0, 1),
+ newNote("Third message", 1, 0), newNote("Fourth message", 1, 1)};
+
+ for (RouteNote request : requests) {
+ appendLogs(logs, "Sending message \"{0}\" at {1}, {2}", request.getMessage(),
+ request.getLocation().getLatitude(),
+ request.getLocation().getLongitude());
+ requestObserver.onNext(request);
+ }
+ } catch (RuntimeException e) {
+ // Cancel RPC
+ requestObserver.onError(e);
+ throw e;
+ }
+ // Mark the end of requests
+ requestObserver.onCompleted();
+
+ // Receiving happens asynchronously
+ if (!finishLatch.await(1, TimeUnit.MINUTES)) {
+ throw new RuntimeException(
+ "Could not finish rpc within 1 minute, the server is likely down");
+ }
+
+ if (failed != null) {
+ throw new RuntimeException(failed);
+ }
+
+ return logs.toString();
+ }
+ }
+
+ private static void appendLogs(StringBuffer logs, String msg, Object... params) {
+ if (params.length > 0) {
+ logs.append(MessageFormat.format(msg, params));
+ } else {
+ logs.append(msg);
+ }
+ logs.append(System.lineSeparator());
+ }
+
+ private static RouteNote newNote(String message, int lat, int lon) {
+ return RouteNote.newBuilder().setMessage(message)
+ .setLocation(Point.newBuilder().setLatitude(lat).setLongitude(lon).build()).build();
+ }
+}
diff --git a/examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideUtil.java b/examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideUtil.java
new file mode 100644
index 000000000..775f1beb9
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/java/io/grpc/routeguideexample/RouteGuideUtil.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package io.grpc.routeguideexample;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.List;
+
+/**
+ * Common utilities for the RouteGuide demo.
+ */
+public class RouteGuideUtil {
+ private static final double COORD_FACTOR = 1e7;
+
+ /**
+ * Gets the latitude for the given point.
+ */
+ public static double getLatitude(Point location) {
+ return location.getLatitude() / COORD_FACTOR;
+ }
+
+ /**
+ * Gets the longitude for the given point.
+ */
+ public static double getLongitude(Point location) {
+ return location.getLongitude() / COORD_FACTOR;
+ }
+
+ /**
+ * Indicates whether the given feature exists (i.e. has a valid name).
+ */
+ public static boolean exists(Feature feature) {
+ return feature != null && !feature.getName().isEmpty();
+ }
+}
diff --git a/examples/android/routeguide/app/src/main/proto/route_guide.proto b/examples/android/routeguide/app/src/main/proto/route_guide.proto
new file mode 100644
index 000000000..f765fc5e1
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/proto/route_guide.proto
@@ -0,0 +1,131 @@
+// 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";
+
+option java_multiple_files = true;
+option java_package = "io.grpc.routeguideexample";
+option java_outer_classname = "RouteGuideProto";
+option objc_class_prefix = "RTG";
+
+package routeguide;
+
+// Interface exported by the server.
+service RouteGuide {
+ // A simple RPC.
+ //
+ // Obtains the feature at a given position.
+ //
+ // A feature with an empty name is returned if there's no feature at the given
+ // position.
+ rpc GetFeature(Point) returns (Feature) {}
+
+ // A server-to-client streaming RPC.
+ //
+ // Obtains the Features available within the given Rectangle. Results are
+ // streamed rather than returned at once (e.g. in a response message with a
+ // repeated field), as the rectangle may cover a large area and contain a
+ // huge number of features.
+ rpc ListFeatures(Rectangle) returns (stream Feature) {}
+
+ // A client-to-server streaming RPC.
+ //
+ // Accepts a stream of Points on a route being traversed, returning a
+ // RouteSummary when traversal is completed.
+ rpc RecordRoute(stream Point) returns (RouteSummary) {}
+
+ // A Bidirectional streaming RPC.
+ //
+ // Accepts a stream of RouteNotes sent while a route is being traversed,
+ // while receiving other RouteNotes (e.g. from other users).
+ rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
+}
+
+// Points are represented as latitude-longitude pairs in the E7 representation
+// (degrees multiplied by 10**7 and rounded to the nearest integer).
+// Latitudes should be in the range +/- 90 degrees and longitude should be in
+// the range +/- 180 degrees (inclusive).
+message Point {
+ int32 latitude = 1;
+ int32 longitude = 2;
+}
+
+// A latitude-longitude rectangle, represented as two diagonally opposite
+// points "lo" and "hi".
+message Rectangle {
+ // One corner of the rectangle.
+ Point lo = 1;
+
+ // The other corner of the rectangle.
+ Point hi = 2;
+}
+
+// A feature names something at a given point.
+//
+// If a feature could not be named, the name is empty.
+message Feature {
+ // The name of the feature.
+ string name = 1;
+
+ // The point where the feature is detected.
+ Point location = 2;
+}
+
+// Not used in the RPC. Instead, this is here for the form serialized to disk.
+message FeatureDatabase {
+ repeated Feature feature = 1;
+}
+
+// A RouteNote is a message sent while at a given point.
+message RouteNote {
+ // The location from which the message is sent.
+ Point location = 1;
+
+ // The message to be sent.
+ string message = 2;
+}
+
+// A RouteSummary is received in response to a RecordRoute rpc.
+//
+// It contains the number of individual points received, the number of
+// detected features, and the total distance covered as the cumulative sum of
+// the distance between each point.
+message RouteSummary {
+ // The number of points received.
+ int32 point_count = 1;
+
+ // The number of known features passed while traversing the route.
+ int32 feature_count = 2;
+
+ // The distance covered in metres.
+ int32 distance = 3;
+
+ // The duration of the traversal in seconds.
+ int32 elapsed_time = 4;
+}
diff --git a/examples/android/routeguide/app/src/main/res/layout/activity_routeguide.xml b/examples/android/routeguide/app/src/main/res/layout/activity_routeguide.xml
new file mode 100644
index 000000000..4b73bf34a
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/layout/activity_routeguide.xml
@@ -0,0 +1,81 @@
+<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=".RouteGuideActivity"
+ 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>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/start_route_guide_button"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:onClick="startRouteGuide"
+ android:text="Start Route Guide" />
+ <Button
+ android:id="@+id/exit_route_guide_button"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:onClick="exitRouteGuide"
+ android:text="Exit Route Guide" />
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/get_feature_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="getFeature"
+ android:text="Get Feature" />
+
+ <Button
+ android:id="@+id/list_features_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="listFeatures"
+ android:text="List Features" />
+
+ <Button
+ android:id="@+id/record_route_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="recordRoute"
+ android:text="Record Route" />
+
+ <Button
+ android:id="@+id/route_chat_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="routeChat"
+ android:text="Route Chat" />
+
+ <TextView
+ android:id="@+id/result_text"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars = "vertical"
+ android:textSize="16sp" />
+
+</LinearLayout>
diff --git a/examples/android/routeguide/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/android/routeguide/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..cde69bccc
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/routeguide/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/android/routeguide/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..c133a0cbd
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/routeguide/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/examples/android/routeguide/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..bfa42f0e7
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/routeguide/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/android/routeguide/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..324e72cdd
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/routeguide/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/examples/android/routeguide/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..aee44e138
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/examples/android/routeguide/app/src/main/res/values/colors.xml b/examples/android/routeguide/app/src/main/res/values/colors.xml
new file mode 100644
index 000000000..1c10bfe70
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/values/colors.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+</resources>
+
diff --git a/examples/android/routeguide/app/src/main/res/values/strings.xml b/examples/android/routeguide/app/src/main/res/values/strings.xml
new file mode 100644
index 000000000..7b287fc8d
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">RouteGuideExample</string>
+</resources>
diff --git a/examples/android/routeguide/app/src/main/res/values/styles.xml b/examples/android/routeguide/app/src/main/res/values/styles.xml
new file mode 100644
index 000000000..7312f6a3b
--- /dev/null
+++ b/examples/android/routeguide/app/src/main/res/values/styles.xml
@@ -0,0 +1,12 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ </style>
+
+</resources>
+
diff --git a/examples/android/routeguide/build.gradle b/examples/android/routeguide/build.gradle
new file mode 100644
index 000000000..187d26b0e
--- /dev/null
+++ b/examples/android/routeguide/build.gradle
@@ -0,0 +1,25 @@
+// 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:2.1.2'
+ classpath "com.google.protobuf:protobuf-gradle-plugin:0.7.7"
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ mavenLocal()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/examples/android/routeguide/gradle/wrapper/gradle-wrapper.jar b/examples/android/routeguide/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..5ccda13e9
--- /dev/null
+++ b/examples/android/routeguide/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/examples/android/routeguide/gradle/wrapper/gradle-wrapper.properties b/examples/android/routeguide/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ae20da0b8
--- /dev/null
+++ b/examples/android/routeguide/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sat May 07 11:11:12 PDT 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip
diff --git a/examples/android/routeguide/gradlew b/examples/android/routeguide/gradlew
new file mode 100755
index 000000000..27309d923
--- /dev/null
+++ b/examples/android/routeguide/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# 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\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# 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
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+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" -a "$nonstop" = "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"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # 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/examples/android/routeguide/gradlew.bat b/examples/android/routeguide/gradlew.bat
new file mode 100644
index 000000000..f6d5974e7
--- /dev/null
+++ b/examples/android/routeguide/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
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@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=
+
+@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 Windows 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/examples/android/routeguide/settings.gradle b/examples/android/routeguide/settings.gradle
new file mode 100644
index 000000000..e7b4def49
--- /dev/null
+++ b/examples/android/routeguide/settings.gradle
@@ -0,0 +1 @@
+include ':app'