Showing posts with label AsyncTask. Show all posts
Showing posts with label AsyncTask. Show all posts

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.

Saturday, October 27, 2012

Tutorial part 3

In this part we are going to take a look at AsyncTask which is light-weight framework intended to save programmers from concurrency traps and handling of Java threads.

AsyncTask

Most important thing is AsyncTask is intended to be used on UI thread, so do not try to use it elsewhere. Signature is android.os.AsyncTask and you can use them or ignore them and replace unused ones with Void. If you are planning to pass array of strings as parameters and not use progress or result than it becomes android.os.AsyncTask.
There are four commonly used and overridden methods:

protected void onPreExecute ()
protected abstract Result doInBackground (Params... params)
protected void onProgressUpdate (Progress... values)
protected void onPostExecute (Result result)


obviously only doInBacground is compulsory to override and that is only one which is not executing on UI thread. Typical implementation looks like this:

private class FetchItemsTask extends AsyncTask {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog.setMessage("Downloading. Please wait...");
        progressDialog.show();
    }
    @Override
    protected Void doInBackground(Void... params) {
        do some heavy I/O work here
        return null;
    }
    @Override
    protected void onPostExecute(Void result) {
        pass to UI result of work here
        progressDialog.dismiss();
    }
}


Usually it is declared as inner class inside Activity and we have instance of ProgressDialog accessible.
It is not full size threading framework, it should be used as suggested to do lengthy I/O operations. That lengthy is few seconds not few minutes. So good candidate for downloading image from Internet or pulling data from DB. Very good idea here is to go to your Android SDK Manager and to download source code and see how implementation of AsyncTask looks like. Equally good idea is to place logging at every method and log ID of current thread, so that we can be sure where is what executed.
If we take a look at my example in git://github.com/FBulovic/grumpyoldprogrammer.git we will see that my BroadcastReceiver contains  AsyncTask. Knowing that  AsyncTask can bi instantiated only from UI thread we can conclude that  BroadcastReceiver is also executed on UI thread. That was nice intro to CursorAdapter and ContentProvider where execution happens outside of UI thread but they need to communicate with UI thread and that may course some problems here and there. Especially you want to access SQLite DB directly without using ContentProvider.
Next part of this tutorial will follow, soon.