Android GRPC接入

2019/8/20 posted in  Android

安装Protobuf插件

Protobuf Support插件可以支持Protobuf文件高亮语法显示

添加Grpc依赖

  • 项目根目录build.gradle添加
buildscript {
    ext.kotlin_version = '1.3.41'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        //添加这句
        classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.10"
    }
}
  • 在Module下build.gradle添加apply plugin: 'com.google.protobuf'
  • 设置proto文件位置(src/main/proto):
android {
    sourceSets {
        main {
            proto {
                srcDir 'src/main/proto'
            }
            java {
                srcDir 'src/main/java'
            }
        }
    }
}
  • 自定义Protobuf编译项
protobuf {
    protoc { artifact = 'com.google.protobuf:protoc:3.9.1' }
    plugins {
        javalite { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
        grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.22.1' }
    }
    generateProtoTasks {
        all().each { task ->
            task.plugins {
                javalite {}
                grpc { option 'lite' }
            }
        }
    }
    generatedFilesBaseDir = "$projectDir/src/generated"
}

clean {
    delete "${projectDir}/src/main/generated-proto"
}
  • 加入grpc依赖
implementation 'io.grpc:grpc-okhttp:1.22.1'
implementation 'io.grpc:grpc-protobuf-lite:1.22.1'
implementation 'io.grpc:grpc-stub:1.22.1'
implementation 'javax.annotation:javax.annotation-api:1.3.2'
  • Rebuild Project之后就会自动生成代码

Protobuf语法

关键字

  • syntax:声明版本。例如上面syntax="proto3",如果没有声明,则默认是proto2。
  • package:声明包名.
  • import:导入包。类似于java,例如上面导入了timestamp.proto包。
  • java_package:指定生成的类应该放在什么Java包名下。如果你没有显式地指定这个值,则它简单地匹配由package 声明给出的Java包名,但这些名字通常都不是合适的Java包名 (由于它们通常不以一个域名打头)。
  • java_outer_classname:定义应该包含这个文件中所有类的类名。如果你没有显式地给定java_outer_classname ,则将通过把文件名转换为首字母大写来生成。例如上面例子编译生成的文件名和类名是AddressBookProtos。
  • message:类似于java中的class关键字。
  • repeated:用于修饰属性,表示对应的属性是个array。

Android中使用

创建Proto文件

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.ifantastic.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

service Greeter {
    rpc SayHello(HelloRequest) returns (HelloReply);
}

Rebuild之后开始调用

  • 创建连接通道

    val connectionChannel: ManagedChannel by lazy {
        OkHttpChannelBuilder.forAddress("192.168.6.104", 9090)
    .usePlaintext()
    .build()
    }
  • 声明Service

    val service = GreeterGrpc.newBlockingStub(connectionChannel)
    
  • Grpc请求

    val requestMessage = HelloRequest.newBuilder()
            .setName(name)
    .build()
    val response = service.sayHello(requestMessage)