DEV Community

Fernie
Fernie

Posted on • Originally published at fern.life

4 1

Android Java GRPC Tutorial

This tutorial is to show you the basic set up to get GRPC working with an Android app using Java as the primary language.

Prerequisites

Set Up

Were going to be borrowing the example java server from the main grpc-java repo

  • clone https://github.com/grpc/grpc-java

  • change directories to the examples folder

  • execute ./gradlew installDist

  • then run ./build/install/examples/bin/hello-world-server


  1. In the Welcome to Android Studio window, click Create New Project.

  2. In the Select a Project Template window, select Empty Activity and click Next.
    Alt Text

  3. In the Configure your project window, complete the following:

    • Enter HelloWorldGrpc in the Name field.
    • Select Java Language drop-down menu.
    • Click Finish Alt Text
  4. Open AndroidManifest.xml add this line above the application block.

    • <uses-permission android:name="android.permission.INTERNET" />
    • For reference here is what it should look like
      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.helloworldgrpc">
      <uses-permission android:name="android.permission.INTERNET" />
      <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/Theme.HelloWorldGrpc">
      <activity android:name=".MainActivity">
      <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      </activity>
      </application>
      </manifest>
  5. Open the project gradle file and add this line to the dependencies section

    • classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.14" Alt Text
      buildscript {
      repositories {
      google()
      jcenter()
      }
      dependencies {
      classpath "com.android.tools.build:gradle:4.1.2"
      classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.14"
      // NOTE: Do not place your application dependencies here; they belong
      // in the individual module build.gradle files
      }
      }
      view raw project.gradle hosted with ❤ by GitHub
  6. Next we add some lines to the module gradle file
    Alt Text

    • Add com.google.protobuf to the top in the plugins object
      plugins {
      id 'com.android.application'
      id 'com.google.protobuf'
      }
    • Add the protobuf block, I add this right above the dependencies block
      protobuf {
      protoc { artifact = 'com.google.protobuf:protoc:3.12.0' }
      plugins {
      grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.35.0'
      }
      }
      generateProtoTasks {
      all().each { task ->
      task.builtins {
      java { option 'lite' }
      }
      task.plugins {
      grpc {
      option 'lite'
      }
      }
      }
      }
      }
    • Add the dependencies to the block, the okhttp, grpc-protobuf-lite, grpc-stub, annotations-api
      dependencies {
      implementation 'androidx.appcompat:appcompat:1.2.0'
      implementation 'com.google.android.material:material:1.3.0'
      implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
      testImplementation 'junit:junit:4.+'
      androidTestImplementation 'androidx.test.ext:junit:1.1.2'
      androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
      // GRPC Deps
      implementation 'io.grpc:grpc-okhttp:1.35.0'
      implementation 'io.grpc:grpc-protobuf-lite:1.35.0'
      implementation 'io.grpc:grpc-stub:1.35.0'
      implementation 'org.apache.tomcat:annotations-api:6.0.53'
      }
  7. Now time to add the proto file

    • Your going to want to go to the terminal and create the proto directory in the main folder Alt Text
    • Then create the proto file, whats great about using gradle and GRPC dependencies is that the proto files are automatically compiled for you touch HelloWorld.proto
    • Add this to the file
      syntax = "proto3";
      option java_multiple_files = true;
      option java_package = "com.example.helloworldgrpc";
      option java_outer_classname = "HelloWorldProto";
      package helloworld;
      service Greeter {
      rpc SayHello (HelloRequest) returns (HelloReply) {}
      }
      message HelloRequest {
      string name = 1;
      }
      message HelloReply {
      string message = 1;
      }
  8. Lets now add the text fields and buttons to the main activity

    • Open the activity_main.xml file
    • Your going to want to delete the TextView component Alt Text Your going to want to add these components to the view
    • PlainText three of them, one for the host input, another for the port input and a third for the message
    • TextView for the result message
    • Button for the sending action
    • It doesn't matter how you arrange them, if you wanted to get this done quickly then copy the xml file from step 9
  9. Add ID's and settings for the components
    For the host and port, I like to default those to the grpc server

    • Host PlainText component id should equal host
    • Port PlainText component id should equal port
    • Message PlainText component id should equal message
    • Send/Submit Button component id should equal send
    • Result TextView component id should equal result
      <?xml version="1.0" encoding="utf-8"?>
      <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context=".MainActivity">
      <TextView
      android:id="@+id/result"
      android:layout_width="358dp"
      android:layout_height="473dp"
      android:layout_marginTop="16dp"
      android:layout_marginBottom="16dp"
      android:text="Result"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/send" />
      <EditText
      android:id="@+id/host"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="16dp"
      android:layout_marginTop="16dp"
      android:ems="10"
      android:hint="Host"
      android:inputType="textPersonName"
      android:text="10.0.2.2"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent" />
      <EditText
      android:id="@+id/port"
      android:layout_width="153dp"
      android:layout_height="wrap_content"
      android:layout_marginStart="12dp"
      android:layout_marginTop="16dp"
      android:layout_marginEnd="16dp"
      android:ems="10"
      android:hint="Port"
      android:inputType="textPersonName"
      android:text="50051"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintHorizontal_bias="1.0"
      app:layout_constraintStart_toEndOf="@+id/host"
      app:layout_constraintTop_toTopOf="parent" />
      <EditText
      android:id="@+id/message"
      android:layout_width="380dp"
      android:layout_height="58dp"
      android:layout_marginTop="16dp"
      android:ems="10"
      android:hint="Message"
      android:inputType="textPersonName"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/host" />
      <Button
      android:id="@+id/send"
      android:layout_width="177dp"
      android:layout_height="36dp"
      android:layout_marginTop="16dp"
      android:onClick="sendGrpcMessage"
      android:text="Submit"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/message" />
      </androidx.constraintlayout.widget.ConstraintLayout>
      Alt Text
  10. Now we move on to the code of the MainActivity. Open up the MainActivity file and declare these vars

    • hostEdit
    • portEdit
    • messageEdit
    • sendButton
    • resultText
      public class MainActivity extends AppCompatActivity {
      private EditText hostEdit;
      private EditText portEdit;
      private EditText messageEdit;
      private Button sendButton;
      private TextView resultText;
      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      }
      }
  11. Add this code to onCreate

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    hostEdit = (EditText) findViewById(R.id.host);
    portEdit = (EditText) findViewById(R.id.port);
    messageEdit = (EditText) findViewById(R.id.message);
    sendButton = (Button) findViewById(R.id.send);
    resultText = (TextView) findViewById(R.id.result);
    resultText.setMovementMethod(new ScrollingMovementMethod());
    }
  12. Add the GrpcTask and code

    private static class GrpcTask extends AsyncTask<String, Void, String> {
    private final WeakReference<Activity> activityReference;
    private ManagedChannel channel;
    private GrpcTask(Activity activity) {
    this.activityReference = new WeakReference<Activity>(activity);
    }
    @Override
    protected String doInBackground(String... params) {
    String host = params[0];
    String message = params[1];
    String portStr = params[2];
    int port = TextUtils.isEmpty(portStr) ? 0 : Integer.valueOf(portStr);
    try {
    channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
    GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
    HelloRequest request = HelloRequest.newBuilder().setName(message).build();
    HelloReply reply = stub.sayHello(request);
    return reply.getMessage();
    } catch (Exception e) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    pw.flush();
    return String.format("Failed... : %n%s", sw);
    }
    }
    @Override
    protected void onPostExecute(String result) {
    try {
    channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    }
    Activity activity = activityReference.get();
    if (activity == null) {
    return;
    }
    TextView resultText = (TextView) activity.findViewById(R.id.result);
    Button sendButton = (Button) activity.findViewById(R.id.send);
    resultText.setText(result);
    sendButton.setEnabled(true);
    }
    }
  13. Add the sendGrpcMessage function that will tie to the submit button

    public void sendGrpcMessage(View view) {
    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
    .hideSoftInputFromWindow(hostEdit.getWindowToken(), 0);
    sendButton.setEnabled(false);
    resultText.setText("");
    new GrpcTask(this)
    .execute(
    hostEdit.getText().toString(),
    messageEdit.getText().toString(),
    portEdit.getText().toString());
    }
  14. Go back to activity_main.xml and set the button onClick listener to sendGrpcMessage
    Alt Text

  15. Run the app on the emulator

    • For the host use 10.0.2.2
    • For the port use 50051
    • Then add a message
    • Click Submit
    • You should get back Hello and what ever you placed in the message component and see it in the result component

Link to the code for https://github.com/efernie/Android-Java-Grpc-Tutorial

A Kotlin version is coming soon

Sentry mobile image

App store rankings love fast apps - mobile vitals can help you get there

Slow startup times, UI hangs, and frozen frames frustrate users—but they’re also fixable. Mobile Vitals help you measure and understand these performance issues so you can optimize your app’s speed and responsiveness. Learn how to use them to reduce friction and improve user experience.

Read full post →

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay