NOTE:

NOTE: Of late, I have been getting requests for very trivial problems that many of you are facing in your day-to-day work. This blog is not to solve your "project" problems - surely not a "Support" site.
I just love to share my knowledge in my spare time and would appreciate any questions or feedback on the articles and code I have shared. I also do appreciate thought-provoking questions that would lead me to write more articles and share.
But please do not put your day-to-day trivial problems here. Even if you do, you most probably would not get a response here.
Thanks

Search This Blog

x

Wednesday 5 May 2010

Http Connection Using Threads & Handlers in Android (Part 19)

This is about how to invoke an Http Url from an android activity. If you have already written such a program in core java, you will not find anything new in the HTTP connectivity part. However, this tutorial also shows how to communicate between thread using the Message object.


In this tutorial, I plan to download 1 image and 1 text from the internet on the click of respective buttons on the android phone.

NOTE: I have also incidentally used Absolute Layout so that the buttons, the text and the image are all seen on the same screen even after being fetched.

Since fetching data from the internet can be a time-consuming task and a very unpredictable one at that, so, it would best be done in a separate thread rather than the UI/main thread. The basics of this have been discussed in the previous tutorial on Handlers and Threads.

To go to the application code directly, on the click of a button “Get Image”, I want to get an image whose URL is hard-coded in the program. For that first, I must open an HTTP connection to the server and then request for the image.

Hence is the code for opening and making an HTTP Connection:

private InputStream openHttpConnection(String urlStr) {
InputStream in = null;
int resCode = -1;
try {


URL url = new URL(urlStr);
URLConnection urlConn = url.openConnection();

if (!(urlConn instanceof HttpURLConnection)) {
throw new IOException ("URL is not an Http URL");
}

HttpURLConnection httpConn = (HttpURLConnection)urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
resCode = httpConn.getResponseCode();


if (resCode == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return in;
}
I will not be explaining this code much as most of this is based on the java.net package. This code would be exactly same even if we were to write this in regular java code, not meant for android usage. In brief, I have opened a URLConnection, checked if it is an instance of HttpURLConnection, set the parameters required and made the ‘connection’ finally by calling the connect() method. Then, I check if the response code is OK and I get a handle to the input stream.


So, this is a utility method that I will use for fetching image as well as text.

Now, coming to fetching the image. I want to fetch it when the end user clicks on a button “Get Image”. So the code associated with the button click is here:

getImageButton = (Button)findViewById(R.id.Button01);
getImageButton.setOnClickListener( new OnClickListener() {
Override
public void onClick(View v) {
downloadImage(http://www.android.com/media/wallpaper/gif/android_logo.gif);
                              }
               });

So the fetching of the image is in the downloadImage() method, which is given the URL of the android logo. Here is the method:

private void downloadImage(String urlStr) {
progressDialog = ProgressDialog.show(this, "", "Fetching Image...");
final String url = urlStr;
new Thread() {
public void run() {
InputStream in = null;
Message msg = Message.obtain();
msg.what = 1;
try {
in = openHttpConnection(url);
bitmap = BitmapFactory.decodeStream(in);
Bundle b = new Bundle();
b.putParcelable("bitmap", bitmap);
msg.setData(b);
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
messageHandler.sendMessage(msg);

}
}.start();
This method looks a bit complicated. First, let us look at the basics. If I were not fetching this in a separate thread, I would have just the 3 lines of code that is in Bold and highlighted. Open a connection, fetch the bitmap and close the connection. However, since this is a typical task that is unpredictable in its response time, it is best done in a separate thread of its own. So, before I start a new thread, I let the UI thread to show a ProgressDialog as shown in

progressDialog = ProgressDialog.show(this, "", "Fetching Image...");

Then, I start a new thread. I make the URL string accessible within the new thread by making it a final variable. Since message is an object that I can use for communication between threads, I create a Message object in the thread. Then, I set the message number to 1, so that I can use it later.
Message msg = Message.obtain();
msg.what = 1;
Then, I bundle my bitmap already fetched into a Bundle object that can be sent back in the Message object.
Bundle b = new Bundle();
b.putParcelable("bitmap", bitmap);
msg.setData(b);

Once I close the input stream as in:
 in.close();
the thread has completed the job. So, I notify the main / UI thread through this method and also pass on the Message object:
messageHandler.sendMessage(msg);
This completes the fetching of the image in a separate thread. Now, how do I retrieve the image from the Message object in the main thread?
As soon as the child thread notifies, the method called back in the main thread is the handleMessage(msg) method. It is in this method that I retrieve the bitmap and set it to the ImageView in the UI. Here it goes:


private Handler messageHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
ImageView img = (ImageView) findViewById(R.id.imageview01);
img.setImageBitmap((Bitmap)(msg.getData().getParcelable("bitmap")));
break;
case 2:
    ……….
}
progressDialog.dismiss();
}
        };

Within this method, first I check the msg.what variable to see what the type of message I am expecting is. If it is 1, which I had set in downloadImage(..) method, then, I do the required things to get a handle to the ImageView object and then give the bitmap to it.

How do I fetch the data from the msg object? Through getData(). Then I use the key “bitmap” to retrieve the bitmap and cast it to Bitmap before setting it to the ImageView. Finally, I dismiss the progress dialog.

I hope this is clear. This example not only shows HTTP Connection from Android but also the Thread-to-thread communication through handler, message exchange.

In a very similar fashion, I also fetch the text. On click of the Get Text button, here is the code that gets invoked:
getTextButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
downloadText(http://saigeethamn.blogspot.com/feeds/posts/default);
}
         });

The downloadText() code is here:

private void downloadText(String urlStr) {
progressDialog = ProgressDialog.show(this, "", "Fetching Text...");
final String url = urlStr;
new Thread () {
public void run() {
int BUFFER_SIZE = 2000;
InputStream in = null;
Message msg = Message.obtain();
msg.what=2;
try {
in = openHttpConnection(url);
InputStreamReader isr = new InputStreamReader(in);
int charRead;
text = "";
char[] inputBuffer = new char[BUFFER_SIZE];
while ((charRead = isr.read(inputBuffer))>0)
{
//---convert the chars to a String---
String readString =
String.copyValueOf(inputBuffer, 0, charRead);
text += readString;
inputBuffer = new char[BUFFER_SIZE];
}
Bundle b = new Bundle();
b.putString("text", text);
msg.setData(b);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
messageHandler.sendMessage(msg);
}
}.start();
}

And the way the text is handled in the main thread handleMessage(..) method is here:
case 2:
TextView text = (TextView) findViewById(R.id.textview01);
text.setText(msg.getData().getString("text"));
break;
The complete code can be downloaded here

 NOTE: the blog editor is posing major problems in editing - it is jumbling up the whole post esp. when I use the " feature. So, please bear with me if somethings look garbled. I have tried my best to work around the editor problem. This has been noticed only in the last 3 posts of mine. Hope it gets fixed soon.
Thanks for your understanding.

28 comments:

  1. Hi Sai Geetha...

    Really its very much useful samples.

    But i am facing an issue. when i am trying to download some images using this code its throwing some error as shown below ..

    06-21 16:07:18.493: DEBUG/skia(603): --- decoder->decode returned false.


    Can u please look in to that once and help us to get rid of that error.

    I didn't found any fruitful solution even in the forums also

    Thanks and Regards,
    Pavan UVR

    ReplyDelete
  2. The above code is working for most of the images

    But its not working for the image

    http://jquery.com/demo/thickbox/images/plant4.jpg

    i donno why its not working....

    can u please check this once

    ReplyDelete
  3. Hi Pavan....
    You can always run your program into debug mode and check if any exception occurred. Regarding your query, if the resource file (that is, the image that u r trying to load) is too big, then it might not load... This might be a reason too.. have u checked the code for any other images?

    ReplyDelete
  4. Yes Arin, The same code is working well for the other Images.

    ReplyDelete
  5. Hi Pavan,

    Do you realize that the image in my code is 12 KB while the one you are trying is 207 KB. Resources are very limited in the mobile domain. Please remember that.

    ReplyDelete
  6. Hey geetha,
    nice article. I am currently using async task to do my network operation but what i am planning to do is use a background thread to do my data download from the webservice meanwhile i will display the old data from the database.

    my question is if i use a thread and handler in my main activity and the user moves to another activity when the thread finishes its download how will the handler work? will it automatically go to the activity that created the handler??

    ReplyDelete
  7. Hi Sandeep,

    I think you need to see this google video so that you validate your design for backend web service calls against thier best practices:
    http://www.youtube.com/watch?v=xHXn3Kg2IQE
    and doc at
    http://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf

    ReplyDelete
  8. Dear Sister Geetha, my name is Bala, i am a B-Tech student, the scope of my final year project is to "Take an image from android mobile camera and upload to the web server. once start the application, the device should automatically capture image from the camera for every few seconds and upload to web server in real time".

    i am very new to Android as well as java and struggling with the Android code on mobile side and php code on server side. i am using eclipse SDK version 3.6.1

    please help me give some advice or if possible give me the source code to perform the above mentioned task. i am working on this for 3 months day & night, so far no solution yet. Today only i come across your blog and very excited with all your explanation about android.

    kindly contact to my Email: "mtbalaict@gmail.com" i will send you the code that i have.
    my mobile: +65 91310837
    i am from tamilnadu, currently working and studying in singapore.
    Thanks a lot for your help... jai shiridi Sairam!

    ReplyDelete
  9. Hi Geeta,

    I have gone through some of your examples and found them to be really helpful.

    I have been trying out a Android Client app running in emulator which must be able to communicate to a Server running on my PC through text messages. For the whole purpose I have been using the HTTP protocol and its methods,but haven't been successful so far.
    Can you please provide me some help in this regard, a example for such a Client Server is what I am looking for.

    ReplyDelete
  10. hai geetha u r code really useful so i have one doubt i want to connect to some site and search for meaning and retrive the first meaning of given results in html form can u heip me to finish that work

    ReplyDelete
  11. hi geetha,

    i downloaded ur app and tried to downlaod n view an image on another device(recognised by a static IP) connected to the same wifi as the first device....its wasnt possible....it worked for almost all low-size images as mentioned above but cudnt recieve the image from the other device's sdcard...can u please shed some light on this topic???

    ReplyDelete
  12. Will it possible for you to provide a tutorial on how to parse XML response and display it?

    Thanks

    ReplyDelete
  13. hi geetha,

    i have worked out this httpconnection samples reading images and text. its really useful to my project. thanks a lot

    ReplyDelete
  14. Hi Geetha,

    A vry helpful artical u shared with all of us..

    I m new to android..
    i need to establish a https connection and send/recieve data...
    can u plz guide me.how to approach towards my job

    Thanks and Regards
    Nisha

    ReplyDelete
  15. Thank you,Its really Helpful.

    ReplyDelete
  16. hi sai geetha,
    Thanks for such a informative tutorial..i've been facing an issue with the emulator..How to enable internet on my AVD? i am using windows7 and a data card for internet access...
    i want to test some apps(webview,maps etc)...there were so many posts on net about this but none solved my problem..any kinda inputs would be helpful..thank you..BTW ur tutorials are very helpful...

    ReplyDelete
  17. Hi, Thanks for this tutorial, but my app is very slow to parsing data from server with JSON... I've tryed to change the buffer size in: BufferedReader reader = new BufferedReader(new InputStreamReader(is), 8*1024); But is the same....Sometimes i have to wait 15 seconds and then the activity is shown. (Tested with Galaxy Tab with 1Ghz CPU, 512Mb RAM and 2MB/s Wifi connection).

    ReplyDelete
  18. Hello Sai Mam,
    Your blog's help me lot...
    Thank you...

    ReplyDelete
  19. Hi Sai Geetha!! Your posts are really helpful.
    Hi Guys is there any interested person to work with me on a android project?
    My email id is karim.ece042@gmail.com

    ReplyDelete
    Replies
    1. Hi, i am working on Android Development and looking forward to work more on interesting projects in android.You can contact me @ sav.accharya@gmail.com.

      Delete
  20. This comment has been removed by the author.

    ReplyDelete
  21. Dear Sai,

    First of all many thanks for your clear blog. I am pretty new in Android. I tried some of your samplecodes and after solving some Eclips-"problems" it works very good..
    In this sample I tried, without success, to change the code so it can load and show two images (different url) after pressing the button. I am messing with Bitmap1 and Bitmap2. Is there someone who can help me with the right structure? Thanks Eugene.

    ReplyDelete
  22. your tutorials are the best.......

    ReplyDelete
  23. Hello Sai, i have a problem at downloading image.
    It seems its problem around the bitmap,cause i m geting NullPointerException on
    img.setImageBitmap((Bitmap) (msg.getData().getParcelable("bitmap")));
    i have everythin from your guide so really no clue why i have this problem.
    Can u help me with solving this ? :)

    ReplyDelete
  24. please tell me how to pass a string to another emulator.. using tcp socket connection

    ReplyDelete
  25. Hello All,

    I'm an M.Tech student working on an android project.
    I need to send some data from the html page to android phone.
    As I'm new to this, I need some help.
    Expecting an urgent reply.
    Thanks.....

    ReplyDelete
  26. hello sir,
    i mae an app using http connection in that i sent data from android app to mysql database sucessfully but am unable to fetch data from mysql database wht to do plz tell me,
    and cant we do that without using json? just want to print data fetch in android app from mysql??

    ReplyDelete