Thursday, December 6, 2012

RESTful web service for picture upload Android client

In previous tutorial http://grumpyoldprogrammer.blogspot.com/2012/11/image-upload-via-restful-web-service.html I described how to create simple server application and deploy it on Tomcat. Now we are going to take a look at client application.
Simplest is to use Apache HttpComponents Client. It is possible to convert HttpMime jar for Android and import it as library. Since not all classes are required for picture upload we can download source and add the following files to project:

AbstractContentBody.java
ByteArrayBody.java
ContentBody.java
ContentDescriptor.java
FormBodyPart.java
Header.java
HttpMultipart.java
HttpMultipartMode.java
MIME.java
MinimalField.java
MultipartEntity.java
StringBody.java


Naturally whole project like this becomes Apache licensed. Some of those Java files are in org.apache.http.entity.mime.content package and others are in org.apache.http.entity.mime.
In this way we avoid compiling two files FileBody.java and InputStreamBody.java
Now will we go refactoring package names to fit them into project is of minor relevance, I usually do.
We create new Android project and we code onCreate like this:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    try {
        bm = BitmapFactory.decodeFile("/sdcard/DCIM/FinalM8.JPG");
        if(bm==null)
            throw new Exception("no picture!");
        new FetchItemsTask().execute();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


Please note that image path is hardcoded, so change it accordingly. Bitmap bm is loaded, defined as field, and if it is different from null we create and execute AsyncTask to upload picture. To keep things simple as possible we will implement only doInBackground, like this:

protected Void doInBackground(Void... arg0) {
    // TODO Auto-generated method stub
    try {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bm.compress(CompressFormat.JPEG, 50, bos);
        byte[] data = bos.toByteArray();
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost postRequest =
            new HttpPost("http://localhost:8080/WebApplication3/xyz/generic/images");
        ByteArrayBody bab = new ByteArrayBody(data, "FinalM8.JPG");
        MultipartEntity reqEntity = new MultipartEntity(
                HttpMultipartMode.BROWSER_COMPATIBLE);
        reqEntity.addPart("image", bab);
        postRequest.setEntity(reqEntity);
        HttpResponse response = httpClient.execute(postRequest);
        System.out.println("Status is "+response.getStatusLine());
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                response.getEntity().getContent(), "UTF-8"));
        String sResponse;
        StringBuilder s = new StringBuilder();
        while ((sResponse = reader.readLine()) != null) {
            s = s.append(sResponse);
        }
        System.out.println("Response: " + s);
    } catch (Exception e) {
        // handle exception here
        e.printStackTrace();
    }
    return null;
}


Image is compressed on 50%, loaded into byte array and upload is attempted. In order to run code just push onto emulator some image and change path.

No comments:

Post a Comment