Exception in getting Image thumbnails in AsyncTask

552 Views Asked by At

I am getting the thumbnail of an Image in the doInBackground() method of the AsyncTask. The problem is while running the AsyncTask if I cancel the AsyncTask using cancel(). I am getting a strange exception in the logcat. The app is not terminating but the logcat is showing the exception message.

My doInBackground() is like below

protected Bitmap doInBackground(String... params) {
        Bitmap bitmap = null;
        String path = params[0];
        bitmap = getImageThumbnail(MainActivity.this,path);
        //Some cache mechanism
        return bitmap;
    }

getImageThumbnail Method

     public static Bitmap getImageThumbnail(Context context,String path) {
            ContentResolver cr = context.getContentResolver();
            Cursor ca = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.MediaColumns._ID}, MediaStore.MediaColumns.DATA + "=?", new String[]{path}, null);
            if (ca != null && ca.moveToFirst()) {
                int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
                ca.close();
                //At this line I am getting exception
                Bitmap thumbnail = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
                return thumbnail;
            }
            return ((BitmapDrawable) context.getResources().getDrawable(R.drawable.dummy)).getBitmap();
        }

While the async task is in runnign state if I call the asyncTask.cancel(true) I am getting the below message in logcat

06-11 17:49:45.380    1600-1708/com.sample.appl V/MiniThumbFile﹕ Got exception checking file magic:
    java.nio.channels.ClosedChannelException
            at java.nio.FileChannelImpl.checkOpen(FileChannelImpl.java:73)
            at java.nio.FileChannelImpl.lock(FileChannelImpl.java:161)
            at android.media.MiniThumbFile.getMagic(MiniThumbFile.java:161)
            at android.provider.MediaStore$InternalThumbnails.getThumbnail(MediaStore.java:635)
            at android.provider.MediaStore$Images$Thumbnails.getThumbnail(MediaStore.java:1008)
            at com.appsforbb.common.filesystem.ImageUtils.getImageThumbnail(ImageUtils.java:55)
            at com.appsforbb.basic.filemanager.CacheImageView$BitmapWorkerTask.doInBackground(CacheImageView.java:79)
            at com.appsforbb.basic.filemanager.CacheImageView$BitmapWorkerTask.doInBackground(CacheImageView.java:58)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)

How to avoid that exception??

2

There are 2 best solutions below

1
On

You are closing your cursor before creating your bitmap thumbnail, change your getImageThumbnail method to look like this:

public static Bitmap getImageThumbnail(Context context,String path) {
            ContentResolver cr = context.getContentResolver();
            Cursor ca = null;
            ca = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.MediaColumns._ID}, MediaStore.MediaColumns.DATA + "=?", new String[]{path}, null);
            if (ca != null && ca.moveToFirst()) {
                int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));

                //At this line I am getting exception
                Bitmap thumbnail = MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
                ca.close();
                return thumbnail;
            }
            return ((BitmapDrawable) context.getResources().getDrawable(R.drawable.dummy)).getBitmap();
        }
4
On

Use asyncTask.cancel(false) to cancel the async task. Then, check isCancelled() before calling getImageThumbnail() in your doInBackground().

Your doInBackground() will now be:

protected Bitmap doInBackground(String... params) {
    Bitmap bitmap = null;
    String path = params[0];
    if(!isCancelled()) {
        bitmap = getImageThumbnail(MainActivity.this,path);
        //Some cache mechanism
    }
    return bitmap;
}

You should also check isCancelled() before doing anything in postExecute().