1

While integrating Weibo's Android SDK into an app, I discovered the HttpClient class it contains uses an obsolete library that Android dislikes intensely (in fact I think they just pasted a Java SDK into an Android Eclipse project and shipped it). This library only seems to perform a single function within Weibo, which is to assemble POST requests (using the PostMethod class) and send them to the Weibo server. I blithely assumed it would be relatively straightforward to replace this with the standard Apache HttpPost, which is included in Android.

Unfortunately the Part class seems to have no straightforward equivalent. At least some of the Parts could be replaced by BasicNameValuePair classes, but there is a custom Part defined by Weibo that looks more like a ByteArrayEntity.

Examining the two methods called multPartUrl (not a typo) in

Weibo's source for HttpClient

the first of which is reproduced here (the second is very similar but pastes in a different type of content):

public Response multPartURL(String url,  PostParameter[] params,ImageItem item,boolean authenticated) throws WeiboException{
  PostMethod post = new PostMethod(url);
  try {
    org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient();
    long t = System.currentTimeMillis();
    Part[] parts=null;
    if(params==null){
      parts=new Part[1];
    }else{
      parts=new Part[params.length+1];
    }
    if (params != null ) {
      int i=0;
        for (PostParameter entry : params) {
          parts[i++]=new StringPart( entry.getName(),(String)entry.getValue());
      }
        parts[parts.length-1]=new ByteArrayPart(item.getContent(), item.getName(), item.getImageType());
      }
    post.setRequestEntity( new MultipartRequestEntity(parts, post.getParams()) );
     List<Header> headers = new ArrayList<Header>();

     if (authenticated) {
              if (basic == null && oauth == null) {
              }
              String authorization = null;
              if (null != oauth) {
                  // use OAuth
                  authorization = oauth.generateAuthorizationHeader( "POST" , url, params, oauthToken);
              } else if (null != basic) {
                  // use Basic Auth
                  authorization = this.basic;
              } else {
                  throw new IllegalStateException(
                          "Neither user ID/password combination nor OAuth consumer key/secret combination supplied");
              }
              headers.add(new Header("Authorization", authorization));
              log("Authorization: " + authorization);
          }
      client.getHostConfiguration().getParams().setParameter("http.default-headers", headers);
    client.executeMethod(post);

    Response response=new Response();
    response.setResponseAsString(post.getResponseBodyAsString());
    response.setStatusCode(post.getStatusCode());

    log("multPartURL URL:" + url + ", result:" + response + ", time:" + (System.currentTimeMillis() - t));
      return response;
  } catch (Exception ex) {
     throw new WeiboException(ex.getMessage(), ex, -1);
  } finally {
    post.releaseConnection();
  }
}

it can be seen that a number of Parts are added to a MultiPartRequestEntity, the last of which is a byte array or a file.

  • What (if anything) is the equivalent to MultiPartRequestEntity in the more up to date Apache libraries?
  • Is there a way to add a byte array to a UrlEncodedFormEntity?
  • Is there, alternatively, a way to add name-value pairs to a ByteArrayEntity?
  • Is there something else I am missing completely?
Andrew Wyld
  • 7,133
  • 7
  • 54
  • 96

1 Answers1

0

The best answer I've found so far seems to be based on the answer to this question:

Post multipart request with Android SDK

This shows where to get the non-obsolete replacements for the libraries used by Weibo.

I've then replaced

Part[] parts=null;
if(params==null){
  parts=new Part[1];
}else{
  parts=new Part[params.length+1];
}
if (params != null ) {
  int i=0;
    for (PostParameter entry : params) {
      parts[i++]=new StringPart( entry.getName(),(String)entry.getValue());
  }
    parts[parts.length-1]=new ByteArrayPart(item.getContent(), item.getName(), item.getImageType());
  }
post.setRequestEntity( new MultipartRequestEntity(parts, post.getParams()) );

with

        MultipartEntity entity = new MultipartEntity();
        if(params!=null) {
            for (PostParameter entry : params) {
                entity.addPart(entry.getName(), new StringBody(entry.getValue()));
            }
        }

        entity.addPart("filename", new ByteArrayBody(item.getContent(), item.getImageType(), item.getName()));

I'm not 100% certain about the last line as I've based that on Weibo's own class, which sets a filename parameter; however, it could well be called something else, though what is not clear.

I've then replaced the HttpClient with an AndroidHttpClient and used standard AndroidHttpClient methods to get the status code and an InputStream with the content from the entity; this stream, I am passing into the Weibo Response class and reading into the string it has as its main member. These assumptions may be wrong but I will continue to look into it.

Community
  • 1
  • 1
Andrew Wyld
  • 7,133
  • 7
  • 54
  • 96