ThumbnailLoadTask.java revision 2ea06183aa826b28fe6ebdb454da49ba3878bc4f
1/*
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mail.ui;
19
20import android.content.res.AssetFileDescriptor;
21import android.graphics.Bitmap;
22import android.graphics.BitmapFactory;
23import android.net.Uri;
24import android.os.AsyncTask;
25
26import com.android.mail.providers.Attachment;
27import com.android.mail.utils.LogUtils;
28
29import java.io.IOException;
30
31/**
32 * Performs the load of a thumbnail bitmap in a background
33 * {@link AsyncTask}. Available for use with any view that implements
34 * the {@link AttachmentBitmapHolder} interface.
35 */
36public class ThumbnailLoadTask extends AsyncTask<Uri, Void, Bitmap> {
37    private static final String LOG_TAG = new LogUtils().getLogTag();
38
39    private final AttachmentBitmapHolder mHolder;
40    private final int mWidth;
41    private final int mHeight;
42
43    public static void setupThumbnailPreview(
44            ThumbnailLoadTask task, AttachmentBitmapHolder holder,
45            Attachment attachment, final Attachment prevAttachment) {
46        if (attachment == null) {
47            holder.setThumbnailToDefault();
48            return;
49        }
50
51        final Uri imageUri = attachment.getImageUri();
52        final Uri prevImageUri = (prevAttachment == null) ? null : prevAttachment.getImageUri();
53        // begin loading a thumbnail if this is an image and either the thumbnail or the original
54        // content is ready (and different from any existing image)
55        if (imageUri != null && (prevImageUri == null || !imageUri.equals(prevImageUri))) {
56            // cancel/dispose any existing task and start a new one
57            if (task != null) {
58                task.cancel(true);
59            }
60            task = new ThumbnailLoadTask(
61                    holder, holder.getThumbnailWidth(), holder.getThumbnailHeight());
62            task.execute(imageUri);
63        } else if (imageUri == null) {
64            // not an image, or no thumbnail exists. fall back to default.
65            // async image load must separately ensure the default appears upon load failure.
66            holder.setThumbnailToDefault();
67        }
68    }
69
70    public ThumbnailLoadTask(AttachmentBitmapHolder holder, int width, int height) {
71        mHolder = holder;
72        mWidth = width;
73        mHeight = height;
74    }
75
76    @Override
77    protected Bitmap doInBackground(Uri... params) {
78        final Uri thumbnailUri = params[0];
79
80        AssetFileDescriptor fd = null;
81        Bitmap result = null;
82
83        try {
84            fd = mHolder.getResolver().openAssetFileDescriptor(thumbnailUri, "r");
85            if (isCancelled() || fd == null) {
86                return null;
87            }
88
89            final BitmapFactory.Options opts = new BitmapFactory.Options();
90            opts.inJustDecodeBounds = true;
91
92            BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts);
93            if (isCancelled() || opts.outWidth == -1 || opts.outHeight == -1) {
94                return null;
95            }
96
97            opts.inJustDecodeBounds = false;
98
99            LogUtils.d(LOG_TAG, "in background, src w/h=%d/%d dst w/h=%d/%d, divider=%d",
100                    opts.outWidth, opts.outHeight, mWidth, mHeight, opts.inSampleSize);
101
102            result = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts);
103
104        } catch (Throwable t) {
105            LogUtils.e(LOG_TAG, t, "Unable to decode thumbnail %s", thumbnailUri);
106        } finally {
107            if (fd != null) {
108                try {
109                    fd.close();
110                } catch (IOException e) {
111                    LogUtils.e(LOG_TAG, e, "");
112                }
113            }
114        }
115
116        return result;
117    }
118
119    @Override
120    protected void onPostExecute(Bitmap result) {
121        if (result == null) {
122            LogUtils.d(LOG_TAG, "back in UI thread, decode failed");
123            mHolder.setThumbnailToDefault();
124            return;
125        }
126
127        LogUtils.d(LOG_TAG, "back in UI thread, decode success, w/h=%d/%d", result.getWidth(),
128                result.getHeight());
129        mHolder.setThumbnail(result);
130    }
131
132}
133