在Android studio中配置使用protobuf,网上有很多资料,但几乎找不到与后台交互,
拿到数据后怎么进行反序列化的操作,下面记录下:
首先定义 .proto文件,我们跟后台交互是有请求头和请求体的。
//这是请求头
message MsgHead {
fixed32 version = 1; ///< 协议版本号
fixed32 app = 2; ///< 应用名称
fixed32 server = 3; ///< 应用内具体业务模块
};
//这是请求体
message MsgBody {
bytes body = 1; ///< 消息体主体
}
//这是需要发送给服务器的字段。
message radio_category_req {
uint32 type = 1;
}
//下面3个是服务器返回的数据
//返回的数据集合,包括了错误描述,数据集合列表
message radio_category_rsp {
errorinfo error = 1; // 错误码信息
repeated radio_category_info radio = 2;
}
//通用的描述错误信息
message errorinfo {
int32 error_code = 1; //错误码
bytes error_info = 2; //错误描述信息
}
//分类列表
message radio_category_info {
bytes name = 1; // 分类名字
uint32 id = 2; // 分类id
}
下面是使用socket进行通讯的类
public class TestProtoActivity extends AppCompatActivity {
private Socket mSocket;
private Button btn_send;
ExecutorService mExecutorService = Executors.newCachedThreadPool();
private int mHeadLength;
private byte[] mBytesHead;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_proto);
//跟后台交互,拿到后台的数据进行反序列化
btn_send = findViewById(R.id.btn_test_proto);
//先创建请求头和请求体
RadioCategorySend.radio_category_req send = RadioCategorySend.radio_category_req.newBuilder().setType(1).build();
MsgBodyOuterClass.MsgBody body = MsgBodyOuterClass.MsgBody.newBuilder().setBody(send.toByteString()).build();
MsgHeadOuterClass.MsgHead head = MsgHeadOuterClass.MsgHead.newBuilder()
.setVersion(1)
.setApp(1)
.setServer(3)
.setServant(2001)
.setSeq(1)
.setRouteId(1)
.setBodyLen(body.toByteArray().length)
.build();
mBytesHead = head.toByteArray();
byte[] bytesBody = body.toByteArray();
mHeadLength = mBytesHead.length; //头长度
/*ZLog.d("-----testProto mHeadLength:" + mHeadLength);
ZLog.d("-----testProto bytesBody:" + Arrays.toString(bytesBody));
ZLog.d("-----testProto bytesHead:" + Arrays.toString(mBytesHead));*/
//我们的请求是头+体,所以需要将2个字节数组进行拼接
byte[] bytesResult = addBytes(mBytesHead, bytesBody);
btn_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
send(bytesResult);
}
});
}
private void testPList() {
}
/**
* 将2个byte数组进行拼接
*/
public byte[] addBytes(byte[] data1, byte[] data2) {
byte[] data3 = new byte[data1.length + data2.length];
System.arraycopy(data1, 0, data3, 0, data1.length);
System.arraycopy(data2, 0, data3, data1.length, data2.length);
return data3;
}
private void send(byte[] bytes) {
mExecutorService.execute(new Runnable() {
@Override
public void run() {
OutputStream os = null;
InputStream inputStream = null;
StringBuffer sb = null;
try {
mSocket = new Socket("192.168.189.9", 8080);
mSocket.setSoTimeout(1000 * 10);
mSocket.setTcpNoDelay(true);
os = mSocket.getOutputStream();
os.write(bytes);// 把msg信息写入输出流中
os.flush();
inputStream = mSocket.getInputStream();
//由于数据量小,所以就用1024拿一次就够了,优化需要自己优化。
byte[] buffer = new byte[1024];
int read = inputStream.read(buffer);
//转换为字符串,我这服务器用的编码很奇怪,默认一般使用UFT-8的,可以自己改
String tempISO = new String(buffer, 0, read, Charset.forName("ISO-8859-1")); //ISO-8859-1
//最终结果
byte[] lastResult = tempISO.getBytes(Charset.forName("ISO-8859-1"));
//先解body,这是重点,必须要先把body解出来。用后台返回的字节数据进行解析
MsgBodyOuterClass.MsgBody body = MsgBodyOuterClass.MsgBody.parseFrom(lastResult);
//这里就能拿到返回的集合列表了##################################
RadioCategoryResult.radio_category_rsp cityResult = RadioCategoryResult.radio_category_rsp.parseFrom(body.getBody());
ZLog.d("-----testProto cityResult:" + cityResult.toString());
RadioCategoryResult.errorinfo error = cityResult.getError();
ZLog.d("-----testProto error:" + error.toString());
List<RadioCategoryResult.radio_category_info> radioList = cityResult.getRadioList();
for (int i = 0; i < radioList.size(); i++) {
ZLog.d("-----testProto getName:" + new String(radioList.get(i).getName().toByteArray()) + "---getId:" + radioList.get(i).getId());
}
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}