您好,登錄后才能下訂單哦!
這篇文章主要介紹“Android怎么使用GRPC進行通信”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Android怎么使用GRPC進行通信”文章能幫助大家解決問題。
Android作為一個開發平臺,本身是使用java進行封裝的,因此java可以調用的庫,在Android中同樣可以進行調用,這樣就使得Android設備具有豐富的功能,可以進行各種類型的開發。
工欲善其事,必先利其器。首先我們先來進行開發環境的搭建。這里先要強調一下,Android開發中使用的項目管理工具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.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版本必須要匹配才行,我引入的插件版本是7.2.0,引入的gralde版本是7.4。
修改gradle版本一共有兩種方式,第一種就是在projectstructure中進行修改。
第二種方法就是直接在配置文件中進行修改
你需要哪個版本的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'
}
模塊編譯的時候會根據這個文件指定的信息進行操作。這里最好根據你自己的配置文件,然后對比看看和上述文件有哪些缺失的信息,一般只需要添加缺失的信息即可,如果完全照搬上面的內容可能導致項目報錯,因為里面記錄了你本身的項目信息,可能和我的項目信息產生沖突。
我們需要創建一個和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文件
最后,我們可以使用一段簡單的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<HelloReply>() { @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<HelloReply> responseObserver) { responseObserver.onNext(sayHello(request)); responseObserver.onCompleted(); } private HelloReply sayHello(HelloRequest request) { return HelloReply.newBuilder() .setMessage(request.getName()) .build(); } } }
然后需要在AndroidManifest.xml文件中添加網絡權限
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- 添加網絡權限 --> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Gprc_learn" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.lib_name" android:value="" /> </activity> </application> </manifest>
最后編譯運行,如果能看到控制臺中有如下信息表示環境搭建成功了,好耶ヾ(??▽?)ノ
好了,到了這一步,我們可以將hello.proto和MainActivity中的代碼清除啦,這只是為了測試環境是否搭建成功而編寫的文件。
GRPC針對不同的業務場景,一共提供了四種通信模式,分別是簡單一元模式,客戶端流模式,服務端流模式和雙向流模式,接下來這個進行介紹。
所謂簡單一元模式,實際上就是客戶端和服務端進行一問一答的通信。
這種通信模式是最簡單的,應用場景有無線設備之間和客戶端之間保持連接的心跳檢測,每隔一段時間就給服務端發送一個心跳檢測包,服務端接收到心跳包后就知道相應客戶端處于連接狀態。
在客戶端編寫如下程序
// 簡單一元模式 public void simpleHello() { // 構建簡單的消息發送 Request request = Request.newBuilder().setReqInfo("simpleHello").build(); stub.simpleHello(request, new StreamObserver<Reply>() { @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<Reply> 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文件中進行指定的。這種模式的應用場景就比如客戶端向服務端發送一連串的數據,然后服務端最后發送一個響應數據表示接收成功。
在客戶端流模式中,客戶端可以在onCompleted之前使用多個onNext進行數據發送。
客戶端代碼如下
// 客戶端流模式 public void clientStream() { StreamObserver<Request> requestStreamObserver = stub.clientStream(new StreamObserver<Reply>() { @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<Request> clientStream(StreamObserver<Reply> responseObserver) { StreamObserver<Request> streamObserver = new StreamObserver<Request>() { @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; }
服務端流模式和客戶端流模式正好相反,本質都是差不多的,應用場景有客戶端發送一個數據包告訴服務端,我需要某某數據,然后服務器將對應的所有信息都發送給客戶端。
客戶端和服務端代碼分別如下所示
// 服務端流模式 public void serverStream() { Request request = Request.newBuilder().setReqInfo("serverStream").build(); stub.serverStream(request, new StreamObserver<Reply>() { @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<Reply> 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); }
雙向流模式是最后一種,也是最常用的一種,在這種模式中,客戶端和服務端的通信沒有什么限制,是比較理想的通信模式,應用場景也最為廣泛,因為在這種模式中,你也可以只發送一個數據包。
客戶端和服務端的代碼如下
// 雙向流模式 public void bothFlowStream() { StreamObserver<Request> streamObserver = stub.bothFlowStream(new StreamObserver<Reply>() { @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<Request> bothFlowStream(StreamObserver<Reply> responseObserver) { StreamObserver<Request> streamObserver = new StreamObserver<Request>() { @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的四種通信模式,以及各種模式中客戶端和服務端對應的編寫方法。
下面來介紹一下我們具體應該如何編寫客戶端服務端代碼。
我們一般會將客戶端和服務端分開來編寫,具體的文件如下圖所示
首先需要編寫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<Reply>() { @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<Request> requestStreamObserver = stub.clientStream(new StreamObserver<Reply>() { @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<Reply>() { @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<Request> streamObserver = stub.bothFlowStream(new StreamObserver<Reply>() { @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<Reply> 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<Request> clientStream(StreamObserver<Reply> responseObserver) { StreamObserver<Request> streamObserver = new StreamObserver<Request>() { @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<Reply> 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<Request> bothFlowStream(StreamObserver<Reply> responseObserver) { StreamObserver<Request> streamObserver = new StreamObserver<Request>() { @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。
<?xml version="1.0" encoding="utf-8"?> <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" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="一元模式" /> <Button android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="客戶端流模式" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/button3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="服務端流模式" /> <Button android:id="@+id/button4" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="雙向流模式" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/text_title" /> <TextView android:id="@+id/text_info" android:layout_width="match_parent" android:layout_height="418dp" /> </LinearLayout>
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進行通信”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。