国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android上使用grpc的方法教程

2019-10-22 18:33:08
字體:
來源:轉載
供稿:網友

前言

最近的一個項目使用到了grpc實現跨平臺的遠程調用,在安卓端使用的時候遇到了一些坑,這里記錄一下。

首先根據grpc android官方Demo配置grpc依賴,測試它的hello world工程。

編譯谷歌官方的helloworld工程

添加rotobuf-gradle-plugin插件

首先添加rotobuf-gradle-plugin插件,他是用來從proto文件自動生成java代碼的:

//Project的build.gradle中添加rotobuf-gradle-plugin插件buildscript { ... dependencies { ... classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.0" ... } ...}
//App的build.gradle中添加下面配置apply plugin: 'com.google.protobuf'protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.0.0' } plugins { javalite {  artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" } grpc {  artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0' // CURRENT_GRPC_VERSION } } generateProtoTasks { all().each { task ->  task.plugins {  javalite {}  grpc {   // Options added to --grpc_out   option 'lite'  }  } } }}

添加proto文件并自動生成java代碼

在src/main/目錄下創建一個proto目錄,并將官方的helloworld.proto放到proto目錄下

之后只需要rebuild一下就能看到build/generated/source/proto/目錄下根據helloworld.proto生成了幾個Java類

android,grpc,使用,java

添加安卓端grpc的依賴

//App的build.gradle中添加下面配置 dependencies { ... compile 'io.grpc:grpc-okhttp:1.1.2' compile 'io.grpc:grpc-protobuf-lite:1.1.2' compile 'io.grpc:grpc-stub:1.1.2' compile 'javax.annotation:javax.annotation-api:1.2' ...}
configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' }

我這個時候報了這個錯誤

Warning:Conflict with dependency ‘com.google.code.findbugs:jsr305'. Resolved versions for app (3.0.0) and test app (2.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.

這是因為com.google.code.findbugs:jsr305的版本不一致導致的

可以在App的build.gradle的android標簽中配置一下解決

android { ... configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' } ...}

編寫demo代碼

public class MainActivity extends AppCompatActivity { private static final String TAG = "GrpcDemo"; private static final int PROT = 55055; private static final String NAME = "linjw"; private static final String HOST = "localhost"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startServer(PROT); startClient(HOST, PROT, NAME); } private void startServer(int port){ try {  Server server = ServerBuilder.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){ new GrpcTask(host, port, name).execute(); } 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("hello "+ request.getName())   .build(); } } private class GrpcTask extends AsyncTask<Void, Void, String> { private String mHost; private String mName; private int mPort; private ManagedChannel mChannel; public GrpcTask(String host, int port, String name) {  this.mHost = host;  this.mName = name;  this.mPort = port; } @Override protected void onPreExecute() { } @Override protected String doInBackground(Void... nothing) {  try {  mChannel = ManagedChannelBuilder.forAddress(mHost, mPort)   .usePlaintext(true)   .build();  GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(mChannel);  HelloRequest message = HelloRequest.newBuilder().setName(mName).build();  HelloReply reply = stub.sayHello(message);  return reply.getMessage();  } catch (Exception e) {  StringWriter sw = new StringWriter();  PrintWriter pw = new PrintWriter(sw);  e.printStackTrace(pw);  pw.flush();  return "Failed... : " + System.lineSeparator() + sw;  } } @Override protected void onPostExecute(String result) {  try {  mChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS);  } catch (InterruptedException e) {  Thread.currentThread().interrupt();  }  Log.d(TAG, result); } }}

這段代碼運行會崩潰:

Caused by: io.grpc.ManagedChannelProvider$ProviderNotFoundException: No functional server found. Try adding a dependency on the grpc-netty artifact

猜測google使用netty替代了okhttp,嘗試換成grpc-netty的依賴:

dependencies { ... compile 'io.grpc:grpc-netty:1.1.2' compile 'io.grpc:grpc-protobuf-lite:1.1.2' compile 'io.grpc:grpc-stub:1.1.2' compile 'javax.annotation:javax.annotation-api:1.2' ...}

這么編譯會報錯

com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/INDEX.LIST

需要加上下面的配置解決

android { ... packagingOptions { pickFirst 'META-INF/INDEX.LIST' pickFirst 'META-INF/LICENSE' pickFirst 'META-INF/io.netty.versions.properties' } ...}

當然,還需要加上INTERNET權限,要不然運行的時候還是會崩潰。

最終就能看的下面的打印,這樣安卓grpc的helloworld就成功了。

03-03 00:04:20.000 6137-6137/linjw.com.grpcdemo D/GrpcDemo: hello linjw

使用com.google.protobuf.Any

Any可以攜帶任意類型的數據,用法相當于c語言的void指針。在項目中是很常用的,但是谷歌在javalite的版本不支持Any。

如果在proto文件中使用了Any的話生成java代碼就會有報錯,例如將helloworld的proto文件改成下面的樣子:

// Copyright 2015, Google Inc.// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived from// this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.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;import "google/protobuf/any.proto";// The greeting service definition.service Greeter { // Sends a greeting rpc SayHello (google.protobuf.Any) returns (HelloReply) {}}// The request message containing the user's name.message HelloRequest { string name = 1;}// The response message containing the greetingsmessage HelloReply { string message = 1;}

報錯如下

google/protobuf/any.proto: File not found.helloworld.proto: Import “google/protobuf/any.proto” was not found or had errors.helloworld.proto:44:17: “google.protobuf.Any” is not defined.

使用grpc-jave代替grpc-javalite

但是現在做的這個項目的linux端實現已經用了Any,要改的話需要耗費比較大的精力。幸好嘗試了下,發現安卓上也能跑支持Any的grpc-java。

首先我們要使用grpc-protobuf依賴替換grpc-protobuf-lite依賴

dependencies { ... compile 'io.grpc:grpc-netty:1.1.2' compile 'io.grpc:grpc-protobuf:1.1.2' compile 'io.grpc:grpc-stub:1.1.2' compile 'javax.annotation:javax.annotation-api:1.2' ...}

接著修改protobuf-gradle-plugin配置使得自動生成java的代碼而不是javalite的代碼

protobuf { protoc {  artifact = 'com.google.protobuf:protoc:3.0.0' } plugins {  grpc {   artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0' // CURRENT_GRPC_VERSION  } } generateProtoTasks {  all().each { task ->   task.builtins {    java {}   }   task.plugins {    grpc {}   }  } }}

對應的修改helloworld的代碼就能運行了

public class MainActivity extends AppCompatActivity { private static final String TAG = "GrpcDemo"; private static final int PROT = 55055; private static final String NAME = "linjw"; private static final String HOST = "localhost"; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  startServer(PROT);  startClient(HOST, PROT, NAME); } private void startServer(int port){  try {   Server server = ServerBuilder.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){  new GrpcTask(host, port, name).execute(); } private class GreeterImpl extends GreeterGrpc.GreeterImplBase {  public void sayHello(Any request, StreamObserver<HelloReply> responseObserver) {   try {    responseObserver.onNext(sayHello(request.unpack(HelloRequest.class)));    responseObserver.onCompleted();   } catch (InvalidProtocolBufferException e) {    e.printStackTrace();   }  }  private HelloReply sayHello(HelloRequest request) {   return HelloReply.newBuilder()     .setMessage("hello "+ request.getName())     .build();  } } private class GrpcTask extends AsyncTask<Void, Void, String> {  private String mHost;  private String mName;  private int mPort;  private ManagedChannel mChannel;  public GrpcTask(String host, int port, String name) {   this.mHost = host;   this.mName = name;   this.mPort = port;  }  @Override  protected void onPreExecute() {  }  @Override  protected String doInBackground(Void... nothing) {   try {    mChannel = ManagedChannelBuilder.forAddress(mHost, mPort)      .usePlaintext(true)      .build();    GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(mChannel);    HelloRequest message = HelloRequest.newBuilder().setName(mName).build();    HelloReply reply = stub.sayHello(Any.pack(message));    return reply.getMessage();   } catch (Exception e) {    StringWriter sw = new StringWriter();    PrintWriter pw = new PrintWriter(sw);    e.printStackTrace(pw);    pw.flush();    return "Failed... : " + System.lineSeparator() + sw;   }  }  @Override  protected void onPostExecute(String result) {   try {    mChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS);   } catch (InterruptedException e) {    Thread.currentThread().interrupt();   }   Log.d(TAG, result);  } }}

完整的demo代碼可以點這里在我的github中查看(也可以通過本地下載

Android方法數不能超過65535的問題

最后使用grpc,方法數會超過65535,可以使用com.android.support:multidex去解決

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 盐边县| 肥乡县| 内丘县| 措勤县| 巴东县| 宁乡县| 嘉鱼县| 克什克腾旗| 乌鲁木齐市| 泸水县| 宜兴市| 嘉禾县| 德格县| 阿合奇县| 望江县| 罗田县| 资源县| 卢氏县| 神农架林区| 宜川县| 龙山县| 乌拉特中旗| 榆树市| 安龙县| 余姚市| 西吉县| 南宁市| 东乡族自治县| 扬中市| 琼结县| 桂林市| 衡阳市| 海南省| 都江堰市| 铜梁县| 灌南县| 安庆市| 德令哈市| 延寿县| 甘洛县| 肇庆市|