Protobuf C ++与Android Java

时间:2018-12-04 05:25:15

标签: java android c++

我正在开发一个Android项目,其中我们使用Google的Protobuf库进行序列化/反序列化。过去,我曾使用C ++开发Protobuf。假设我有一个带有一个protobuf对象的.proto文件:

message LoginAck {
  enum LoginResult {
    OK = 1;
    NO_AUTH = 2;
    ERROR = 3;
  }
  optional LoginResult result = 1;
}

在用C ++生成代码时,为此对象生成的类是从google :: protobuf :: Message派生的,如下所示: 类登录:公共:: google :: protobuf ::消息{ ... }

如果我尝试使用Android生成相同的代码,则这些类是从以下类派生/扩展的 公共静态最终课程Login扩展了com.google.protobuf.GeneratedMessageLite

com.google.protobuf.GeneratedMessageLite<
          Login, Login.Builder> implements
      // @@protoc_insertion_point(message_implements:Login)
      LoginOrBuilder {
...
}

问题在于,对于MessageLite类型,我无法使用只能通过Message类访问的描述符。我的Gradle构建文件如下所示:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.google.protobuf:protobuf-java:3.4.0'
    implementation 'com.koushikdutta.async:androidasync:2.1.6'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

protobuf {
    generatedFilesBaseDir = "$projectDir/src/generated"
    protoc {
        // You still need protoc like in the non-Android case
        artifact = 'com.google.protobuf:protoc:3.4.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.builtins {
                // In most cases, you don't need the full Java output
                // if you use the lite output.
                remove java
            }
            task.plugins {
                javalite {}
            }
            task.generateDescriptorSet = true
            task.descriptorSetOptions.includeSourceInfo = true
            task.descriptorSetOptions.includeImports = true
        }
    }
}

我想使用从Message扩展而不是MessageLite扩展的类生成Java文件。如何实现呢?

1 个答案:

答案 0 :(得分:0)

经过更多研究和大量尝试之后,我终于找到了解决方案。我必须进行的更改位于Protobuf块中的build.gradle文件中,如下所示:

protobuf {
    generatedFilesBaseDir = "$projectDir/src/generated"
    protoc {
        // You still need protoc like in the non-Android case
        artifact = 'com.google.protobuf:protoc:3.4.0'
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                // In most cases you don't need the full Java output
                // if you use the lite output.
                java {}
            }
            task.generateDescriptorSet = true
            task.descriptorSetOptions.includeSourceInfo = true
            task.descriptorSetOptions.includeImports = true
        }
    }
}

这里的区别是我必须从块中删除javalite插件并保留Java生成的代码。但是,为了使新脚本起作用,我不得不删除项目中现有的“生成”文件夹。现在,我得到了Messages.java文件,该对象具有扩展Message类而不是MessageLite类的对象,该类具有很多可用的功能,例如描述符。 可惜的是,这个事实没有在线记录在任何地方。因此,如果将来有人遇到这种情况,请对build.gradle文件进行上述更改。 谢谢