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.
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 unregister 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.
1. 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); } }
2. 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(); }
3. 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"); } }
4. 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; } }
5. 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("Error in downloading image"); } } }
6. 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); } } }