- bounty将在7天后过期**。回答此问题可获得+100的声望奖励。Konrad Sikorski正在查找规范答案:我只是想知道如何添加和使用基于. proto文件的GRPC客户端在Kotlin Android应用程序。
任务
我需要使用gRPC将Android客户端与Python服务器连接起来。在Python中制作服务器和生成原型很容易,但Kt客户端缺乏教程和令人困惑的文档,这使得它看起来极其复杂。
背景
到目前为止,我已经使用Kotlin制作了一些简单的Android应用程序,我习惯于向模块或应用程序级别的build.gradle添加依赖项。
我尝试了什么?
我的第一个想法是像Python一样去官方的documentation。我发现那里的指南相当混乱(我觉得那篇文章缺少了一些东西),所以我去看了他们GitHub的完整示例。我还克隆了repo,并使用gradlew installDist命令编译了protos。然后事情变得非常复杂:
- 创建Android Studio项目时,您会获得一系列gradle内容(模块和应用级构建. gradle、gradlew和gradlew.bat、设置等)
- 克隆repo之后,您会在grpc-kotlin文件夹中获得另一组gradle内容。
- 您还可以获得build. gradle. kts,它们似乎是相同的构建逻辑/包管理器帮助文件,但具有其他依赖项和Kotlin脚本语法。
这是当我去YouTube寻找一个简单的实现时,发现只有少数几个关于 * gRPC with Kotlin * 主题的视频,而且大多数都是关于使用Coroutine时Kotlin中gRPC特性的演示视频。
我现在拥有的
我将我所有的build. gradle迁移到了 *. kts * 版本。这是我的模块级 * build. gradle. kts * 的外观:
buildscript {
val kotlin_version = "1.5.10"
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:4.2.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}")
classpath("org.jetbrains.kotlin:kotlin-android-extensions:${kotlin_version}")
classpath("com.google.gms:google-services:4.3.8")
classpath ("com.google.protobuf:protobuf-gradle-plugin:0.8.14")
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
tasks.register("clean",Delete::class){
delete(rootProject.buildDir)
}
这是我的应用级别 * build. gradle. kts * 的外观:
import com.google.protobuf.gradle.generateProtoTasks
import com.google.protobuf.gradle.id
import com.google.protobuf.gradle.plugins
import com.google.protobuf.gradle.protobuf
import com.google.protobuf.gradle.protoc
plugins {
id("com.android.application")
id("com.google.protobuf")
kotlin("android")
}
android {
compileSdkVersion(30)
buildToolsVersion = "30.0.3"
defaultConfig {
applicationId = "com.example.myapplication"
minSdkVersion(26)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
viewBinding = true
}
}
protobuf {
protoc { artifact = "com.google.protobuf:protoc:3.12.0" }
plugins {
id("grpc") {
artifact = "io.grpc:protoc-gen-grpc-java:1.35.0"
}
}
generateProtoTasks {
all().forEach { task ->
task.plugins.create("java") {
option("lite")
}
task.plugins {
id("grpc") {
this.option("lite")
}
}
}
}
}
dependencies {
val kotlin_version = "1.5.10"
implementation("org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}")
implementation("androidx.core:core-ktx:1.5.0")
implementation("androidx.appcompat:appcompat:1.3.0")
implementation("com.google.android.material:material:1.3.0")
implementation("androidx.constraintlayout:constraintlayout:2.0.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.2")
androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0")
// GRPC Deps
implementation("io.grpc:grpc-okhttp:1.37.0")
implementation("io.grpc:grpc-protobuf-lite:1.37.0")
implementation("io.grpc:grpc-stub:1.36.0")
implementation("org.apache.tomcat:annotations-api:6.0.53")
}
我可以生成原型,但它们有些不对劲。
问题
当实现请求函数时,分别是双向流,我发现我所有的rpc函数都需要一个额外的StreamObserver参数(我在互联网上找到的所有教程都没有这个参数).仔细观察,我发现所有生成的文件都是java和官方文档,生成的文件都是POJO和Kotlin.
下面是我生成的Stub类的外观:
public static final class ChatServiceStub extends io.grpc.stub.AbstractAsyncStub<ChatServiceStub> {
private ChatServiceStub(
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
super(channel, callOptions);
}
@java.lang.Override
protected ChatServiceStub build(
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
return new ChatServiceStub(channel, callOptions);
}
/**
* <pre>
* This bi-directional stream makes it possible to send and receive Notes between 2 persons
* </pre>
*/
public void chatStream(grpc.Chat.Empty request,
io.grpc.stub.StreamObserver<grpc.Chat.Note> responseObserver) {
io.grpc.stub.ClientCalls.asyncServerStreamingCall(
getChannel().newCall(getChatStreamMethod(), getCallOptions()), request, responseObserver);
}
/**
*/
public void sendNote(grpc.Chat.Note request,
io.grpc.stub.StreamObserver<grpc.Chat.Empty> responseObserver) {
io.grpc.stub.ClientCalls.asyncUnaryCall(
getChannel().newCall(getSendNoteMethod(), getCallOptions()), request, responseObserver);
}
}
我不知道如何为我的项目复制gradle脚本,我发现互联网上没有人解释所有这些build. gradle是如何链接在一起的(我发现模块级build. gradle描述的是它们所在的模块应该如何构建,而应用级build. gradle是相同的,但适用于整个应用)。我找到的大多数文章都与官方文档相同。
我想要的
我只是想一个简单的项目或一步一步的教程,没有"克隆这一点,并在终端运行命令,它只是工作"。
我不责怪开发人员或谁写的官方文件,我敢打赌,我是愚蠢的一个在这里,但我很难理解这些概念,我会很感激,如果有人能告诉我,我做错了什么或在哪里学习。
另外,很抱歉问了这么长的问题,我试着尽我所能地暴露我的POV,这是我开始学习编程以来的第二个问题,如果问题和我的目标不够清楚,我很抱歉,如果需要的话,我会编辑任何东西。
1条答案
按热度按时间dojqjjoe1#
我没有一个循序渐进的过程可以分享,也不想轻视一个很好的问题,但是,我想回应的是,在研究一个类似的问题时,我发现Square有一个库似乎更适合Kotlin:
https://square.github.io/wire/#wire-kotlin