Android中Protobuf使用

Protobuf 全称Google Protocol Buffers,是google开发的的一套用于 数据存储 ,网络通信时用于协议编解码的工具库。

这边记录下在Android中如何使用,不对编码格式原理深究。Github源码

1. protobuf环境配置

当前上下文环境

gradle: distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
android gradle: com.android.tools.build:gradle:4.2.2
java: 1.8

在项目根build.gradle中配置protobuf的gradle插件

buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.13'
    }
}

在app module下的build.gradle配置protobuf任务以及依赖

apply plugin: 'com.google.protobuf'
protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:3.21.7'
    }
    generateProtoTasks {
        all().each { task ->
            task.builtins {
                remove java
            }
            task.builtins {
                java {}// 生产java源码
            }
        }
    }
}
dependencies {
    ...
    implementation 'com.google.protobuf:protobuf-java:3.21.7'
    implementation 'com.google.protobuf:protoc:3.21.7'
}

2. 在app module的src/main下创建proto文件夹,创建proto接口定义文件。

proto协议文件有固定的语法,可在网络查找定义。

student.proto

syntax = "proto3";
package cn.rock;
option java_package = "cn.rock";
option java_outer_classname = "StudentProto";
message Student {
  string name = 1;
  int32 age = 2;
  Sex sex = 3;
  string email = 4;
  map<string, string> address = 5;
  repeated string course = 6;

  enum Sex {
    MALE = 0;
    FEMALE = 1;
  }
}

3.直接同步构建项目即可生成java实体。

类路径:./app/build/generated/source/proto/debug/java

4.使用

//创建实体
StudentProto.Student student = StudentProto.Student.newBuilder().setAge(12).setSex(StudentProto.Student.Sex.FEMALE).addCourse("math").build();
((TextView) findViewById(R.id.student)).setText(student.toString());

//实体转ByteString
ByteString byteString = student.toByteString();
((TextView) findViewById(R.id.byteString)).setText(byteString.toString());

//ByteString转实体
try {
    student = StudentProto.Student.parseFrom(byteString);
    ((TextView) findViewById(R.id.student1)).setText(student.toString());
} catch (InvalidProtocolBufferException e) {
    e.printStackTrace();
}

以ByteString包括字节数组的容器,封装了数组和ByteString对象间的转换,可用于传递字节数组。

//ByteString处理字节数组
new Thread(() -> {
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tjxb);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    byte[] bytes = baos.toByteArray();
    ByteString tmpByteString = ByteString.copyFrom(bytes);
    byte[] tmpBytes = tmpByteString.toByteArray();
    Bitmap tmpBitmap = BitmapFactory.decodeByteArray(tmpBytes, 0, bytes.length);
    ImageView imageView = (ImageView) findViewById(R.id.imageView);
    imageView.post(() -> imageView.setImageBitmap(tmpBitmap));
}).start();

网络中使用protobuf传输数据,以Socket传输上述Student对象为例:

客户端:

private void connectServer(StudentProto.Student student) {
    try {
        Socket socket = new Socket("0.0.0.0", 9998);
        OutputStream os = socket.getOutputStream();
        student.writeTo(os);
        socket.shutdownOutput();
        socket.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

服务端:

private void startServer() {
    try {
        ServerSocket serverSocket = new ServerSocket(9998);
        while (true) {
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
            StudentProto.Student student = StudentProto.Student.parseFrom(inputStream);
            System.out.println("客户端: " + student);
            socket.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Protobuf生成的实体类有对InputStream和OutputStream接口,可以直接输出。

工程源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值