簡體   English   中英

如何在 Kotlin 中為 Android 應用程序生成 protobuf?

[英]How can I generate protobuf in Kotlin for Android applications?

任何人都可以幫助我了解如何在 Kotlin 中生成 protobuf? 我聽說過gRPCwireKotlinPoet ,但我不明白有什么區別,我應該使用哪個示例,任何簡單的文檔請免費填寫與我分享? 任何人都可以提供一個示例鏈接,該鏈接顯示如何將 Protobuf 示例生成到 Kotlin?

我使用square/wireio.grpc庫與 gRPC 服務進行通信。 wire的問題是它還不支持 proto3 版本。

https://github.com/square/wire/issues/279

在這里,我將為您提供一個如何從io.grpc開始的示例。

假設有一個 gRPC 服務總結了您發送給它的號碼的 stream。 它的原型文件會是這樣的:

累加器.proto

syntax = "proto3";

package accumulator;

service Accumulator {
    rpc NumberStream (stream NumberRequest) returns (stream AccumulateReply) {
    }
}

message NumberRequest {
    int32 number = 1;
}

message AccumulateReply {
    int64 sumUp = 1;
}

你應該把這個文件放在項目的/src/main/proto/目錄下。

現在是時候將所需的依賴項添加到build.gradle文件中了。 請注意,它使用kapt生成代碼。


應用層的 build.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.protobuf'
apply plugin: 'kotlin-kapt'

android {
    
    ... others

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8
    }
}

protobuf {
    protoc { artifact = 'com.google.protobuf:protoc:3.10.0' }

    plugins {
        javalite { artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0" }
        grpc {
            artifact = 'io.grpc:protoc-gen-grpc-java:1.25.0' // CURRENT_GRPC_VERSION
        }
    }

    generateProtoTasks {
        all().each { task ->
            task.plugins {
                javalite {}
                grpc { // Options added to --grpc_out
                    option 'lite'
                }
            }
        }
    }
}

dependencies {
    ... other dependencies

    // ------- GRPC
    def grpc_version = '1.25.0'
    implementation "io.grpc:grpc-android:$grpc_version"
    implementation "io.grpc:grpc-okhttp:$grpc_version"
    implementation "io.grpc:grpc-protobuf-lite:$grpc_version"
    implementation "io.grpc:grpc-stub:$grpc_version"

    // ------- Annotation
    def javax_annotation_version = '1.3.2'
    implementation "javax.annotation:javax.annotation-api:$javax_annotation_version"
}

項目級別的 build.gradle

buildscript {

    repositories {
        google()
        jcenter()
    }

    dependencies {
        ... others

        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
    }
}

這是一個 class 封裝了 stream 活動與服務器。 它通過回調返回接收到的值:

累加器處理程序.kt

import android.content.Context
import io.grpc.ManagedChannel
import io.grpc.android.AndroidChannelBuilder
import io.grpc.stub.ClientCallStreamObserver
import io.grpc.stub.StreamObserver
import accumulator.AccumulatorOuterClass
import java.util.concurrent.Executors


/**
 * @author aminography
 */
class AccumulatorHandler constructor(
    private val context: Context,
    private val endPoint: String
) {

    var callback: AccumulatorCallback? = null

    private var managedChannel: ManagedChannel? = null

    private var requestObserver: StreamObserver<AccumulatorOuterClass.NumberRequest>? = null

    private val responseObserver: StreamObserver<AccumulatorOuterClass.AccumulateReply> =
        object : StreamObserver<AccumulatorOuterClass.AccumulateReply> {

            override fun onNext(value: AccumulatorOuterClass.AccumulateReply?) {
                callback?.onReceived(value.sumUp)
            }

            override fun onError(t: Throwable?) {
                callback?.onError(t)
            }

            override fun onCompleted() {
                callback?.onCompleted()
            }
        }

    fun offer(number: Int) {
        initChannelIfNeeded()
        requestObserver?.onNext(
            AccumulatorOuterClass.NumberRequest.newBuilder()
                .setNumber(number)
                .build()
        )
    }

    fun offeringFinished() {
        requestObserver?.onCompleted()
    }

    private fun initChannelIfNeeded() {
        if (managedChannel == null) {
            managedChannel = AndroidChannelBuilder.forTarget(endPoint)
                .context(context)
                .usePlaintext()
                .executor(Executors.newSingleThreadExecutor())
                .build()
        }
        if (requestObserver == null) {
            requestObserver = AccumulatorGrpc.newStub(managedChannel)
                .withExecutor(Executors.newSingleThreadExecutor())
                .numberStream(responseObserver)
        }
    }

    fun release() {
        (requestObserver as? ClientCallStreamObserver<*>)?.cancel("Cancelled by client.", null)
        requestObserver = null

        managedChannel?.shutdown()
        managedChannel = null

        callback = null
    }

    interface AccumulatorCallback {
        fun onReceived(sum: Long)
        fun onError(t: Throwable?)
        fun onCompleted()
    }

}

為了測試它,我編寫了一個活動 class 以簡單的方式展示它的用法:

我的活動.kt

/**
 * @author aminography
 */
class MyActivity: AppCompatActivity, AccumulatorHandler.AccumulatorCallback {

    private var accumulatorHandler: AccumulatorHandler? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        accumulatorHandler = AccumulatorHandler(applicationContext, "http://...")
        accumulatorHandler.callback = this

        for (number in 1..10){
            accumulatorHandler.offer(number)
        }
        accumulatorHandler.offeringFinished()
    }

    override fun onReceived(sum: Long) {
        Toast.makeText(this, "onReceived: $sum", Toast.LENGTH_SHORT).show()
    }

    override fun onError(t: Throwable?) {
        Toast.makeText(this, "onError: $t", Toast.LENGTH_SHORT).show()
        accumulatorHandler.release()
    }

    override fun onCompleted() {
        Toast.makeText(this, "onCompleted", Toast.LENGTH_SHORT).show()
        accumulatorHandler.release()
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM