如何使用凌空要求protobuf?

时间:2013-06-12 04:23:52

标签: android protocol-buffers android-volley

任何人都有一个例子,你在哪里读过一个protobuf,使用凌空?我已经读过你可以实现ProtobufRequest类,但我找不到它的文档。谢谢你的帮助。

4 个答案:

答案 0 :(得分:2)

我已经做到了,工作还可以,希望它是有帮助的。首先创建ProtobufRequest类,如下面扩展Request,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 {

}

答案 1 :(得分:1)

发件人: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);
    }
}

答案 2 :(得分:-1)

这不是一个例子,我自己还没有(但是)这样做,但我会这样做:

一种方法是使用以下方式扩展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);

如果您有解决方案,请不要忘记分享。

答案 3 :(得分:-1)

只是坚持这个以防它有用: 我搜索了很多类似于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);
  } 
}