Mike Walker Mike Walker - 2 months ago 38
reST (reStructuredText) Question

Android Volley getParams Not Called for Custom Request

I have created a custom

Volley
Request
class which extends
Request<NetworkResponse>
. Here is the code for that custom class:

public class MultipartRequest extends Request<NetworkResponse> {
private final Response.Listener<NetworkResponse> mListener;
private final Response.ErrorListener mErrorListener;
private final Map<String, String> mHeaders;
private final Map<String, String> mParams;
private final String mMimeType;
private final byte[] mMultipartBody;

public MultipartRequest(String url, Map<String, String> headers, Map<String, String> params, String mimeType, byte[] multipartBody, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
this.mHeaders = headers;
this.mParams = params;
this.mMimeType = mimeType;
this.mMultipartBody = multipartBody;
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Log.i("MultipartRequest", "headers = " + mHeaders);
return mHeaders;
}

@Override
protected Map<String, String> getParams() throws AuthFailureError {
Log.i("MultipartRequest", "params = " + mParams);
return mParams;
}

@Override
public String getBodyContentType() {
return mMimeType;
}

@Override
public byte[] getBody() throws AuthFailureError {
return mMultipartBody;
}

@Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
try {
return Response.success(
response,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}

@Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}

@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
}


I have inserted the
Log.i
statements within
getHeaders()
and
getParams()
to ensure they are called properly.I create the request as follows:

final Map<String, String> volleyParams = new HashMap<>();
volleyParams.put("size", String.valueOf(data.imageSize));
volleyParams.put("width", String.valueOf(data.imageWidth));
volleyParams.put("height", String.valueOf(data.imageHeight));
volleyParams.put("isIndex", updateProfilePhoto ? "1" : "0");

final Context context = this;
final String twoHyphens = "--";
final String lineEnd = "\r\n";
final String boundary = "apiclient-" + System.currentTimeMillis();
final String mimeType = "multipart/form-data;boundary=" + boundary;
byte[] multipartBody = new byte[0];

ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
try {
// the first file
buildPart(dos, data.thumbnailImageArray, "file0");
// the second file
buildPart(dos, data.scaledImageArray, "file1");
// send multipart form data necesssary after file data
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// pass to multipart body
multipartBody = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}

Map<String, String> headers = new HashMap<String, String>();
headers.put("User-Agent", Authentication.getUserAgent());
headers.put("X-XX-API", Authentication.getKey());

MultipartRequest multipartRequest = new MultipartRequest(BASE_URL + "member/photos", headers, volleyParams, mimeType, multipartBody, new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
Log.i(LOG_TAG, "response: " + response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {

Log.i(LOG_TAG, "statusCode = " + error.networkResponse.statusCode);
Log.i(LOG_TAG, "data = " + error.networkResponse.data);
Log.i(LOG_TAG, "headers = " + error.networkResponse.headers);
Log.i(LOG_TAG, "notModified = " + error.networkResponse.notModified);
Log.i(LOG_TAG, "networkTimeMs = " + error.networkResponse.networkTimeMs);
}
});

MySingleton.getInstance(context).addToRequestQueue(multipartRequest);


The call is performed, however the
getParams()
is never called. How can I ensure the
getParams()
is always called?

Answer

I have had the same problem. You need to override the getBody method and convert all your params to an array of bytes. For example, for a JSON request.

@Override
public String getBodyContentType() {
    return "application/json; charset=utf-8";
}

@Override
public byte[] getBody() {
    if (mParams == null) {
        return null;
    }

    try {
        return new Gson().toJson(mParams).getBytes("utf-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return null;
}