Monday 12 August 2013

Efficient android image downloader to over come error java.lang.OutOfMemoryError: bitmap size exceeds VM budget

ImageDownloader :

public class ImageDownloader {

Map<String,Bitmap> imageCache;
private Bitmap defaultIcon;

public ImageDownloader(){
imageCache = new HashMap<String, Bitmap>();

}

//download function
public void download(String url, ImageView imageView,Bitmap defaultImg) {
    if (cancelPotentialDownload(url, imageView)) {
   
    this.defaultIcon=defaultImg;
    //Caching code right here
    String filename = String.valueOf(url.hashCode());
    File f = new File(getCacheDirectory(imageView.getContext()), filename);

     // Is the bitmap in our memory cache?
    Bitmap bitmap = null;
   
     bitmap = (Bitmap)imageCache.get(f.getPath());
   
     if(bitmap == null){
   
     bitmap = BitmapFactory.decodeFile(f.getPath());
   
     if(bitmap != null){
     imageCache.put(f.getPath(), bitmap);
     }
   
     }
     //No? download it
     if(bitmap == null){
     BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
   
     DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task,null,defaultImg);
     imageView.setImageDrawable(downloadedDrawable);
     imageView.setBackgroundDrawable(null);
     task.execute(url);
     }else{
     //Yes? set the image
     imageView.setImageBitmap(bitmap);
     imageView.setBackgroundDrawable(null);
     }
    }
}

//cancel a download (internal only)
private static boolean cancelPotentialDownload(String url, ImageView imageView) {
   BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

   if (bitmapDownloaderTask != null) {
       String bitmapUrl = bitmapDownloaderTask.url;
       if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
           bitmapDownloaderTask.cancel(true);
       } else {
           // The same URL is already being downloaded.
           return false;
       }
   }
   return true;
}

//gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
   if (imageView != null) {
       Drawable drawable = imageView.getDrawable();
       if (drawable instanceof DownloadedDrawable) {
           DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
           return downloadedDrawable.getBitmapDownloaderTask();
       }
   }
   return null;
}

//our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context){
String sdState = android.os.Environment.getExternalStorageState();
File cacheDir;
   
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();

//TODO : Change your diretcory here
cacheDir = new File(sdDir,"data/tac/images");
}
else
cacheDir = context.getCacheDir();

if(!cacheDir.exists())
cacheDir.mkdirs();
return cacheDir;
}

private void writeFile(Bitmap bmp, File f) {
 FileOutputStream out = null;

 try {
   out = new FileOutputStream(f);
   bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
 } catch (Exception e) {
   e.printStackTrace();
 }
 finally {
   try { if (out != null ) out.close(); }
   catch(Exception ex) {}
 }
}
///////////////////////

//download asynctask
    public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    private String url;
        private final WeakReference<ImageView> imageViewReference;

        public BitmapDownloaderTask(ImageView imageView) {
            imageViewReference = new WeakReference<ImageView>(imageView);
   
        }

        @Override
        // Actual download method, run in the task thread
        protected Bitmap doInBackground(String... params) {
             // params comes from the execute() call: params[0] is the url.
        url = (String)params[0];
             return downloadBitmap(params[0]);
        }

        @Override
        // Once the image is downloaded, associates it to the imageView
        protected void onPostExecute(Bitmap bitmap) {
            if (isCancelled()) {
                bitmap = null;
            }

            if (imageViewReference != null) {
                ImageView imageView = imageViewReference.get();
                BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
                // Change bitmap only if this process is still associated with it
                if (this == bitmapDownloaderTask) {
                    imageView.setImageBitmap(bitmap);
                   
                    //cache the image
                   
                   
                    String filename = String.valueOf(url.hashCode());
            File f = new File(getCacheDirectory(imageView.getContext()), filename);
           
            imageCache.put(f.getPath(), bitmap);
           
                    writeFile(bitmap, f);
                }
            }
        }
       
       
    }
   
//    static class DownloadedDrawable extends ColorDrawable {
//        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
//
//        public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
//          super(Color.TRANSPARENT);
//            bitmapDownloaderTaskReference =
//                new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
//        }
//
//        public BitmapDownloaderTask getBitmapDownloaderTask() {
//            return bitmapDownloaderTaskReference.get();
//        }
//    }
   
    private static class DownloadedDrawable extends BitmapDrawable {
        private final WeakReference<BitmapDownloaderTask>
           bitmapDownloaderTaskReference;

        private DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask,
           Resources resources, Bitmap bitmap) {
            super(resources, bitmap); // you'll have to provide these
            bitmapDownloaderTaskReference =
                new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference.get();
        }
    }
   
    //the actual download code
    static Bitmap downloadBitmap(String url) {
    url=url.replace(" ", "%20");
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
    HttpClient client = new DefaultHttpClient(params);
        final HttpGet getRequest = new HttpGet(url);

        try {
            HttpResponse response = client.execute(getRequest);
            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
                return null;
            }
           
            final HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = null;
                try {
                    inputStream = entity.getContent();
                    final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    return bitmap;
                } finally {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    entity.consumeContent();
                }
            }
        } catch (Exception e) {
            // Could provide a more explicit error message for IOException or IllegalStateException
            getRequest.abort();
            Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString());
        } finally {
            if (client != null) {
                //client.close();
            }
        }
        return null;
    }
}

How to use:


ImageDownloader downloader = new ImageDownloader();

downloader.download(stringUrl,
imageViewProfile, defaultImgBitmap);

Android interview questions




  • What is Android?

    Android is a software stack for mobile devices that includes an operating system, middleware and key applications. The application runs in its own process and its own instance of Dalvik virtual machine. Many virtual machines are efficiently by a DVM device. DVM run Java bytecode languages ​​which later turns into. DEX files format.

    History


    Android, Inc. was founded in Palo Alto, California in October 2003 by Andy Rubin (co-founder of Danger), Rich Miner (co-founder of Wildfire Communications, Inc.), Nick Sears (once VP at T-Mobile), and Chris White (headed design and interface development at WebTV) to develop, in Rubin's words "smarter mobile devices that are more aware of its owner's location and preferences". The early intentions of the company were to develop an advanced operating system for digital cameras, when it was realised that the market for the devices was not large enough, and diverted their efforts to producing a smartphone operating system to rival those of Symbian and Windows Mobile (Apple's iPhone had not been released at the time). Despite the past accomplishments of the founders and early employees, Android Inc. operated secretly, revealing only that it was working on software for mobile phones. That same year, Rubin ran out of money. Steve Perlman, a close friend of Rubin, brought him $10,000 in cash in an envelope and refused a stake in the company .

     Android Architecture?

    Android Architecture is made up of 4 key components:
    - Linux Kernel
    - Libraries
    - Android Framework
    - Android Applications

    Describe Activities.

    Activities are what you refer to as the window to a user interface. Just as you create windows in order to display output or to ask for an input in the form of dialog boxes, activities play the same role, though it may not always be in the form of a user interface.

    What are the core components under the Android application architecture?

    There are 5 key components under the Android application architecture:
    - services
    - intent
    - resource externalization
    - notifications
    - content providers

    What are Intents?

    Intents displays notification messages to the user from within the Android enabled device. It can be used to alert the user of a particular state that occurred. Users can be made to respond to intents.

    What are the core components under the Android application architecture?

    There are 5 key components under the Android application architecture:
    - services
    - intent
    - resource externalization
    - notifications
    - content providers

     Differentiate Activities from Services.

    Activities can be closed, or terminated anytime the user wishes. On the other hand, services are designed to run behind the scenes, and can act independently. Most services run continuously, regardless of whether there are certain or no activities being executed.

     What items are important in every Android project?

    These are the essential items that are present each time an Android project is created:
    - AndroidManifest.xml
    - build.xml
    - bin/
    - src/
    - res/
    - assets/

    What is ANR?

    ANR is short for Application Not Responding. This is actually a dialog that appears to the user whenever an application have been unresponsive for a long period of time.

     How can the ANR be prevented?

    One technique that prevents the Android system from concluding a code that has been responsive for a long period of time is to create a child thread. Within the child thread, most of the actual workings of the codes can be placed, so that the main thread runs with minimal periods of unresponsive times.

     When does ANR occur?

    The ANR dialog is displayed to the user based on two possible conditions. One is when there is no response to an input event within 5 seconds, and the other is when a broadcast receiver is not done executing within 10 seconds.

    What is AIDL?

    AIDL, or Android Interface Definition Language, handles the interface requirements between a client and a service so both can communicate at the same level through interprocess communication or IPC. This process involves breaking down objects into primitives that Android can understand. This part is required simply because a process cannot access the memory of the other process.

    What data types are supported by AIDL?

    AIDL has support for the following data types:
    -string
    -charSequence
    -List
    -Map

    -all native Java data types like int,long, char and Boolean