How to download Image in blackberry


This tutorial explains “How to download Image in blackberry” from remote server using HTTP connection on different networks (Wi-Fi, WAP, and 3G).  Below example is using Observer design pattern which is listed under the Behavioral design patterns category from globally used Gang-Of-Four (GOF) patterns.

1. Overview of Observer Design pattern

It is used to implement the Publisher/Subscriber scenario. We need a mechanism which allows us to notify subscriber objects whenever the publisher object changes state. For observers to receive a notification, they must implement some kind of update method/listeners which the subject can call whenever it changes state. The observers must have the freedom to register and un-register from subscription to the subject at any point in time.

Here in this example the subscriber object is the Blackberry UI thread and the publisher object is the Networking/Downloading thread. Network thread has to notify the UI thread once it complete or failed to download. And then the UI thread takes the control and updates the information in UI.

2. Create and Blackberry UIApplication project

package com.javatechig.bb.java.ui;
import net.rim.device.api.ui.UiApplication;
public class DownloadMain extends UiApplication {
  public static void main(String[] args) {
          DownloadMain app = new DownloadMain();
         app.enterEventDispatcher();
 }
  public DownloadMain() {
         ImageDownloadScreen screen = new ImageDownloadScreen();
        pushScreen(screen);
  }
}

3. Create an “DownloadListener” interface

Here I am declaring two methods downloadSuccess() and errorOccured().
package com.javatechig.bb.java.ui;
import net.rim.device.api.system.Bitmap;
public interface DownloadListener {
       // invokes if download success
       public void downloadSuccess(Bitmap bitmap);

    // invokes if download failed
    public void errorOccured();
}

4. Create a Screen class and extends from MainScreen

This class will have the logic to implement all of the UI controls. Here in this example I am creating a button “Click to download”. My screen class is implementing the “DownloadListener” interface and overrides the downloadSuccess() and errorOccured() method. downloadSuccess() method used to perform all the UI activity, like update to UI if the download success. And errorOccured() method is for displaying the error message to UI if failed to download. Find the code below
package com.javatechig.bb.java.ui;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.Dialog;
public class ImageDownloadScreen extends LoaderScreen implements DownloadListener{
    ImageDownloadScreen activeScreen = null;
    public ImageDownloadScreen() {
        setTitle("Download Image");
        ButtonField btn = new ButtonField("Click to Download", ButtonField.CONSUME_CLICK) {
            protected boolean navigationClick(int arg0, int arg1) {
                setShowLoader(true);
                //starting download thread
                ImageDownloader download = new ImageDownloader("http://www.ciracar.com/img/girls/cute_selena_gomez/cute_selena_gomez7.jpg");
                download.setDelegate(activeScreen);
                //Starting download thread
                new Thread(download).start();
                return true;
            }
        }
        ;
        //adding button to screen
        add(btn);
        //getting the reference of active screen
        activeScreen = this;
    }
    // Method to perform all the UI activity, like update to UI if the download success
    public void downloadSuccess(final Bitmap bitmap) {
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run() {
                setShowLoader(false);
                if (bitmap == null) {
                    Dialog.alert("Failed to download Image");
                }
                else {
                    try {
                        BitmapField image = new BitmapField(bitmap);
                        activeScreen.add(image);
                    }
                    catch (Exception e) {
                        Dialog.alert("Got error: " + e);
                    }
                }
            }
        }
        );
    }
    //display error message if error in download
    public void errorOccured() {
        //Currently not being used
        Dialog.alert("Failed to download Image");
    }
}

5. Using a generic NetRequest class for separating all networking logic from the UI

Currently it has updateConnSuffix() method. This method updates the connection suffix required for different networks in blackberry. You can also write your logic and enhance this to prioritize the network connection usages. Find the code below
import net.rim.device.api.servicebook.ServiceRecord;
import net.rim.device.api.system.DeviceInfo;
import net.rim.device.api.system.RadioInfo;
import net.rim.device.api.system.WLANInfo;
public class NetRequest {
    protected String updateConnSuffix() {
        String connSuffix = null;
        if (DeviceInfo.isSimulator()) {
            connSuffix = ";deviceside=true";
        } else if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) && 
                   RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) {
            connSuffix = ";interface=wifi";
        } else {
            String uid = null;
            ServiceBook sb = ServiceBook.getSB();
            ServiceRecord[] records = sb.findRecordsByCid("WPTCP");
            for (int i = 0; i < records.length; i++) {
                if (records[i].isValid() && !records[i].isDisabled()) {
                    if (records[i].getUid() != null && records[i].getUid().length() != 0) {
                        if ((records[i].getCid().toLowerCase().indexOf("wptcp") != -1) &&
                            (records[i].getUid().toLowerCase().indexOf("wifi") == -1) &&
                            (records[i].getUid().toLowerCase().indexOf("mms") == -1)) {
                            uid = records[i].getUid();
                            break;
                        }
                    }
                }
            }
            if (uid != null) {
                // WAP2 Connection 
                connSuffix = ";ConnectionUID=" + uid;
            } else {
                connSuffix = ";deviceside=true";
            }
        }
        return connSuffix;
    }
}

6.  Declare “ImageDownloader” class to put all the downloading logic separately from UI.

Here I am extending from NetRrquest as I want to reuse the “NetRequest” code for all of the networking logic we write. You can always open yourself to write in your own way. Find the code below
package com.javatechig.bb.java.net;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import com.javatechig.java.ui.DownloadListener;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.component.Dialog;
public class ImageDownloader extends NetRequest implements Runnable {
    // Holds the URL to download the image
    StringBuffer url = null;
    //holds the instance of the delegate screen
    protected Object delegate;
    public ImageDownloader(String url) {
        // image URL
        this.url = new StringBuffer();
        this.url.append(url.toString());
    }
    //taking the instance of the delegate
    //this is the object of the active screen from where the request is made
    public Object getDelegate() {
        return delegate;
    }
    public void setDelegate(Object delegate) {
        this.delegate = delegate;
    }
    // Thread starts the execution
    public void run() {
        byte[] dataArray;
        InputStream input;
        url.append(updateConnSuffix());
        HttpConnection httpConn = null;
        try {
            httpConn = (HttpConnection) Connector.open(url.toString());
            input = httpConn.openInputStream();
            dataArray = net.rim.device.api.io.IOUtilities.streamToBytes(input);
            final Bitmap googleImage = Bitmap.createBitmapFromBytes( dataArray, 0, -1, 1);
            ((DownloadListener) delegate).downloadSuccess(googleImage);
        }
        catch (IOException e) {
            e.printStackTrace();
            Dialog.alert("Eoor in downloading image");
        }
    }
}

7. Showing loading progress in UI while the download is under progress

For this I have used a generic class “LoaderScreen” which extends MainScreen class. I am using “TimerTask” class for showing the loading animations.
package com.javatechig.bb.java.ui;
import java.util.Timer;
import java.util.TimerTask;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.container.MainScreen;
public class LoaderScreen extends MainScreen {
    Timer loadingTimer = new Timer();
    TimerTask loadingTask;
    int imageIndex = 0;
    Bitmap loader1 = Bitmap.getBitmapResource("loader001.png");
    Bitmap loader2 = Bitmap.getBitmapResource("loader002.png");
    Bitmap loader3 = Bitmap.getBitmapResource("loader003.png");
    Bitmap loader4 = Bitmap.getBitmapResource("loader004.png");
    Bitmap loader5 = Bitmap.getBitmapResource("loader005.png");
    Bitmap loader6 = Bitmap.getBitmapResource("loader006.png");
    Bitmap loader7 = Bitmap.getBitmapResource("loader007.png");
    Bitmap loader8 = Bitmap.getBitmapResource("loader008.png");
    Bitmap loader9 = Bitmap.getBitmapResource("loader009.png");
    Bitmap loader10 = Bitmap.getBitmapResource("loader010.png");
    Bitmap loader11 = Bitmap.getBitmapResource("loader011.png");
    Bitmap loader12 = Bitmap.getBitmapResource("loader012.png");
    boolean showLoader = false;
    int screenWidth = Display.getWidth();
    int screenHeight = Display.getHeight();
    int xAnchor = (screenWidth-200)/2;
    int yAnchor = (screenHeight-40)/2;
    String loaderText = "Please wait...";
    public LoaderScreen() {
        super();
        loadingTask = new TimerTask() {
            public void run() {
                invalidate();
                imageIndex++;
                if(imageIndex == 11){
                    imageIndex = 0;
                }
            }
        }
        ;
        loadingTimer.scheduleAtFixedRate(loadingTask, 100, 100);
    }
    public void setShowLoader(boolean showLoader) {
        this.showLoader = showLoader;
    }
    public boolean isShowing(){
        return showLoader;
    }
    protected void paint(Graphics graphics) {
        super.paint(graphics);
        if (showLoader) {
            //draw background:
            graphics.setColor(0x363636);
            graphics.fillRect(xAnchor, yAnchor, 200, 40);
            //draw animation frame:
            switch (imageIndex) {
                case 0:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader1, 0, 0);
                break;
                case 1:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader2, 0, 0);
                break;
                case 2:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader3, 0, 0);
                break;
                case 3:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader4, 0, 0);
                break;
                case 4:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader5, 0, 0);
                break;
                case 5:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader6, 0, 0);
                break;
                case 6:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader7, 0, 0);
                break;
                case 7:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader8, 0, 0);
                break;
                case 8:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader9, 0, 0);
                break;
                case 9:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader10, 0, 0);
                break;
                case 10:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader11, 0, 0);
                break;
                case 11:
                graphics.drawBitmap(xAnchor + 4, yAnchor + 4, 32, 32, loader12, 0, 0);
                break;
            }
            graphics.setColor(0xefefef);
            graphics.drawText(loaderText, xAnchor + 44, yAnchor + 6);
            graphics.setColor(0xff0000);
            graphics.drawRect(xAnchor, yAnchor, 200, 40);
        }
    }
}

About 

A game lover, father and a programmer. He had worked as a professor in Image Collegge of Arts and Animation and in some of the top production house like EA, Gameloft, Digital Chocolate.

Share this post:

PinIt
  • Dev. Desai

    How about downloading multiple list items asyncly. ? can you please provide me some samples or some idea to implement the same. I want to have a scrollable list with a icon, and two headings for each row. Any samples would help.

    • http://javatechig.com Javatechig

      You have to go for thread pool design pattern. Where you have to maintain the maximum pool size and play around with the worker threads. Below are the ideas to implement the same
      1. Create one TaskWorker for your application (use singelton)
      2. Implement Task class from TaskWorker – DownloadImageTask (simply put everything from Runnable.run() to Task.doTask() method)
      3. Instead of new thread creation for every image download, just add tasks to queue TaskWorker.addTask()
      You have to keep the thread safety in mind.

  • Enrim

    Nice one. It would be good if you could put some screenshots along with post.

  • Raj

    This post is really helpful. Thank you.

  • Jithin

    Hi, I am a new bee to Blackberry development.

    Can you please provide me the logic to save the image into SDCard after downloading?
    Any help will be appreciated.

    -Subash

  • Vicky

    Nice blog.. I will love to follow it.

  • Joy Yuost

    I am JOY, happened to have your code from google code. But it doesnt seems to be compiled. Can you help me to understand where it is going wrong?
    As i am a bignner to BB programming, my question might be a silly one.

    Thanks in advance.

Fork me on GitHub