diff options
author | Adam Copp <adamcopp@google.com> | 2012-08-22 03:22:45 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-08-22 03:22:45 -0700 |
commit | 34e9a4486aeeaa104f534629a0bea2fccd2bc88a (patch) | |
tree | 3935d5c0939a5635c00996c1a07b14602d503516 /photoviewer | |
parent | 5f53c9840779cbe038c2aea348a3b0ff0c6817f5 (diff) | |
parent | d7ae9863e34c878985d35133c3b56bee481ec4b1 (diff) | |
download | android_frameworks_ex-34e9a4486aeeaa104f534629a0bea2fccd2bc88a.tar.gz android_frameworks_ex-34e9a4486aeeaa104f534629a0bea2fccd2bc88a.tar.bz2 android_frameworks_ex-34e9a4486aeeaa104f534629a0bea2fccd2bc88a.zip |
Merge "Add HTTP uri handling & fetch thumbnail first"
Diffstat (limited to 'photoviewer')
4 files changed, 214 insertions, 175 deletions
diff --git a/photoviewer/.gitignore b/photoviewer/.gitignore new file mode 100644 index 0000000..ff7ef7d --- /dev/null +++ b/photoviewer/.gitignore @@ -0,0 +1,8 @@ +*~ +*.bak +*.class +bin/ +gen/ +*.properties +.classpath +.project diff --git a/photoviewer/src/com/android/ex/photo/PhotoViewActivity.java b/photoviewer/src/com/android/ex/photo/PhotoViewActivity.java index 2e54569..c15bc1a 100644 --- a/photoviewer/src/com/android/ex/photo/PhotoViewActivity.java +++ b/photoviewer/src/com/android/ex/photo/PhotoViewActivity.java @@ -31,6 +31,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.view.MenuItem; import android.view.View; import com.android.ex.photo.PhotoViewPager.InterceptType; @@ -237,6 +238,16 @@ public class PhotoViewActivity extends Activity implements outState.putBoolean(STATE_FULLSCREEN_KEY, mFullScreen); } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + default: + return super.onOptionsItemSelected(item); + } + } + public void addScreenListener(OnScreenListener listener) { mScreenListeners.add(listener); } diff --git a/photoviewer/src/com/android/ex/photo/fragments/PhotoViewFragment.java b/photoviewer/src/com/android/ex/photo/fragments/PhotoViewFragment.java index 97ea3b8..4da6ab0 100644 --- a/photoviewer/src/com/android/ex/photo/fragments/PhotoViewFragment.java +++ b/photoviewer/src/com/android/ex/photo/fragments/PhotoViewFragment.java @@ -204,7 +204,7 @@ public class PhotoViewFragment extends Fragment implements mCallback.addScreenListener(this); mCallback.addCursorListener(this); - getLoaderManager().initLoader(LOADER_ID_PHOTO, null, this); + getLoaderManager().initLoader(LOADER_ID_THUMBNAIL, null, this); super.onResume(); } @@ -284,10 +284,8 @@ public class PhotoViewFragment extends Fragment implements mProgressBarNeeded = false; } else { - mPhotoPreviewImage.setVisibility(View.VISIBLE); - mPhotoPreviewImage.setImageBitmap(data); - - mProgressBarNeeded = false; + bindPhoto(data); + getLoaderManager().initLoader(LOADER_ID_PHOTO, null, this); } break; default: diff --git a/photoviewer/src/com/android/ex/photo/util/ImageUtils.java b/photoviewer/src/com/android/ex/photo/util/ImageUtils.java index 8564457..501356e 100644 --- a/photoviewer/src/com/android/ex/photo/util/ImageUtils.java +++ b/photoviewer/src/com/android/ex/photo/util/ImageUtils.java @@ -1,175 +1,197 @@ -/*
- * Copyright (C) 2011 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.ex.photo.util;
-
-import android.content.ContentResolver;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Build;
-import android.util.Log;
-
-import com.android.ex.photo.PhotoViewActivity;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Image utilities
- */
-public class ImageUtils {
- // Logging
- private static final String TAG = "ImageUtils";
-
- /** Minimum class memory class to use full-res photos */
- private final static long MIN_NORMAL_CLASS = 32;
- /** Minimum class memory class to use small photos */
- private final static long MIN_SMALL_CLASS = 24;
-
- public static enum ImageSize {
- EXTRA_SMALL,
- SMALL,
- NORMAL,
- }
-
- public static final ImageSize sUseImageSize;
- static {
- // On HC and beyond, assume devices are more capable
- if (Build.VERSION.SDK_INT >= 11) {
- sUseImageSize = ImageSize.NORMAL;
- } else {
- if (PhotoViewActivity.sMemoryClass >= MIN_NORMAL_CLASS) {
- // We have plenty of memory; use full sized photos
- sUseImageSize = ImageSize.NORMAL;
- } else if (PhotoViewActivity.sMemoryClass >= MIN_SMALL_CLASS) {
- // We have slight less memory; use smaller sized photos
- sUseImageSize = ImageSize.SMALL;
- } else {
- // We have little memory; use very small sized photos
- sUseImageSize = ImageSize.EXTRA_SMALL;
- }
- }
- }
-
- /**
- * @return true if the MimeType type is image
- */
- public static boolean isImageMimeType(String mimeType) {
- return mimeType != null && mimeType.startsWith("image/");
- }
-
- /**
- * Create a bitmap from a local URI
- *
- * @param resolver The ContentResolver
- * @param uri The local URI
- * @param maxSize The maximum size (either width or height)
- *
- * @return The new bitmap
- */
- public static Bitmap createLocalBitmap(ContentResolver resolver, Uri uri, int maxSize) {
- InputStream inputStream = null;
- try {
- final BitmapFactory.Options opts = new BitmapFactory.Options();
- final Point bounds = getImageBounds(resolver, uri);
-
- inputStream = resolver.openInputStream(uri);
- opts.inSampleSize = Math.max(bounds.x / maxSize, bounds.y / maxSize);
-
- final Bitmap decodedBitmap = decodeStream(inputStream, null, opts);
-
- // Correct thumbnail orientation as necessary
+/* + * Copyright (C) 2011 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.ex.photo.util; + +import android.content.ContentResolver; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Point; +import android.graphics.Rect; +import android.net.Uri; +import android.os.Build; +import android.util.Log; + +import com.android.ex.photo.PhotoViewActivity; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; + +/** + * Image utilities + */ +public class ImageUtils { + // Logging + private static final String TAG = "ImageUtils"; + + /** Minimum class memory class to use full-res photos */ + private final static long MIN_NORMAL_CLASS = 32; + /** Minimum class memory class to use small photos */ + private final static long MIN_SMALL_CLASS = 24; + + public static enum ImageSize { + EXTRA_SMALL, + SMALL, + NORMAL, + } + + public static final ImageSize sUseImageSize; + static { + // On HC and beyond, assume devices are more capable + if (Build.VERSION.SDK_INT >= 11) { + sUseImageSize = ImageSize.NORMAL; + } else { + if (PhotoViewActivity.sMemoryClass >= MIN_NORMAL_CLASS) { + // We have plenty of memory; use full sized photos + sUseImageSize = ImageSize.NORMAL; + } else if (PhotoViewActivity.sMemoryClass >= MIN_SMALL_CLASS) { + // We have slight less memory; use smaller sized photos + sUseImageSize = ImageSize.SMALL; + } else { + // We have little memory; use very small sized photos + sUseImageSize = ImageSize.EXTRA_SMALL; + } + } + } + + /** + * @return true if the MimeType type is image + */ + public static boolean isImageMimeType(String mimeType) { + return mimeType != null && mimeType.startsWith("image/"); + } + + /** + * Create a bitmap from a local URI + * + * @param resolver The ContentResolver + * @param uri The local URI + * @param maxSize The maximum size (either width or height) + * + * @return The new bitmap + */ + public static Bitmap createLocalBitmap(ContentResolver resolver, Uri uri, int maxSize) { + // TODO: make this method not download the image for both getImageBounds and decodeStream + InputStream inputStream = null; + try { + final BitmapFactory.Options opts = new BitmapFactory.Options(); + final Point bounds = getImageBounds(resolver, uri); + + inputStream = openInputStream(resolver, uri); + opts.inSampleSize = Math.max(bounds.x / maxSize, bounds.y / maxSize); + + final Bitmap decodedBitmap = decodeStream(inputStream, null, opts); + + // Correct thumbnail orientation as necessary // TODO: Fix rotation if it's actually a problem //return rotateBitmap(resolver, uri, decodedBitmap); return decodedBitmap; -
- } catch (FileNotFoundException exception) {
- // Do nothing - the photo will appear to be missing
- } catch (IOException exception) {
- // Do nothing - the photo will appear to be missing
+ + } catch (FileNotFoundException exception) { + // Do nothing - the photo will appear to be missing + } catch (IOException exception) { + // Do nothing - the photo will appear to be missing } catch (IllegalArgumentException exception) { // Do nothing - the photo will appear to be missing - } finally {
- try {
- if (inputStream != null) {
- inputStream.close();
- }
- } catch (IOException ignore) {
- }
- }
- return null;
- }
-
- /**
- * Wrapper around {@link BitmapFactory#decodeStream(InputStream, Rect,
- * BitmapFactory.Options)} that returns {@code null} on {@link
- * OutOfMemoryError}.
- *
- * @param is The input stream that holds the raw data to be decoded into a
- * bitmap.
- * @param outPadding If not null, return the padding rect for the bitmap if
- * it exists, otherwise set padding to [-1,-1,-1,-1]. If
- * no bitmap is returned (null) then padding is
- * unchanged.
- * @param opts null-ok; Options that control downsampling and whether the
- * image should be completely decoded, or just is size returned.
- * @return The decoded bitmap, or null if the image data could not be
- * decoded, or, if opts is non-null, if opts requested only the
- * size be returned (in opts.outWidth and opts.outHeight)
- */
- public static Bitmap decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts) {
- try {
- return BitmapFactory.decodeStream(is, outPadding, opts);
- } catch (OutOfMemoryError oome) {
- Log.e(TAG, "ImageUtils#decodeStream(InputStream, Rect, Options) threw an OOME", oome);
- return null;
- }
- }
-
- /**
- * Gets the image bounds
- *
- * @param resolver The ContentResolver
- * @param uri The uri
- *
- * @return The image bounds
- */
- private static Point getImageBounds(ContentResolver resolver, Uri uri)
- throws IOException {
- final BitmapFactory.Options opts = new BitmapFactory.Options();
- InputStream inputStream = null;
-
- try {
- opts.inJustDecodeBounds = true;
- inputStream = resolver.openInputStream(uri);
- decodeStream(inputStream, null, opts);
-
- return new Point(opts.outWidth, opts.outHeight);
- } finally {
- try {
- if (inputStream != null) {
- inputStream.close();
- }
- } catch (IOException ignore) {
- }
- }
- }
-}
+ } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException ignore) { + } + } + return null; + } + + /** + * Wrapper around {@link BitmapFactory#decodeStream(InputStream, Rect, + * BitmapFactory.Options)} that returns {@code null} on {@link + * OutOfMemoryError}. + * + * @param is The input stream that holds the raw data to be decoded into a + * bitmap. + * @param outPadding If not null, return the padding rect for the bitmap if + * it exists, otherwise set padding to [-1,-1,-1,-1]. If + * no bitmap is returned (null) then padding is + * unchanged. + * @param opts null-ok; Options that control downsampling and whether the + * image should be completely decoded, or just is size returned. + * @return The decoded bitmap, or null if the image data could not be + * decoded, or, if opts is non-null, if opts requested only the + * size be returned (in opts.outWidth and opts.outHeight) + */ + public static Bitmap decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts) { + try { + return BitmapFactory.decodeStream(is, outPadding, opts); + } catch (OutOfMemoryError oome) { + Log.e(TAG, "ImageUtils#decodeStream(InputStream, Rect, Options) threw an OOME", oome); + return null; + } + } + + /** + * Gets the image bounds + * + * @param resolver The ContentResolver + * @param uri The uri + * + * @return The image bounds + */ + private static Point getImageBounds(ContentResolver resolver, Uri uri) + throws IOException { + final BitmapFactory.Options opts = new BitmapFactory.Options(); + InputStream inputStream = null; + String scheme = uri.getScheme(); + try { + opts.inJustDecodeBounds = true; + inputStream = openInputStream(resolver, uri); + decodeStream(inputStream, null, opts); + + return new Point(opts.outWidth, opts.outHeight); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException ignore) { + } + } + } + + private static InputStream openInputStream(ContentResolver resolver, Uri uri) throws + FileNotFoundException { + String scheme = uri.getScheme(); + if("http".equals(scheme) || "https".equals(scheme)) { + try { + return new URL(uri.toString()).openStream(); + } catch (MalformedURLException e) { + // Fall-back to the previous behaviour, just in case + Log.w(TAG, "Could not convert the uri to url: " + uri.toString()); + return resolver.openInputStream(uri); + } catch (IOException e) { + Log.w(TAG, "Could not open input stream for uri: " + uri.toString()); + return null; + } + } + return resolver.openInputStream(uri); + } +} |