protobuf为Google什么什么…(自行百度),总之重要的一点,它比Json和XML大体上会有更好的封装更小的体积。
AS配置
project的build.geadle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
//...
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.6'
//加入gradle的依赖
}
}
小插曲
如果遇到以下错误:
A problem was found with the configuration of task ':app:generateDebugProto'.
> Directory '...ProtoBuffTest/app/build/extracted-include-protos/main' specified for property '$3' does not exist.
PS:这个错误是说在proto的build里面extracted-include-protos少了main这个文件夹,别问我为什么,我还没有去研究(应该是我protobuf编译生成那部分写的有问题),只是记录一下。你可以手动在extracted-include-protos这个里面加上,只要没有执行gradle clean那么之后都不会报这个错,也可以在工程或者app的build.gradle里面添加
ext{
File file = new File("app/build/extracted-include-protos/main")//路径看你自己文件目录喽
if (!file.exists()) {
file.mkdirs()
}
}
app build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.google.protobuf' //引入
...
sourceSets{
main{
proto {
srcDir 'src/proto' //proto配置文件的路径
include '**/*.proto' //find it
}
}
}
....
//依赖包
implementation 'com.google.protobuf:protobuf-java:3.4.0'
implementation 'com.google.protobuf:protoc:3.4.0'
//编译并生成
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.4.0'
}
plugins {
javalite {
// The codegen for lite comes as a separate artifact
artifact = 'com.google.protobuf:protobuf-java: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.
remove java
}
task.builtins {
java {}
cpp {}
}
}
}
}
使用
配置完gradle就可以开心的使用了
这个过程有三个部分
- 新建配置文件
- 在业务里面使用之-封装
- 在业务里面使用之-解析
解析还可有花式的玩法,有同一个APP的解析,还有不同APP的解析
新建配置文件
比如说新建一个test.proto,它的位置按照build.gradle 里面应该是摆在如下的位置
内容可以自己DIY喽
syntax = "proto3";
package proto;
message TestMessage{
string type = 1;
string typeStatus = 2;
string flag = 3;
int64 flagtime = 4;
bytes data = 5;
string network = 6;
string config = 7;
int32 width = 8;
int32 height = 9;
}
对了这里应该插一张变量类型说明
这里用的是proto3,它还有2,,2是需要在特殊变量需求前面加修饰符的,太麻烦
如上的类型总结我是拿的这位仁兄的成果
或者自行去Google
写好这个之后就可以去build里面看一下它生成了没
就这样生成了。
封装
byte[] bytes = new byte[1024];
Test.TestMessage testMessage = Test.TestMessage
.newBuilder()
.setConfig("")
.setData(ByteString.copyFrom(bytes))
.setHeight(1)
.build();
byte[] result = testMessage.toByteArray();
这样一个就封装好了
闲的蛋疼看一下它封装后的样子。
有如下数据:
上面已经表明了大小。下面先看一下Json封装,看看它的二进制是什么样的
看起来完全显示,啥都能知道,下面是protobuf的封装:
看起来就很喜庆。
解析(同APP解析)
因为是在一个APP里面,那么可以公用一套的protobuf的配置,只要你配置好就可以瞎用了
故
当拿到byte准备解析时
Test.TestMessage message= Test.TestMessage.parseFrom(data);
就是这么简单
PS:注意在遇到什么什么zero报错的时候,你要确定一下这个byte的包是否完整,这个是经常会出现的问题。
解析(不同APP)
如果是不同APP,是不是还要做前面一系列的配置呢?答案是否定的。
分两步:
1.把自己build(如上面配置步骤)出来的.java或者.cpp给对应app。
2.在对应APP的build.geadle 里面添加依赖
implementation 'com.google.protobuf:protobuf-java:3.4.0'
这样就可以用了
PS:还有些许的操作,当跨APP使用时,我们会发现在build出来的Test.java(就拿上面的配置举例)里面含有proto.Test这样的写法,那么当这个文件拷到别的app时,难道还需要建立相同的目录去放置使用么,那样真的是太麻烦了。于是产生了如下写法:
syntax = "proto3";
//package proto;
message TestMessage{
string type = 1;
string typeStatus = 2;
string flag = 3;
int64 flagtime = 4;
bytes data = 5;
string network = 6;
string config = 7;
int32 width = 8;
int32 height = 9;
}
暂时去掉它的包名,然后make project,尽管会报错,但是它同样会在build下面生成Test.java的
这个时候你可以看到,在proto包里面的那个是原来配置里面加package的产出,屏蔽掉的是没在proto的Test.java,此时我们发现没在proto里面的那个.java文件里面是不包含proto.Test这样的函数的。这样就可以直接拷的别的APP里面用咯。