验证码: 看不清楚,换一张 查询 注册会员,免验证
  • {{ basic.site_slogan }}
  • 打开微信扫一扫,
    您还可以在这里找到我们哟

    关注我们

Android怎么使用GRPC进行通信

阅读:613 来源:乙速云 作者:代码code

Android怎么使用GRPC进行通信

      引言

      Android作为一个开发平台,本身是使用java进行封装的,因此java可以调用的库,在Android中同样可以进行调用,这样就使得Android设备具有丰富的功能,可以进行各种类型的开发。

      环境搭建

      工欲善其事,必先利其器。首先我们先来进行开发环境的搭建。这里先要强调一下,Android开发中使用的项目管理工具Gradle对于版本的要求非常严格,如果不使用正确的版本号,可能导致程序报错,因此这一点需要特别注意。

      我们在创建完一个项目后,需要修改一些文件的信息,具体需要修改的文件信息如下

      Android怎么使用GRPC进行通信

      对于上面的修改我们一个一个来看。

      修改项目的setting.gradle信息

      这个文件里面指定了gradle去哪个仓库中去找插件和第三方依赖库,我以及项目引入的模块信息。

      我找到的一个可行的配置信息如下

      pluginManagement {
          repositories {
              gradlePluginPortal()
              google()
              mavenCentral()
          }
      }
      dependencyResolutionManagement {
          repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
          repositories {
              google()
              mavenCentral()
              maven { url 'https://jitpack.io' }
              maven { url 'https://repo.eclipse.org/content/repositories/paho-releases/'}
          }
      }
      rootProject.name = "gprc_learn"
      include ':app'

      修改项目的build.gralde信息

      项目目录下的build.gradle文件主要指定了项目中需要引入的插件,当然在这个文件中主要是下载插件,我们需要到具体的模块的build.gralde中去引入插件。

      在这个项目中,主要指定gradle插件和protobuf插件,我找到的一个可行配置如下

      // Top-level build file where you can add configuration options common to all sub-projects/modules.
      buildscript {
          repositories {
              maven{ url 'https://maven.aliyun.com/repository/jcenter'}
              maven { url 'https://maven.aliyun.com/repository/google' }
              maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
              maven { url 'https://maven.aliyun.com/repository/public' }
              google()
              mavenCentral()
          }
          dependencies {
              classpath "com.android.tools.build:gradle:7.2.0"
              classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17"
          }
      }
      task clean(type: Delete) {
          delete rootProject.buildDir
      }

      修改gradle版本号

      这一步需要和你引入的gradle插件相关联,插件的版本和你引入的gradle版本必须要匹配才行,我引入的插件版本是7.2.0,引入的gralde版本是7.4。

      修改gradle版本一共有两种方式,第一种就是在projectstructure中进行修改。

      Android怎么使用GRPC进行通信

      第二种方法就是直接在配置文件中进行修改

      Android怎么使用GRPC进行通信

      你需要哪个版本的gradle就直接在配置文件中指定对应版本的压缩包。

      这两种修改方式都是等效的。

      修改模块的build.gradle信息

      模块的build.gradle中引入了插件,同时对插件做了一些配置,最最重要的就是引入第三方库。

      我的配置信息如下

      plugins {
          id 'com.android.application'
          id 'com.google.protobuf'
      }
      android {
          namespace 'com.example.grpc_learn'
          compileSdk 32
          defaultConfig {
              applicationId "com.example.grpc_learn"
              minSdk 29
              targetSdk 32
              versionCode 1
              versionName "1.0"
              testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
          }
          buildTypes {
              release {
                  minifyEnabled false
                  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
              }
          }
          compileOptions {
              sourceCompatibility JavaVersion.VERSION_1_8
              targetCompatibility JavaVersion.VERSION_1_8
          }
          configurations.all {
              resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
              exclude group: 'com.google.guava', module: 'listenablefuture'
          }
          sourceSets {
              main {
                  proto {
                      srcDir 'src/main/proto'
                  }
              }
          }
          packagingOptions {
              pickFirst 'META-INF/INDEX.LIST'
              pickFirst 'META-INF/LICENSE'
              pickFirst 'META-INF/io.netty.versions.properties'
          }
      }
      protobuf {
          protoc {
              artifact = 'com.google.protobuf:protoc:3.17.2'
          }
          plugins {
              grpc {
                  artifact = 'io.grpc:protoc-gen-grpc-java:1.39.0' // CURRENT_GRPC_VERSION
              }
          }
          generateProtoTasks {
              all().each { task ->
                  task.builtins {
                      java { option 'lite' }
                  }
                  task.plugins {
                      grpc {
                          option 'lite' }
                  }
              }
          }
      }
      dependencies {
          implementation 'androidx.appcompat:appcompat:1.4.1'
          implementation 'com.google.android.material:material:1.5.0'
          implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
          testImplementation 'junit:junit:4.13.2'
          androidTestImplementation 'androidx.test.ext:junit:1.1.3'
          androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
          implementation 'io.grpc:grpc-netty:1.39.0'
          implementation 'io.grpc:grpc-okhttp:1.39.0' // CURRENT_GRPC_VERSION
          implementation 'io.grpc:grpc-protobuf-lite:1.39.0' // CURRENT_GRPC_VERSION
          implementation 'io.grpc:grpc-stub:1.39.0' // CURRENT_GRPC_VERSION
          implementation 'org.apache.tomcat:annotations-api:6.0.53'
      }

      模块编译的时候会根据这个文件指定的信息进行操作。这里最好根据你自己的配置文件,然后对比看看和上述文件有哪些缺失的信息,一般只需要添加缺失的信息即可,如果完全照搬上面的内容可能导致项目报错,因为里面记录了你本身的项目信息,可能和我的项目信息产生冲突。

      在main目录下创建proto目录

      我们需要创建一个和java目录同级的proto文件夹,里面存放proto文件,这样做是因为在build.gradle文件中指定了去proto文件夹中找到*.proto文件,并且编译成java代码。

      测试一下

      做完上述的几个步骤后,我们可以编写一个简单的grpc通信模型,测试一下环境是否搭建成功。

      首先在proto文件夹下编写hello.proto文件

      syntax = "proto3";
      option java_multiple_files = true;
      option java_package = "io.grpc.examples.helloworld";
      option java_outer_classname = "HelloWorldProto";
      option objc_class_prefix = "HLW";
      package helloworld;
      // The greeting service definition.
      service Greeter {
          // Sends a greeting
          rpc SayHello (HelloRequest) returns (HelloReply) {}
      }
      // The request message containing the user's name.
      message HelloRequest {
          string name = 1;
      }
      // The response message containing the greetings
      message HelloReply {
          string message = 1;
      }

      然后编译项目,我们可以在build目录下看到对应的java文件

      Android怎么使用GRPC进行通信

      最后,我们可以使用一段简单的grpc通信代码看看是否可以正常通信,我们直接修改MainActivity文件即可

      public class MainActivity extends AppCompatActivity {
          private static final String TAG = "GrpcDemo";
          private static final int PROT = 56322;
          private static final String NAME = "hello world";
          private static final String HOST = "localhost";
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              Log.d(TAG, "start");
              startServer(PROT);
              Log.d(TAG, "start server.");
              startClient(HOST, PROT, NAME);
              Log.d(TAG, "start client.");
          }
          private void startServer(int port){
              try {
                  NettyServerBuilder.forPort(port)
                          .addService(new GreeterImpl())
                          .build()
                          .start();
              } catch (IOException e) {
                  e.printStackTrace();
                  Log.d(TAG, e.getMessage());
              }
          }
          private void startClient(String host, int port, String name){
              ManagedChannel mChannel = ManagedChannelBuilder.forAddress(host, port)
                      .usePlaintext()
                      .build();
              GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(mChannel);
              HelloRequest message = HelloRequest.newBuilder().setName(name).build();
              stub.sayHello(message, new StreamObserver() {
                  @Override
                  public void onNext(HelloReply value) {
                      //Log.d(TAG, "sayHello onNext.");
                      Log.d(TAG, value.getMessage());
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "sayHello onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "sayHello onCompleted.");
                  }
              });
          }
          private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
              public void sayHello(HelloRequest request, StreamObserver responseObserver) {
                  responseObserver.onNext(sayHello(request));
                  responseObserver.onCompleted();
              }
              private HelloReply sayHello(HelloRequest request) {
                  return HelloReply.newBuilder()
                          .setMessage(request.getName())
                          .build();
              }
          }
      }

      然后需要在AndroidManifest.xml文件中添加网络权限

      
      
          
          
          
              
                  
                      
                      
                  
                  
              
          
      

      最后编译运行,如果能看到控制台中有如下信息表示环境搭建成功了,好耶ヾ(✿゚▽゚)ノ

      Android怎么使用GRPC进行通信

      好了,到了这一步,我们可以将hello.proto和MainActivity中的代码清除啦,这只是为了测试环境是否搭建成功而编写的文件。

      GRPC的四种通信模式

      GRPC针对不同的业务场景,一共提供了四种通信模式,分别是简单一元模式,客户端流模式,服务端流模式和双向流模式,接下来这个进行介绍。

      简单一元模式

      所谓简单一元模式,实际上就是客户端和服务端进行一问一答的通信。

      Android怎么使用GRPC进行通信

      这种通信模式是最简单的,应用场景有无线设备之间和客户端之间保持连接的心跳检测,每隔一段时间就给服务端发送一个心跳检测包,服务端接收到心跳包后就知道相应客户端处于连接状态。

      在客户端编写如下程序

          // 简单一元模式
          public void simpleHello() {
              // 构建简单的消息发送
              Request request = Request.newBuilder().setReqInfo("simpleHello").build();
              stub.simpleHello(request, new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "simpleHello onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "simpleHello onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "simpleHello onCompleted.");
                  }
              });
          }

      服务端也需要编写对应的处理程序

          @Override
          public void simpleHello(Request request, StreamObserver responseObserver) {
              Log.d(TAG, "服务端调用simpleHello.");
              String info = "[客户端->服务端]" + request.getReqInfo();
              sendInfo(info);
              responseObserver.onNext(Reply.newBuilder().setRepInfo("simpleHello").build());
              responseObserver.onCompleted();
              super.simpleHello(request, responseObserver);
          }

      客户端流模式

      客户端流模式的意思就是客户端可以一次性发送多个数据片段,当然数据片段是一个类,具体的类有哪些字段都是你在最开始的proto文件中进行指定的。这种模式的应用场景就比如客户端向服务端发送一连串的数据,然后服务端最后发送一个响应数据表示接收成功。

      Android怎么使用GRPC进行通信

      在客户端流模式中,客户端可以在onCompleted之前使用多个onNext进行数据发送。

      客户端代码如下

          // 客户端流模式
          public void clientStream() {
              StreamObserver requestStreamObserver = stub.clientStream(new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "clientStream onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "clientStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "clientStream onCompleted.");
                  }
              });
              requestStreamObserver.onNext(Request.newBuilder().setReqInfo("clientStream1").build());
              requestStreamObserver.onNext(Request.newBuilder().setReqInfo("clientStream2").build());
              requestStreamObserver.onCompleted();
          }

      服务端也需要编写相应代码

          @Override
          public StreamObserver clientStream(StreamObserver responseObserver) {
              StreamObserver streamObserver = new StreamObserver() {
                  @Override
                  public void onNext(Request value) {
                      Log.d(TAG, "clientStream onNext.");
                      String info = "[服务端->客户端]" + value.getReqInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "clientStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "clientStream onCompleted.");
                      // 接收完所有消息后给客户端发送消息
                      responseObserver.onNext(Reply.newBuilder().setRepInfo("clientStream").build());
                      responseObserver.onCompleted();
                  }
              };
              return streamObserver;
          }

      服务端流模式

      服务端流模式和客户端流模式正好相反,本质都是差不多的,应用场景有客户端发送一个数据包告诉服务端,我需要某某数据,然后服务器将对应的所有信息都发送给客户端。

      Android怎么使用GRPC进行通信

      客户端和服务端代码分别如下所示

          // 服务端流模式
          public void serverStream() {
              Request request = Request.newBuilder().setReqInfo("serverStream").build();
              stub.serverStream(request, new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "serverStream onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "serverStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "serverStream onCompleted.");
                  }
              });
          }
          @Override
          public void serverStream(Request request, StreamObserver responseObserver) {
              String info = "[客户端->服务端]" + request.getReqInfo();
              sendInfo(info);
              responseObserver.onNext(Reply.newBuilder().setRepInfo("serverStream1").build());
              responseObserver.onNext(Reply.newBuilder().setRepInfo("serverStream2").build());
              responseObserver.onCompleted();
              super.serverStream(request, responseObserver);
          }

      双向流模式

      双向流模式是最后一种,也是最常用的一种,在这种模式中,客户端和服务端的通信没有什么限制,是比较理想的通信模式,应用场景也最为广泛,因为在这种模式中,你也可以只发送一个数据包。

      Android怎么使用GRPC进行通信

      客户端和服务端的代码如下

          // 双向流模式
          public void bothFlowStream() {
              StreamObserver streamObserver = stub.bothFlowStream(new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "bothFlowStream onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "bothFlowStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "bothFlowStream onCompleted.");
                  }
              });
              streamObserver.onNext(Request.newBuilder().setReqInfo("bothFlowStream1").build());
              streamObserver.onNext(Request.newBuilder().setReqInfo("bothFlowStream2").build());
              streamObserver.onCompleted();
          }
          @Override
          public StreamObserver bothFlowStream(StreamObserver responseObserver) {
              StreamObserver streamObserver = new StreamObserver() {
                  @Override
                  public void onNext(Request value) {
                      Log.d(TAG, "bothFlowStream onNext.");
                      String info = "[客户端->服务端]" + value.getReqInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "bothFlowStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "bothFlowStream onCompleted.");
                      responseObserver.onNext(Reply.newBuilder().setRepInfo("bothFlowStream1").build());
                      responseObserver.onNext(Reply.newBuilder().setRepInfo("bothFlowStream2").build());
                      responseObserver.onCompleted();
                  }
              };
              return streamObserver;
          }

      简单的GRPC客户端服务端程序设计

      上面介绍了GRPC的四种通信模式,以及各种模式中客户端和服务端对应的编写方法。

      下面来介绍一下我们具体应该如何编写客户端服务端代码。

      我们一般会将客户端和服务端分开来编写,具体的文件如下图所示

      Android怎么使用GRPC进行通信

      首先需要编写hello.proto文件,并且编译后生成对应的java文件,我们在proto文件中编写了两个类用来请求和相应,并且编写了四个接口方法,分别对应GRPC请求响应的四种模式

      syntax = "proto3";
      option java_multiple_files = true;
      option java_package = "io.grpc.examples.helloworld";
      option java_outer_classname = "HelloWorldProto";
      option objc_class_prefix = "HLW";
      package helloworld;
      service Greeter {
          // 简单一元模式
          rpc simpleHello (Request) returns (Reply) {}
          // 客户端流模式
          rpc clientStream (stream Request) returns (Reply) {}
          // 服务端流模式
          rpc serverStream (Request) returns (stream Reply) {}
          // 双向流模式
          rpc bothFlowStream (stream Request) returns (stream Reply) {}
      }
      message Request {
          string reqInfo = 1;
      }
      message Reply {
          string repInfo = 1;
      }

      客户端我们只需要编写一个文件即可

      public class GRPCClient {
          private final String TAG = GRPCClient.class.toString();
          private final String host = "localhost";
          private final int port = 55056;
          private Context context;
          private ManagedChannel managedChannel;
          private GreeterGrpc.GreeterStub stub;
          // 在构造函数中连接
          public GRPCClient(Context context) {
              this.context = context;
              managedChannel = ManagedChannelBuilder.forAddress(host, port)
                      .usePlaintext()
                      .build();
              stub = GreeterGrpc.newStub(managedChannel);
          }
          // 使用广播的方法发送数据更新ui
          private void sendInfo(String info) {
              Intent intent = new Intent("main.info");
              intent.putExtra("info", info);
              context.sendBroadcast(intent);
          }
          // 简单一元模式
          public void simpleHello() {
              // 构建简单的消息发送
              Request request = Request.newBuilder().setReqInfo("simpleHello").build();
              stub.simpleHello(request, new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "simpleHello onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "simpleHello onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "simpleHello onCompleted.");
                  }
              });
          }
          // 客户端流模式
          public void clientStream() {
              StreamObserver requestStreamObserver = stub.clientStream(new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "clientStream onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "clientStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "clientStream onCompleted.");
                  }
              });
              requestStreamObserver.onNext(Request.newBuilder().setReqInfo("clientStream1").build());
              requestStreamObserver.onNext(Request.newBuilder().setReqInfo("clientStream2").build());
              requestStreamObserver.onCompleted();
          }
          // 服务端流模式
          public void serverStream() {
              Request request = Request.newBuilder().setReqInfo("serverStream").build();
              stub.serverStream(request, new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "serverStream onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "serverStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "serverStream onCompleted.");
                  }
              });
          }
          // 双向流模式
          public void bothFlowStream() {
              StreamObserver streamObserver = stub.bothFlowStream(new StreamObserver() {
                  @Override
                  public void onNext(Reply value) {
                      Log.d(TAG, "bothFlowStream onNext.");
                      String info = "[服务端->客户端]" + value.getRepInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "bothFlowStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "bothFlowStream onCompleted.");
                  }
              });
              streamObserver.onNext(Request.newBuilder().setReqInfo("bothFlowStream1").build());
              streamObserver.onNext(Request.newBuilder().setReqInfo("bothFlowStream2").build());
              streamObserver.onCompleted();
          }
      }

      在构造函数中,我们需要和服务端建立连接,所以一般需要服务端先启动。在连接建立完成后,无论调用什么方法都采用一个连接,然后分别编写GRPC对应的不同服务接口。

      服务端可以分成两个类来编写,其中GRPCServer主要用来启动服务端,GRPCServiceImpl则是继承了GreeterGrpc.GreeterImplBase,可以重写里面的方法,表示服务端如何处理GRPC请求。

      public class GRPCServer {
          private final String TAG = GRPCServer.class.toString();
          private final int port = 55056;
          private Context context;
          public GRPCServer(Context context) {
              this.context = context;
              start();
              Log.d(TAG, "服务端启动");
              sendInfo("服务端启动");
          }
          // 使用广播的方法发送数据更新ui
          private void sendInfo(String info) {
              Intent intent = new Intent("main.info");
              intent.putExtra("info", info);
              context.sendBroadcast(intent);
          }
          private void start() {
              try {
                  NettyServerBuilder.forPort(port)
                          .addService(new GRPCServiceImpl(context))
                          .build()
                          .start();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      public class GRPCServiceImpl extends GreeterGrpc.GreeterImplBase {
          private final String TAG = GRPCServiceImpl.class.toString();
          private Context context;
          public GRPCServiceImpl(Context context) {
              this.context = context;
          }
          // 使用广播的方法发送数据更新ui
          private void sendInfo(String info) {
              Intent intent = new Intent("main.info");
              intent.putExtra("info", info);
              context.sendBroadcast(intent);
          }
          @Override
          public void simpleHello(Request request, StreamObserver responseObserver) {
              Log.d(TAG, "服务端调用simpleHello.");
              String info = "[客户端->服务端]" + request.getReqInfo();
              sendInfo(info);
              responseObserver.onNext(Reply.newBuilder().setRepInfo("simpleHello").build());
              responseObserver.onCompleted();
              super.simpleHello(request, responseObserver);
          }
          @Override
          public StreamObserver clientStream(StreamObserver responseObserver) {
              StreamObserver streamObserver = new StreamObserver() {
                  @Override
                  public void onNext(Request value) {
                      Log.d(TAG, "clientStream onNext.");
                      String info = "[服务端->客户端]" + value.getReqInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "clientStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "clientStream onCompleted.");
                      // 接收完所有消息后给客户端发送消息
                      responseObserver.onNext(Reply.newBuilder().setRepInfo("clientStream").build());
                      responseObserver.onCompleted();
                  }
              };
              return streamObserver;
          }
          @Override
          public void serverStream(Request request, StreamObserver responseObserver) {
              String info = "[客户端->服务端]" + request.getReqInfo();
              sendInfo(info);
              responseObserver.onNext(Reply.newBuilder().setRepInfo("serverStream1").build());
              responseObserver.onNext(Reply.newBuilder().setRepInfo("serverStream2").build());
              responseObserver.onCompleted();
              super.serverStream(request, responseObserver);
          }
          @Override
          public StreamObserver bothFlowStream(StreamObserver responseObserver) {
              StreamObserver streamObserver = new StreamObserver() {
                  @Override
                  public void onNext(Request value) {
                      Log.d(TAG, "bothFlowStream onNext.");
                      String info = "[客户端->服务端]" + value.getReqInfo();
                      sendInfo(info);
                  }
                  @Override
                  public void onError(Throwable t) {
                      Log.d(TAG, "bothFlowStream onError.");
                  }
                  @Override
                  public void onCompleted() {
                      Log.d(TAG, "bothFlowStream onCompleted.");
                      responseObserver.onNext(Reply.newBuilder().setRepInfo("bothFlowStream1").build());
                      responseObserver.onNext(Reply.newBuilder().setRepInfo("bothFlowStream2").build());
                      responseObserver.onCompleted();
                  }
              };
              return streamObserver;
          }
      }

      我们采用一个简单的布局,就是四个按钮,分别对应GRPC的四个接口,然后在显示客户端和服务端发送给MainActivity的信息。这里面我们在信息传递的时候采用了广播的方法,为了能够发送广播,在实例化客户端和服务端类的时候都需要传递Context作为参数,这个Context就可以发送广播了,然后在MainActivity中需要注册一个广播接收器,当接收到具体信息的时候就更新ui。

      
      
          
              
              
          
          
              
              
          
          
          
      
      public class MainActivity extends AppCompatActivity {
          private final String TAG = MainActivity.class.toString();
          private Button button1;
          private Button button2;
          private Button button3;
          private Button button4;
          private TextView text_info;
          // 服务端和客户端
          private GRPCClient grpcClient;
          private GRPCServer grpcServer;
          // 注册一个广播用于更新ui
          private BroadcastReceiver broadcastReceiver;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              // 初始化控件
              initView();
              // 注册广播接收器
              register();
              // 初始化服务端和客户端
              grpcClient = new GRPCClient(MainActivity.this);
              grpcServer = new GRPCServer(MainActivity.this);
          }
          // 初始化控件
          private void initView() {
              button1 = findViewById(R.id.button1);
              button1.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      grpcClient.simpleHello();
                  }
              });
              button2 = findViewById(R.id.button2);
              button2.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      grpcClient.clientStream();
                  }
              });
              button3 = findViewById(R.id.button3);
              button3.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      grpcClient.serverStream();
                  }
              });
              button4 = findViewById(R.id.button4);
              button4.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      grpcClient.bothFlowStream();
                  }
              });
              text_info = findViewById(R.id.text_info);
              text_info.setMovementMethod(new ScrollingMovementMethod());
          }
          // 注册广播更新ui
          private void register() {
              broadcastReceiver = new BroadcastReceiver() {
                  @Override
                  public void onReceive(Context context, Intent intent) {
                      Log.d(TAG, "广播收到消息" + intent.getStringExtra("info"));
                      text_info.append(intent.getStringExtra("info") + "n");
                  }
              };
              IntentFilter filter = new IntentFilter("main.info");
              registerReceiver(broadcastReceiver, filter);
          }
      }

      最后在虚拟机上运行程序,依次点击四个按钮,如果得到了下图的结果,则表示程序跑通

      Android怎么使用GRPC进行通信

    分享到:
    *特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: hlamps#outlook.com (#换成@)。
    相关文章
    {{ v.title }}
    {{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
    你可能感兴趣
    推荐阅读 更多>