9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Hello GRPC
3 | Hello GRPC world!
4 | Settings
5 | Hello server!
6 | GRPC server host
7 | port
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/lovoo/ubuntudroid/hellogrpc/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.lovoo.ubuntudroid.hellogrpc;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest () {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/Sven.Bendel/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "23.0.0 rc2"
6 |
7 | defaultConfig {
8 | applicationId "com.lovoo.ubuntudroid.hellogrpc"
9 | minSdkVersion 21
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 | lintOptions {
22 | disable 'InvalidPackage'
23 | }
24 | }
25 |
26 | dependencies {
27 | compile fileTree(dir: 'libs', include: ['*.jar'])
28 | //compile fileTree(dir: '../lib_hello_grpc/libs', include: ['grpc-all-0.7.1.jar'])
29 | compile project(':lib_hello_grpc')
30 | compile 'com.jakewharton:butterknife:7.0.0'
31 | compile 'com.squareup.okhttp:okhttp:2.4.0'
32 | compile 'com.squareup.picasso:picasso:2.5.2'
33 | }
34 |
--------------------------------------------------------------------------------
/lib_hello_grpc/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | }
5 | dependencies {
6 | classpath 'com.google.protobuf:protobuf-gradle-plugin:0.4.1'
7 | }
8 | }
9 |
10 | apply plugin: 'java'
11 | apply plugin: 'com.google.protobuf'
12 |
13 | //region protobuf code generation
14 | sourceSets {
15 | main {
16 | proto {
17 | plugins {
18 | grpc { }
19 | }
20 | }
21 | }
22 | }
23 |
24 | protocDep = "com.google.protobuf:protoc:3.0.0-alpha-3"
25 | protobufNativeCodeGenPluginDeps = ["grpc:io.grpc:protoc-gen-grpc-java:0.7.1"]
26 |
27 | apply plugin: 'idea'
28 |
29 | // Allow intellij projects to refer to generated-sources
30 | idea {
31 | module {
32 | // The whole build dir is excluded by default, but we need build/generated-sources,
33 | // which contains the generated proto classes.
34 | excludeDirs = [file('.gradle')]
35 | if (buildDir.exists()) {
36 | excludeDirs += files(buildDir.listFiles())
37 | excludeDirs -= file("$buildDir/generated-sources")
38 | }
39 | }
40 | }
41 | //endregion
42 |
43 | dependencies {
44 | compile fileTree(dir: 'libs', include: ['*.jar'])
45 |
46 | compile 'com.google.guava:guava:18.0'
47 | compile 'com.google.protobuf:protobuf-java:3.0.0-alpha-2'
48 | compile 'com.google.code.findbugs:jsr305:3.0.0'
49 | // we cannot use the following dependency as com.google.auth:google-auth-library-oauth2-http:0.1.0 seems to be unavailable right now
50 | //compile 'io.grpc:grpc-all:0.7.1'
51 |
52 | // these libraries are necessary for the server
53 | compile 'io.netty:netty-all:4.1.0.Beta5'
54 | compile 'com.twitter:hpack:0.11.0'
55 | }
--------------------------------------------------------------------------------
/lib_hello_grpc/src/main/proto/hello.proto:
--------------------------------------------------------------------------------
1 | // Copyright 2015, Google Inc.
2 | // All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the names of its
15 | // contributors may be used to endorse or promote products derived from
16 | // this software without specific prior written permission.
17 | //
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | syntax = "proto3";
31 |
32 | package helloworld;
33 |
34 | option java_multiple_files = true;
35 | option java_package = "io.grpc.examples.helloworld";
36 | option java_outer_classname = "HelloWorldProto";
37 |
38 | // The greeting service definition.
39 | service Greeter {
40 | // Sends a greeting
41 | rpc SayHello (HelloRequest) returns (HelloResponse) {}
42 | }
43 |
44 | // The request message containing the user's name.
45 | message HelloRequest {
46 | string name = 1;
47 | }
48 |
49 | // The response message containing the greetings
50 | message HelloResponse {
51 | string message = 1;
52 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
16 |
17 |
24 |
25 |
32 |
33 |
34 |
42 |
43 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lovoo/ubuntudroid/hellogrpc/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.lovoo.ubuntudroid.hellogrpc;
2 |
3 | /**
4 | * Copyright (c) 2015, LOVOO GmbH
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | *
10 | * Redistributions of source code must retain the above copyright notice, this
11 | * list of conditions and the following disclaimer.
12 | *
13 | * Redistributions in binary form must reproduce the above copyright notice,
14 | * this list of conditions and the following disclaimer in the documentation
15 | * and/or other materials provided with the distribution.
16 | *
17 | * Neither the name of LOVOO GmbH nor the names of its
18 | * contributors may be used to endorse or promote products derived from
19 | * this software without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 |
33 | import android.app.Activity;
34 | import android.os.Bundle;
35 | import android.view.Menu;
36 | import android.view.MenuItem;
37 |
38 | /**
39 | * Just a very simple activity acting as a holder for the fragment which is responsible for
40 | * showing the GRPC client UI to the user.
41 | *
42 | * Created by ubuntudroid.
43 | */
44 | public class MainActivity extends Activity {
45 |
46 | @Override
47 | protected void onCreate ( Bundle savedInstanceState ) {
48 | super.onCreate(savedInstanceState);
49 | setContentView(R.layout.activity_main);
50 | }
51 |
52 |
53 | @Override
54 | public boolean onCreateOptionsMenu ( Menu menu ) {
55 | // Inflate the menu; this adds items to the action bar if it is present.
56 | getMenuInflater().inflate(R.menu.menu_main, menu);
57 | return true;
58 | }
59 |
60 | @Override
61 | public boolean onOptionsItemSelected ( MenuItem item ) {
62 | // Handle action bar item clicks here. The action bar will
63 | // automatically handle clicks on the Home/Up button, so long
64 | // as you specify a parent activity in AndroidManifest.xml.
65 | int id = item.getItemId();
66 |
67 | //noinspection SimplifiableIfStatement
68 | if (id == R.id.action_settings) {
69 | return true;
70 | }
71 |
72 | return super.onOptionsItemSelected(item);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | GRPC Android Demo
2 | =================
3 |
4 | About
5 | -----
6 |
7 | As there seems to be currently no ready-to-go example for an Android application communicating with
8 | a GRPC server which doesn't involve setting up a boatload of tools we decided to create this simple
9 | demo project which contains a simple GRPC Java server and a matching Android client.
10 |
11 | Changing the protocol
12 | ---------------------
13 |
14 | The setup contains working code generation so feel free to change the proto file in lib_hello_grpc.
15 | Upon the next build the necessary classes are generated by the gradle grpc plugin. You'll just have
16 | to adapt the server and client code to the newly generated GRPC java classes. The compiler will
17 | point you to the locations you have to change by means of compilitation errors.
18 |
19 | It is advisable to clean the lib_hello_grpc module by calling `./gradlew :lib_hello_grpc:clean` after
20 | having removed or changed the name of a service or a message. This will remove all stale generated
21 | classes and prevent compilation errors within the other generated classes.
22 |
23 | Setup
24 | -----
25 |
26 | The following documentation assumes that you've installed Android Studio. Import the project via
27 | gradle.
28 |
29 | Running the server
30 | ------------------
31 |
32 | By default the server runs on port 8080, but you may change that via command line arguments or
33 | directly in the code.
34 |
35 | Run the server from Android Studio by right-clicking the `Server.java` in the `lib_hello_grpc`
36 | module. This also creates a suitable run configuration which you can use to run the server again
37 | later. After importing the project here will be errors which are automatically resolved during the first
38 | build via code generation. Make sure, that only one server instance runs at a time (at least if you
39 | attempt to use the same port).
40 |
41 | Incoming requests are logged on stdout.
42 |
43 | Running the client
44 | ------------------
45 |
46 | While importing the project to Android Studio via gradle the IDE automatically generates a run
47 | configuration for the app which you can use to install it on your device or emulator.
48 |
49 | In the app first type in the hostname and the port of your server. Then click on the `HELLO SERVER!`
50 | button to execute a request against your GRPC server instance. In case of success the server will
51 | reply with `Hello Android`.
52 |
53 | If you did everything correctly it should look something like this:
54 |
55 |
56 |
57 | Licence
58 | -------
59 |
60 | Copyright (c) 2015, LOVOO GmbH
61 | All rights reserved.
62 |
63 | Redistribution and use in source and binary forms, with or without
64 | modification, are permitted provided that the following conditions are met:
65 |
66 | * Redistributions of source code must retain the above copyright notice, this
67 | list of conditions and the following disclaimer.
68 |
69 | * Redistributions in binary form must reproduce the above copyright notice,
70 | this list of conditions and the following disclaimer in the documentation
71 | and/or other materials provided with the distribution.
72 |
73 | * Neither the name of LOVOO GmbH nor the names of its
74 | contributors may be used to endorse or promote products derived from
75 | this software without specific prior written permission.
76 |
77 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
78 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
80 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
81 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
83 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOEVER
84 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
85 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
86 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
87 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lovoo/ubuntudroid/hellogrpc/MainActivityFragment.java:
--------------------------------------------------------------------------------
1 | package com.lovoo.ubuntudroid.hellogrpc;
2 |
3 | /**
4 | * Copyright (c) 2015, LOVOO GmbH
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | *
10 | * Redistributions of source code must retain the above copyright notice, this
11 | * list of conditions and the following disclaimer.
12 | *
13 | * Redistributions in binary form must reproduce the above copyright notice,
14 | * this list of conditions and the following disclaimer in the documentation
15 | * and/or other materials provided with the distribution.
16 | *
17 | * Neither the name of LOVOO GmbH nor the names of its
18 | * contributors may be used to endorse or promote products derived from
19 | * this software without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 |
33 | import android.app.Fragment;
34 | import android.os.AsyncTask;
35 | import android.os.Bundle;
36 | import android.text.TextUtils;
37 | import android.text.method.ScrollingMovementMethod;
38 | import android.view.LayoutInflater;
39 | import android.view.View;
40 | import android.view.ViewGroup;
41 | import android.widget.Button;
42 | import android.widget.EditText;
43 | import android.widget.TextView;
44 |
45 | import com.google.common.util.concurrent.UncheckedExecutionException;
46 |
47 | import java.util.concurrent.TimeUnit;
48 |
49 | import butterknife.Bind;
50 | import butterknife.ButterKnife;
51 | import butterknife.OnClick;
52 | import io.grpc.ChannelImpl;
53 | import io.grpc.examples.helloworld.GreeterGrpc;
54 | import io.grpc.examples.helloworld.HelloRequest;
55 | import io.grpc.examples.helloworld.HelloResponse;
56 | import io.grpc.transport.okhttp.OkHttpChannelBuilder;
57 |
58 | /**
59 | * This Fragment displays UI to handle communication with the bundled GRPC server.
60 | *
61 | * The user may enter server host/IP of the server and execute requests while examining the log
62 | * file.
63 | *
64 | * In a real implementation communication wouldn't be done here, but in a dedicated controller/job
65 | * class.
66 | *
67 | * Created by ubuntudroid.
68 | */
69 | public class MainActivityFragment extends Fragment {
70 |
71 | @Bind(R.id.main_edit_server_host)
72 | EditText mServerHostEditText;
73 |
74 | @Bind(R.id.main_edit_server_port)
75 | EditText mServerPortEditText;
76 |
77 | @Bind(R.id.main_text_log)
78 | TextView mLogText;
79 |
80 | @Bind(R.id.main_button_send_request)
81 | Button mSendButton;
82 |
83 | private ChannelImpl mChannel;
84 |
85 | public MainActivityFragment () {
86 | }
87 |
88 | @Override
89 | public View onCreateView ( LayoutInflater inflater, ViewGroup container,
90 | Bundle savedInstanceState ) {
91 | View view = inflater.inflate(R.layout.fragment_main, container, false);
92 | ButterKnife.bind(this, view);
93 |
94 | /*
95 | makes log text view scroll automatically as new lines are added, just works in combination
96 | with gravity:bottom
97 | */
98 | mLogText.setMovementMethod(new ScrollingMovementMethod());
99 |
100 | return view;
101 | }
102 |
103 | @Override
104 | public void onDestroyView () {
105 | super.onDestroyView();
106 | ButterKnife.unbind(this);
107 | shutdownChannel();
108 | }
109 |
110 | @OnClick(R.id.main_button_send_request)
111 | public void sendRequestToServer () {
112 | new SendHelloTask().execute();
113 | }
114 |
115 | private void log ( String logMessage ) {
116 | mLogText.append("\n" + logMessage);
117 | }
118 |
119 | private void shutdownChannel () {
120 | if (mChannel != null) {
121 | try {
122 | mChannel.shutdown().awaitTerminated(1, TimeUnit.SECONDS);
123 | } catch (InterruptedException e) {
124 | // FIXME this call seems fishy as it interrupts the main thread
125 | Thread.currentThread().interrupt();
126 | }
127 | }
128 | mChannel = null;
129 | }
130 |
131 | private class SendHelloTask extends AsyncTask {
132 |
133 | private String mHost = "";
134 | private int mPort = -1;
135 |
136 | @Override
137 | protected void onPreExecute () {
138 | mSendButton.setEnabled(false);
139 |
140 | String newHost = mServerHostEditText.getText().toString();
141 | if (!mHost.equals(newHost)) {
142 | mHost = newHost;
143 | shutdownChannel();
144 | }
145 | if (TextUtils.isEmpty(mHost)) {
146 | log("ERROR: empty host name!");
147 | cancel(true);
148 | return;
149 | }
150 |
151 | String portString = mServerPortEditText.getText().toString();
152 | if (TextUtils.isEmpty(portString)) {
153 | log("ERROR: empty port");
154 | cancel(true);
155 | return;
156 | }
157 |
158 | try {
159 | int newPort = Integer.parseInt(portString);
160 | if (mPort != newPort) {
161 | mPort = newPort;
162 | shutdownChannel();
163 | }
164 | } catch (NumberFormatException ex) {
165 | log("ERROR: invalid port");
166 | cancel(true);
167 | return;
168 | }
169 |
170 | log("Sending hello to server...");
171 | }
172 |
173 | @Override
174 | protected String doInBackground ( Void... params ) {
175 | try {
176 | if (mChannel == null) {
177 | mChannel = OkHttpChannelBuilder.forAddress(mHost, mPort).build();
178 | }
179 | GreeterGrpc.GreeterBlockingStub greeterStub = GreeterGrpc.newBlockingStub(
180 | mChannel);
181 | HelloRequest helloRequest = HelloRequest.newBuilder().setName("Android").build();
182 |
183 | HelloResponse helloResponse = greeterStub.sayHello(helloRequest);
184 | return "SERVER: " + helloResponse.getMessage();
185 | } catch ( SecurityException | UncheckedExecutionException e ) {
186 | e.printStackTrace();
187 | return "ERROR: " + e.getMessage();
188 | }
189 | }
190 |
191 | @Override
192 | protected void onPostExecute ( String s ) {
193 | shutdownChannel();
194 | log(s);
195 | mSendButton.setEnabled(true);
196 | }
197 |
198 | @Override
199 | protected void onCancelled () {
200 | mSendButton.setEnabled(true);
201 | }
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/lib_hello_grpc/src/main/java/com/lovoo/ubuntudroid/hellogrpc/Server.java:
--------------------------------------------------------------------------------
1 | package com.lovoo.ubuntudroid.hellogrpc;
2 |
3 | /**
4 | * Copyright (c) 2015, LOVOO GmbH
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | *
10 | * Redistributions of source code must retain the above copyright notice, this
11 | * list of conditions and the following disclaimer.
12 | *
13 | * Redistributions in binary form must reproduce the above copyright notice,
14 | * this list of conditions and the following disclaimer in the documentation
15 | * and/or other materials provided with the distribution.
16 | *
17 | * Neither the name of LOVOO GmbH nor the names of its
18 | * contributors may be used to endorse or promote products derived from
19 | * this software without specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 | */
32 |
33 | import com.google.common.util.concurrent.MoreExecutors;
34 |
35 | import java.util.concurrent.Executors;
36 | import java.util.concurrent.ScheduledExecutorService;
37 | import java.util.concurrent.TimeUnit;
38 |
39 | import io.grpc.Metadata;
40 | import io.grpc.ServerCall;
41 | import io.grpc.ServerCallHandler;
42 | import io.grpc.ServerImpl;
43 | import io.grpc.ServerInterceptor;
44 | import io.grpc.ServerInterceptors;
45 | import io.grpc.examples.helloworld.GreeterGrpc;
46 | import io.grpc.examples.helloworld.HelloRequest;
47 | import io.grpc.examples.helloworld.HelloResponse;
48 | import io.grpc.stub.StreamObserver;
49 | import io.grpc.transport.netty.NettyServerBuilder;
50 |
51 | /**
52 | * A simple GRPC server implementation which understands the protocol defined in hello.proto.
53 | *
54 | * Inspired by
55 | * grpc-java's TestServiceServer,
56 | * but radically simplified.
57 | *
58 | * When changing the proto file you also have to adapt the {@link #start()} method. For more complex
59 | * implementations extracting the service implementation in an own class is advised.
60 | */
61 | public class Server {
62 | /**
63 | * The main application allowing this server to be launched from the command line.
64 | */
65 | public static void main ( String[] args ) throws Exception {
66 | final Server server = new Server();
67 | server.parseArgs(args);
68 | if (server.useTls) {
69 | System.out.println(
70 | "\nUsing fake CA for TLS certificate. Test clients should expect host\n"
71 | + "*.test.google.fr and our test CA. For the Java test client binary, use:\n"
72 | + "--server_host_override=foo.test.google.fr --use_test_ca=true\n");
73 | }
74 |
75 | Runtime.getRuntime().addShutdownHook(new Thread() {
76 | @Override
77 | public void run() {
78 | try {
79 | System.out.println("Shutting down");
80 | server.stop();
81 | } catch (Exception e) {
82 | e.printStackTrace();
83 | }
84 | }
85 | });
86 | server.start();
87 | System.out.println("Server started on port " + server.port);
88 | }
89 |
90 | private int port = 8080;
91 | private boolean useTls = false;
92 |
93 | private ScheduledExecutorService executor;
94 | private ServerImpl server;
95 |
96 | private void parseArgs(String[] args) {
97 | boolean usage = false;
98 | for (String arg : args) {
99 | if (!arg.startsWith("--")) {
100 | System.err.println("All arguments must start with '--': " + arg);
101 | usage = true;
102 | break;
103 | }
104 | String[] parts = arg.substring(2).split("=", 2);
105 | String key = parts[0];
106 | if ("help".equals(key)) {
107 | usage = true;
108 | break;
109 | }
110 | if (parts.length != 2) {
111 | System.err.println("All arguments must be of the form --arg=value");
112 | usage = true;
113 | break;
114 | }
115 | String value = parts[1];
116 | if ("port".equals(key)) {
117 | port = Integer.parseInt(value);
118 | } else if ("use_tls".equals(key)) {
119 | useTls = Boolean.parseBoolean(value);
120 | } else if ("grpc_version".equals(key)) {
121 | if (!"2".equals(value)) {
122 | System.err.println("Only grpc version 2 is supported");
123 | usage = true;
124 | break;
125 | }
126 | } else {
127 | System.err.println("Unknown argument: " + key);
128 | usage = true;
129 | break;
130 | }
131 | }
132 | if (usage) {
133 | Server s = new Server();
134 | System.out.println(
135 | "Usage: [ARGS...]"
136 | + "\n"
137 | + "\n --port=PORT Port to connect to. Default " + s.port
138 | + "\n --use_tls=true|false Whether to use TLS. Default " + s.useTls
139 | );
140 | System.exit(1);
141 | }
142 | }
143 |
144 | private void start() throws Exception {
145 | executor = Executors.newSingleThreadScheduledExecutor();
146 | server = NettyServerBuilder.forPort(port)
147 | .addService(ServerInterceptors.intercept(
148 | GreeterGrpc.bindService(new GreeterGrpc.Greeter() {
149 | @Override
150 | public void sayHello ( HelloRequest request, StreamObserver responseObserver ) {
151 | responseObserver.onValue(HelloResponse.newBuilder().setMessage("Hello " + request.getName()).build());
152 | responseObserver.onCompleted();
153 | }
154 | }),
155 | new ServerInterceptor() {
156 | @Override
157 | public ServerCall.Listener interceptCall ( String method,
158 | ServerCall serverCall,
159 | Metadata.Headers headers,
160 | ServerCallHandler serverCallHandler ) {
161 | System.out.println("Received call to " + method);
162 | return serverCallHandler.startCall(method, serverCall, headers);
163 | }
164 | }))
165 | .build().start();
166 | }
167 |
168 | private void stop() throws Exception {
169 | server.shutdownNow();
170 | if (!server.awaitTerminated(5, TimeUnit.SECONDS)) {
171 | System.err.println("Timed out waiting for server shutdown");
172 | }
173 | MoreExecutors.shutdownAndAwaitTermination(executor, 5, TimeUnit.SECONDS);
174 | }
175 | }
176 |
--------------------------------------------------------------------------------