/* * Copyright (C) 2012 Google Inc. * Licensed to The Android Open Source Project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.mail.ui; import android.content.res.AssetFileDescriptor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import com.android.mail.providers.Attachment; import com.android.mail.utils.LogUtils; import java.io.IOException; /** * Performs the load of a thumbnail bitmap in a background * {@link AsyncTask}. Available for use with any view that implements * the {@link AttachmentBitmapHolder} interface. */ public class ThumbnailLoadTask extends AsyncTask { private static final String LOG_TAG = new LogUtils().getLogTag(); private final AttachmentBitmapHolder mHolder; private final int mWidth; private final int mHeight; public static void setupThumbnailPreview( ThumbnailLoadTask task, AttachmentBitmapHolder holder, Attachment attachment, final Attachment prevAttachment) { if (attachment == null) { holder.setThumbnailToDefault(); return; } final Uri imageUri = attachment.getImageUri(); final Uri prevImageUri = (prevAttachment == null) ? null : prevAttachment.getImageUri(); // begin loading a thumbnail if this is an image and either the thumbnail or the original // content is ready (and different from any existing image) if (imageUri != null && (prevImageUri == null || !imageUri.equals(prevImageUri))) { // cancel/dispose any existing task and start a new one if (task != null) { task.cancel(true); } task = new ThumbnailLoadTask( holder, holder.getThumbnailWidth(), holder.getThumbnailHeight()); task.execute(imageUri); } else if (imageUri == null) { // not an image, or no thumbnail exists. fall back to default. // async image load must separately ensure the default appears upon load failure. holder.setThumbnailToDefault(); } } public ThumbnailLoadTask(AttachmentBitmapHolder holder, int width, int height) { mHolder = holder; mWidth = width; mHeight = height; } @Override protected Bitmap doInBackground(Uri... params) { final Uri thumbnailUri = params[0]; AssetFileDescriptor fd = null; Bitmap result = null; try { fd = mHolder.getResolver().openAssetFileDescriptor(thumbnailUri, "r"); if (isCancelled() || fd == null) { return null; } final BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts); if (isCancelled() || opts.outWidth == -1 || opts.outHeight == -1) { return null; } opts.inJustDecodeBounds = false; LogUtils.d(LOG_TAG, "in background, src w/h=%d/%d dst w/h=%d/%d, divider=%d", opts.outWidth, opts.outHeight, mWidth, mHeight, opts.inSampleSize); result = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts); } catch (Throwable t) { LogUtils.e(LOG_TAG, t, "Unable to decode thumbnail %s", thumbnailUri); } finally { if (fd != null) { try { fd.close(); } catch (IOException e) { LogUtils.e(LOG_TAG, e, ""); } } } return result; } @Override protected void onPostExecute(Bitmap result) { if (result == null) { LogUtils.d(LOG_TAG, "back in UI thread, decode failed"); mHolder.setThumbnailToDefault(); return; } LogUtils.d(LOG_TAG, "back in UI thread, decode success, w/h=%d/%d", result.getWidth(), result.getHeight()); mHolder.setThumbnail(result); } }