任何人都有一个例子,你在其中使用 volley 阅读 protobuf?我读过你可以实现 ProtobufRequest 类,但我找不到它的文档。谢谢您的帮助。
4 回答
我已经完成了,工作还可以,希望对您有所帮助。首先创建如下扩展 Request 的 ProtobufRequest 类,Request 是 Volley 中的基本请求类,然后,您可以创建自定义请求扩展 ProtobufRequest 进行自定义 doParse( ). 仅作为参考。
RequestData 是 SomeProto 消息,
private static final int SOCKET_TIMEOUT = 30000;
/** Content type for request. */
private static final String PROTOCOL_CONTENT_TYPE = "application/x-protobuf";
private static final Object sDecodeLock = new Object();
private RequestData mRequestData;
private BaseCallback mCallback;
public ProtobufRequest(RequestData data, BaseCallback callback) {
super(Method.POST, Constants.SERVER_URL, callback);
// TODO Auto-generated constructor stub
mRequestData = data;
mCallback = callback;
this.setRetryPolicy(getRetryPolicy());
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("Charset", "UTF-8");
headers.put("Content-Type", "application/x-protobuf");
headers.put("Accept", "application/x-protobuf");
return headers;
}
@Override
public String getBodyContentType() {
return PROTOCOL_CONTENT_TYPE;
}
@Override
public RetryPolicy getRetryPolicy() {
RetryPolicy retryPolicy = new DefaultRetryPolicy(SOCKET_TIMEOUT,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
return retryPolicy;
}
/**
** write the protobuf data to http request,it is very important
*/
@Override
public byte[] getBody() throws AuthFailureError {
if (mRequestData == null) {
return super.getBody();
} else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
baos.write(mRequestData.toByteArray());
} catch (IOException e) {
return super.getBody();
}
return baos.toByteArray();
}
}
@Override
protected void deliverResponse(Object arg0) {
mCallback.onResponse(arg0);
}
/**
** parse the response result
*/
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
synchronized (sDecodeLock) {
try {
return doParse(response, HttpHeaderParser.parseCacheHeaders(response));
} catch (OutOfMemoryError e) {
return Response.error(new ParseError(e));
}
}
}
abstract protected Response<T> doParse(NetworkResponse response, Entry entry)
public interface BaseCallback extends Listener<Object>, ErrorListener {
}
来自:cmcneil添加代码以防链接失效。Volley 或 Protocol Buffers 最终应该会有一个正式的实现,所以请在必要时更新它。
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.RetryPolicy;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.protobuf.MessageLite;
import java.util.HashMap;
import java.util.Map;
/**
* Created by carson@convox.org on 5/10/15.
*/
public class ProtoBufRequest<ReqT extends MessageLite, RespT extends MessageLite> extends Request<RespT> {
private ReqT request;
private final Class<RespT> responseType;
private final Listener<RespT> listener;
private static final String PROTOCOL_CONTENT_TYPE = "application/x-protobuf";
private static final int SOCKET_TIMEOUT = 30000;
public ProtoBufRequest(int method, String url, ReqT data, Class<RespT> responseType,
Listener<RespT> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = listener;
this.request = data;
this.responseType = responseType;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("Charset", "UTF-8");
headers.put("Content-Type", PROTOCOL_CONTENT_TYPE);
headers.put("Accept", PROTOCOL_CONTENT_TYPE);
return headers;
}
@Override
public byte[] getBody() throws AuthFailureError {
if (request == null) {
return super.getBody();
}
return request.toByteArray();
}
@Override
protected Response<RespT> parseNetworkResponse(NetworkResponse response) {
try {
if (responseType == null) {
throw new IllegalArgumentException("The response type was never provided.");
}
RespT responseInstance = responseType.newInstance();
return (Response<RespT>) Response.success(
responseInstance.newBuilderForType().mergeFrom(response.data).build(),
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
e.printStackTrace();
return Response.error(new ParseError(e));
}
}
@Override
public String getBodyContentType() {
return PROTOCOL_CONTENT_TYPE;
}
@Override
public RetryPolicy getRetryPolicy() {
RetryPolicy retryPolicy = new DefaultRetryPolicy(SOCKET_TIMEOUT,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
return retryPolicy;
}
@Override
protected void deliverResponse(RespT response) {
listener.onResponse(response);
}
}
这不是一个例子,我自己(还没有)做过,但我会这样做:
一种方法是扩展 JsonObjectRequest 并将每个协议缓冲区序列化和反序列化为 Json,使用:
Message someProto = SomeProto.getDefaultInstance();
String jsonFormat = JsonFormat.printToString(someProto);
Message.Builder builder = SomeProto.newBuilder();
String jsonFormat = _load json document from a source_;
JsonFormat.merge(jsonFormat, builder);
请参阅:https ://code.google.com/p/protobuf-java-format/
否则,如果您想将协议缓冲区序列化发送到 byte[],您可以扩展Request<T>
. public byte[] getBody()
您将为请求正文/有效负载覆盖,并Response<Message> parseNetworkResponse(NetworkResponse response)
为答案提供保护。
然后,您将使用以下函数来序列化协议缓冲区。
byte[] toByteArray();
parseFrom(byte[] data);
如果您有解决方案,请不要忘记分享。
只是把它贴在这里以防它有用:我搜索了很多通用方法来做类似于jeff wang的答案的事情。我找不到任何东西,所以我写了这个。让我知道您是否有任何方法可以摆脱那里未经检查的演员...
ProtobufRequest.java
public class ProtoBufRequest<ReqT extends Message, RespT extends Message> extends Request<RespT> { private ReqT request; private final Class<RespT> responseType; private final Listener<RespT> listener; private static final String PROTOCOL_CONTENT_TYPE = "application/x-protobuf"; private static final int SOCKET_TIMEOUT = 30000; public ProtoBufRequest(int method, String url, ReqT data, Class<RespT> responseType, Listener<RespT> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); this.listener = listener; this.request = data; this.responseType = responseType; } @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<String, String>(); headers.put("Charset", "UTF-8"); headers.put("Content-Type", PROTOCOL_CONTENT_TYPE); headers.put("Accept", PROTOCOL_CONTENT_TYPE); return headers; } @Override public byte[] getBody() throws AuthFailureError { if (request == null) { return super.getBody(); } return request.toByteArray(); } @Override protected Response<RespT> parseNetworkResponse(NetworkResponse response) { try { if (responseType == null) { throw new IllegalArgumentException("The response type was never provided."); } RespT responseInstance = responseType.newInstance(); return (Response<RespT>) Response.success( responseInstance.newBuilderForType().mergeFrom(response.data).build(), HttpHeaderParser.parseCacheHeaders(response)); } catch (Exception e) { e.printStackTrace(); return Response.error(new ParseError(e)); } } @Override public String getBodyContentType() { return PROTOCOL_CONTENT_TYPE; } @Override public RetryPolicy getRetryPolicy() { RetryPolicy retryPolicy = new DefaultRetryPolicy(SOCKET_TIMEOUT, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT); return retryPolicy; } @Override protected void deliverResponse(RespT response) { listener.onResponse(response); } }