Kotlin Android的协议缓冲区gradle支持无法正常工作?

时间:2017-10-23 10:23:26

标签: android kotlin protocol-buffers

我在Kotlin有一个Android项目,它正确设置并正常工作

在Root build.gradle中

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

在App build.gradle中

apply plugin: 'kotlin-android'
// ...
implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

一切运作良好。

根据https://github.com/google/protobuf-gradle-plugin

,它还有Protobuf支持

App build.gradle中的位置

apply plugin: 'com.google.protobuf'
// ...
protobuf {
    protoc {
        // Download from repositories
        artifact = 'com.google.protobuf:protoc:3.0.0'
    }

    plugins {
        javalite {
            // The codegen for lite comes as a separate artifact
            artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
        }
    }
    generateProtoTasks {
        all().each { task ->
            task.plugins {
                javalite { }
            }
        }
    }
}

sourceSets {
    main {
        java {
            srcDirs += file("${protobuf.generatedFilesBaseDir}/debug/javalite")
        }
    }
}

// ...
api 'com.google.protobuf:protobuf-lite:3.0.0'

唯一的一点是,当访问Protobuf生成代码的代码(即com.elyeproj.proto.*中的代码)是Java时,一切运行良好

package com.elyeproj.myapplication;

import com.elyeproj.proto.Card;
import com.elyeproj.proto.Heart;
import com.elyeproj.proto.Result;
import com.elyeproj.proto.Spade;

public class MainPresenter {

    private MainView mainView;

    public MainPresenter(MainView mainView) {
        this.mainView = mainView;
    }

    public void fetchData() {
        Card card1 = Card.newBuilder().setHeart(Heart.newBuilder().build()).build();
        Card card2 = Card.newBuilder().setSpade(Spade.newBuilder().build()).build();
        Result result = Result.newBuilder().addCards(card1).addCards(card2).build();
        mainView.showResult(result.toString());

    }
}

然而,转换为Kotlin时

package com.elyeproj.myapplication

import com.elyeproj.proto.Card
import com.elyeproj.proto.Heart
import com.elyeproj.proto.Result
import com.elyeproj.proto.Spade

class MainPresenter(private val mainView: MainView) {

    fun fetchData() {
        val card1 = Card.newBuilder().setHeart(Heart.newBuilder().build()).build()
        val card2 = Card.newBuilder().setSpade(Spade.newBuilder().build()).build()
        val result = Result.newBuilder().addCards(card1).addCards(card2).build()
        mainView.showResult(result.toString())

    }
}

它将在编译时使用以下消息呈现错误:

Error:(6, 21) Unresolved reference: proto
Error:(11, 21) Unresolved reference: Card
Error:(11, 48) Unresolved reference: Heart
Error:(12, 48) Unresolved reference: Spade
Error:(13, 22) Unresolved reference: Result

即。它无法访问那些Protobuf生成的代码(虽然在Android Studio中,它仍然可以访问代码,例如代码自动完成可以找到函数)。

看起来Protobuf Gradle支持和Kotlin无法正常工作。或者我错过了什么?

要测试它,您可以使用Java中的MainPresentation访问https://github.com/elye/issue_android_protobuf_light_java中的代码,编译正常。但是,如果转换为Kotlin,它将导致如上所述的错误。

2 个答案:

答案 0 :(得分:1)

我刚刚在我的项目中解决了这个问题。也许你可以尝试我的解决方案。在app build.gradle中添加以下配置:

android {
    ...
     // Adding generated proto to srcDirs depending on build variant
     variantFilter { variant ->
        def sourceSet = android.sourceSets.findByName(variant.buildType.name)
         if (sourceSet != null) {
             sourceSet.java.srcDirs += "build/generated/source/proto/${variant.name}/javalite"
        }
    }
    ...
}

//Running generating proto task before compiling Kotlin
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
    mustRunAfter tasks.withType(com.google.protobuf.gradle.GenerateProtoTask)
}

答案 1 :(得分:0)

有一个关于获得Kotlin支持的解决方法,即使用Kotlin模块生成protobuf文件。然后作为单独的模块,然后可以使用它。查看https://medium.com/@elye.project/android-protobuf-in-kotlin-a1c33014a4e2了解更多详情。