Try communication using gRPC on Android + Java server

Introduction

In this article, I decided to use gRPC for communication between the server and the client in the project I am currently working on, and I wrote that I did a lot of research while doing a tutorial to implement gRPC on Android. ..

What is gRPC in the first place?

What is gRPC? As mentioned in the overview, it is a communication protocol developed by Google. [Remote procedure call](https://ja.wikipedia.org/wiki/%E9%81%A0%E9%9A%94%E6%89%8B%E7%B6%9A%E3%81%8D%E5 % 91% BC% E5% 87% BA% E3% 81% 97) was developed to realize a technology that allows the server and client to communicate by directly calling the server method, and vice versa. I did.

In the conventional REST API, information was mainly exchanged with Json, but since the server and client implement separately, the implementation cost has increased.

However, gRPC can generate implementations of various programming languages just by defining API specifications in the .proto file, which leads to a reduction in implementation cost on both the server and client.

In addition, Protocol Buffers enables faster communication than REST. [^ 1] [^ 2]

Try the tutorial right away

environment

Hello World

First of all, while looking at the Official Quick Start Guide, I will try to move the application that returns Hello 〇 〇 (arbitrary input character string).

Download sample

Download the sample code from the Github repository with git clone.

$ # 2017/12/22 latest version 1.8.Download 0
$ git clone -b v1.8.0 https://github.com/grpc/grpc-java
$ #Move to the directory containing the sample code
$ cd grpc-java/examples

Run gRPC application

In the grpc-java / examples directory, compile the server by doing the following:

$ ./gradlew installDist

Then let the server run.

$ ./build/install/examples/bin/hello-world-server

Connect your Android device in debug mode and execute the following with adb.

adb reverse tcp:8080 tcp:50051

Open a terminal different from the terminal on which the server was run, and compile and run the client.

$ cd android/helloworld
$ ./gradlew installDebug

If successful, the app will be installed on your device and you should see a screen like the one below.

Screenshot_20171223-183811.png

Enter localhost in Host, 8080 in Port (because it was reversed to 50051 with adb), enter the character you want to send appropriately in message (for example, world), and the response is returned as follows. When it comes, communication with the server is successful!

Screenshot_20171223-184944.png

About the code

It worked for the time being, but what's the actual content of the code? Now let's look at the .proto file, the server code, and the client (Android) code.

helloworld.proto and generated code

//Method definition
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

//Definition of request data structure
message HelloRequest {
  string name = 1;
}

//Definition of response data structure
message HelloReply {
  string message = 1;
}

In the helloworld.proto file, write the API specification as described above. Specifically, describe the method and the data structure of the data to be used.

For details on how to write, see Language Guide (proto3) in Protocol Buffers. See buffers / docs / proto3? hl = ja).

Compiling this helloworld.proto file for each language will generate a language-specific gRPC interface.

Server code

Regarding the server side, it is written in the article I tried gRPC now, so I will omit it here.

Client (Android) code

Code generated from helloworld.proto

The code generated from helloworld.proto is built with gradlew and placed in the following location in the ʻapp / build / generated` directory:

generated/source/proto/debug(/grpc/io.grpc.examples.helloworld & /javalite/io.grpc.examples.helloworld)

Sample implementation code

The code implemented as a sample looks like the following. (Partially omitted)

By the way, since OnClickListener is not implemented, I was searching around without knowing how to call the sendMessage method, but it seems that it is called from the layout xml.

HelloworldActivity.java


public class HelloworldActivity extends AppCompatActivity {
    
    ...

    public void sendMessage(View view) {
        new GrpcTask().execute();
    }

    private class GrpcTask extends AsyncTask<Void, Void, String> {
        private String mHost;
        private String mMessage;
        private int mPort;
        private ManagedChannel mChannel;

        @Override
        protected void onPreExecute() {
            mHost = mHostEdit.getText().toString();
            mMessage = mMessageEdit.getText().toString();
            String portStr = mPortEdit.getText().toString();
            mPort = TextUtils.isEmpty(portStr) ? 0 : Integer.valueOf(portStr);
            mResultText.setText("");
        }

        @Override
        protected String doInBackground(Void... nothing) {
            try {
                //Create Channel
                mChannel = ManagedChannelBuilder.forAddress(mHost, mPort)
                    .usePlaintext(true)
                    .build();
                
                //Create stub
                GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(mChannel);

                //Create request and specify value
                HelloRequest message = HelloRequest.newBuilder().setName(mMessage).build();
                
                //Execute sayHello method and receive reply
                HelloReply reply = stub.sayHello(message);

                return reply.getMessage();
            } catch (Exception e) {
                ...
            }
        }

        @Override
        protected void onPostExecute(String result) {
            try {
                mChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            mResultText.setText(result);
        }
    }
}

Since communication needs to be implemented as asynchronous processing, we are creating a GrpcTask class that inherits AsyncTask.

Looking inside the doInBackground method that is doing asynchronous processing,

  1. Create Channel
  2. Creating a stub
  3. Create request
  4. Run

You can see that it is possible to realize the process of communicating and returning reply just by specifying request as an argument to the sayHello method in the same way as calling the method of the class. ..

At the end

When I first touched gRPC this time, I felt that it could be implemented much simpler than REST. I was very grateful to be able to intuitively write the communication part in the form of a method.

In the future, I would like to deepen my understanding while implementing it in the project.

Reference information


Recommended Posts

Try communication using gRPC on Android + Java server
Try using Firebase Cloud Functions on Android (Java)
Try image classification using TensorFlow Lite on Android (JAVA)
Try bidirectional communication with gRPC Java
Try using the service on Android Oreo
Sobel filter using OpenCV on Android (Java)
Try using RocksDB in Java
Try scraping using java [Notes]
Use serial communication on Android
Try gRPC with Java, Maven
[Java] Server Client Communication 1 (Unfinished)
Try using gRPC in Ruby
Try launching a webAP server on the micro using Helidon
Try Hello World using plain Java on a Docker container
Using Java on OSX 10.15 (Catalina) β
Try implementing Android Hilt in Java
Try implementing GraphQL server in Java
Try using Redmine on Mac docker
Try using Redis with Java (jar)
Save ArrayList using GSON on Android
[Java] Try to implement using generics
Try using IBM Java method tracing
Notes on Android (java) thread processing
Develop gRPC on Windows + Java 7 + Maven 2
Try using Hyperledger Iroha's Java SDK
[Java] Where did you try using java?
Try using Java framework Nablarch [Web application]
Try using the Stream API in Java
Using JupyterLab + Java with WSL on Windows 10
Calling java from C ++ on Android NDK
Kick ShellScript on the server from Java
Notes on operators using Java ~ String type ~
[Adult free study] Acoustic communication on Android
Study Java Try using Scanner or Map
Try using JSON format API in Java
Try using JobScheduler's REST-API --Java RestClient implementation--
Building Java Web Applications on Windows Server 2016
Try using the Emotion API from Android
Try using the Wii remote with Java
Try implementing GraphQL server using grahpql-java-tools (+ kotlin)
Build Web Application Server (Java) on VPS
[Android] [Java] Download images on GCS (Google Cloud Storage) with Stream using Glide
Place Java project using database on the server created in VPS so far
Try using JobScheduler's REST-API --Java RestClient Test class-
Try to build Java8 environment on Amazon Linux2
Install java and android-sdk on Mac using homebrew
Android application development using Unity + ARCore on Ubuntu
Try Azure Service Fabric (Java) on Mac-Local Environment
Beginners try using android studio Part 2 (event processing)
Try local file search using Fess on CentOS7
Try using Sourcetrail (win version) in Java code
Try using GCP's Cloud Vision API in Java
Beginners try using android studio Part 1 (Hello World)
Try similar search of Image Search using Java SDK [Search]
(Android) Try to display static text using DataBinding
[Java] 4 steps to implement splash screen on Android
Try using the COTOHA API parsing in Java
Story of test automation using Appium [Android / java]
* Android * [HTTP communication_1] Try hitting WebAPI [GET, POST]
Try using libGDX
Try using Maven