summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWu-cheng Li <wuchengli@google.com>2011-05-13 15:18:10 +0800
committerWu-cheng Li <wuchengli@google.com>2011-05-17 15:44:34 +0800
commit8ab2b624d51b3b8254ece98c46a7e22a6fb5d4aa (patch)
tree9a62692e59dcfbc8b48e78cfb71e69bfdb7edb4c
parent9e1fcfe35695fd1e71d6c86f28075ca356e5bad5 (diff)
downloadpackages_apps_LegacyCamera-8ab2b624d51b3b8254ece98c46a7e22a6fb5d4aa.zip
packages_apps_LegacyCamera-8ab2b624d51b3b8254ece98c46a7e22a6fb5d4aa.tar.gz
packages_apps_LegacyCamera-8ab2b624d51b3b8254ece98c46a7e22a6fb5d4aa.tar.bz2
Refactor RotateImageView and thumbnail.
Change-Id: Ic435b7cd97ba775ec8f4b8342a1d4d25e2a5120c
-rw-r--r--src/com/android/camera/Camera.java95
-rw-r--r--src/com/android/camera/Storage.java130
-rw-r--r--src/com/android/camera/Thumbnail.java201
-rw-r--r--src/com/android/camera/Util.java39
-rw-r--r--src/com/android/camera/VideoCamera.java87
-rw-r--r--src/com/android/camera/ui/RotateImageView.java (renamed from src/com/android/camera/RotateImageView.java)104
6 files changed, 315 insertions, 341 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index dc399a4..ae522ef 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -26,7 +26,6 @@ import com.android.camera.ui.ZoomControllerListener;
import com.android.camera.ui.ZoomPicker;
import android.app.Activity;
-import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -101,8 +100,7 @@ public class Camera extends ActivityBase implements View.OnClickListener,
private static final String TAG = "camera";
- private static final String LAST_THUMB_PATH =
- Storage.THUMBNAILS + "/image_last_thumb";
+ private static final String LAST_THUMB_FILENAME = "image_last_thumb";
private static final int CROP_MSG = 1;
private static final int FIRST_TIME_INIT = 2;
@@ -172,8 +170,12 @@ public class Camera extends ActivityBase implements View.OnClickListener,
private GLRootView mGLRootView;
- // The last captured picture.
+ // A button showing the last captured picture thumbnail. Clicking on it
+ // goes to gallery.
private RotateImageView mThumbnailButton;
+ // The bitmap of the last captured picture thumbnail and the URI of the
+ // original picture.
+ private Thumbnail mThumbnail;
// mCropValue and mSaveUri are used only if isImageCaptureIntent() is true.
private String mCropValue;
@@ -377,7 +379,7 @@ public class Camera extends ActivityBase implements View.OnClickListener,
// Initialize last picture button.
mContentResolver = getContentResolver();
- if (!mIsImageCaptureIntent) {
+ if (!mIsImageCaptureIntent) { // no thumbnail in image capture intent
findViewById(R.id.camera_switch).setOnClickListener(this);
initThumbnailButton();
}
@@ -423,30 +425,23 @@ public class Camera extends ActivityBase implements View.OnClickListener,
}
private void initThumbnailButton() {
- mThumbnailButton =
- (RotateImageView) findViewById(R.id.review_thumbnail);
- if (mThumbnailButton != null) {
- mThumbnailButton.setOnClickListener(this);
- mThumbnailButton.loadData(LAST_THUMB_PATH);
- updateThumbnailButton();
- }
+ mThumbnailButton.setOnClickListener(this);
+ // Load the thumbnail from the disk.
+ mThumbnail = Thumbnail.loadFrom(LAST_THUMB_FILENAME);
+ updateThumbnailButton();
}
private void updateThumbnailButton() {
- if (mThumbnailButton == null) return;
// Update last image if URI is invalid and the storage is ready.
- if (!mThumbnailButton.isUriValid() && mPicturesRemaining >= 0) {
- Storage.Thumbnail thumbnail =
- Storage.getLastImageThumbnail(mContentResolver);
- if (thumbnail != null) {
- mThumbnailButton.setData(thumbnail.getOriginalUri(),
- thumbnail.getBitmap(mContentResolver));
- } else {
- mThumbnailButton.setData(null, null);
- }
+ if ((mThumbnail == null || !Util.isUriValid(mThumbnail.getUri(), mContentResolver))
+ && mPicturesRemaining >= 0) {
+ mThumbnail = Thumbnail.getLastImageThumbnail(mContentResolver);
+ }
+ if (mThumbnail != null) {
+ mThumbnailButton.setBitmap(mThumbnail.getBitmap());
+ } else {
+ mThumbnailButton.setBitmap(null);
}
- mThumbnailButton.setVisibility(
- (mThumbnailButton.getUri() != null) ? View.VISIBLE : View.GONE);
}
// If the activity is paused and resumed, this method will be called in
@@ -859,17 +854,15 @@ public class Camera extends ActivityBase implements View.OnClickListener,
if (!mIsImageCaptureIntent) {
long dateTaken = System.currentTimeMillis();
String title = createName(dateTaken);
-
- Storage.Thumbnail thumbnail = Storage.addImage(
- mContentResolver, title, dateTaken, loc, data);
-
- if (thumbnail != null && mThumbnailButton != null) {
- mThumbnailButton.setData(thumbnail.getOriginalUri(),
- thumbnail.getBitmap(mContentResolver));
- mThumbnailButton.setVisibility(View.VISIBLE);
-
- sendBroadcast(new Intent("com.android.camera.NEW_PICTURE",
- thumbnail.getOriginalUri()));
+ int orientation = Exif.getOrientation(data);
+ Uri uri = Storage.addImage(mContentResolver, title, dateTaken,
+ loc, orientation, data);
+ if (uri != null) {
+ mThumbnail = Thumbnail.createThumbnail(data, orientation, uri);
+ if (mThumbnail != null) {
+ mThumbnailButton.setBitmap(mThumbnail.getBitmap());
+ }
+ sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", uri));
}
} else {
mJpegImageData = data;
@@ -982,6 +975,7 @@ public class Camera extends ActivityBase implements View.OnClickListener,
}
mSurfaceView = (SurfaceView) findViewById(R.id.camera_preview);
mFocusRectangle = (FocusRectangle) findViewById(R.id.focus_rectangle);
+ mThumbnailButton = (RotateImageView) findViewById(R.id.review_thumbnail);
mPreferences = new ComboPreferences(this);
CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal());
@@ -1272,8 +1266,8 @@ public class Camera extends ActivityBase implements View.OnClickListener,
restartPreview();
break;
case R.id.review_thumbnail:
- if (isCameraIdle()) {
- viewImage(mThumbnailButton);
+ if (isCameraIdle() && mThumbnail != null) {
+ Util.viewUri(mThumbnail.getUri(), this);
}
break;
case R.id.btn_done:
@@ -1506,9 +1500,7 @@ public class Camera extends ActivityBase implements View.OnClickListener,
if (mFirstTimeInitialized) {
mOrientationListener.disable();
if (!mIsImageCaptureIntent) {
- if (mThumbnailButton != null) {
- mThumbnailButton.storeData(LAST_THUMB_PATH);
- }
+ if (mThumbnail != null) mThumbnail.saveTo(LAST_THUMB_FILENAME);
}
hidePostCaptureAlert();
}
@@ -2146,25 +2138,6 @@ public class Camera extends ActivityBase implements View.OnClickListener,
MenuHelper.gotoCameraImageGallery(this);
}
- private void viewImage(RotateImageView view) {
- if(!view.isUriValid()) {
- Log.e(TAG, "Uri invalid. uri=" + view.getUri());
- return;
- }
-
- try {
- startActivity(new Intent(
- Util.REVIEW_ACTION, view.getUri()));
- } catch (ActivityNotFoundException ex) {
- try {
- startActivity(new Intent(
- Intent.ACTION_VIEW, view.getUri()));
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "review image fail. uri=" + view.getUri(), e);
- }
- }
- }
-
private void startReceivingLocationUpdates() {
if (mLocationManager != null) {
try {
@@ -2463,10 +2436,10 @@ public class Camera extends ActivityBase implements View.OnClickListener,
if (mPausing) return;
// Share the last captured picture.
- if (mThumbnailButton.getUri() != null) {
+ if (mThumbnail != null) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/jpeg");
- intent.putExtra(Intent.EXTRA_STREAM, mThumbnailButton.getUri());
+ intent.putExtra(Intent.EXTRA_STREAM, mThumbnail.getUri());
startActivity(Intent.createChooser(intent, getString(R.string.share_picture_via)));
} else { // No last picture
if (mNoShareToast == null) {
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index 23a9282..86fb443 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -17,20 +17,13 @@
package com.android.camera;
import android.content.ContentResolver;
-import android.content.ContentUris;
import android.content.ContentValues;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
import android.location.Location;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.ImageColumns;
-import android.provider.MediaStore.Video;
-import android.provider.MediaStore.Video.VideoColumns;
import android.util.Log;
import java.io.File;
@@ -39,13 +32,11 @@ import java.io.FileOutputStream;
class Storage {
private static final String TAG = "CameraStorage";
- private static final String DCIM =
+ public static final String DCIM =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString();
public static final String DIRECTORY = DCIM + "/Camera";
- public static final String THUMBNAILS = DCIM + "/.thumbnails";
-
// Match the code in MediaProvider.computeBucketValues().
public static final String BUCKET_ID =
String.valueOf(DIRECTORY.toLowerCase().hashCode());
@@ -54,109 +45,10 @@ class Storage {
public static final long PREPARING = -2L;
public static final long UNKNOWN_SIZE = -3L;
- public static class Thumbnail {
- private Uri mBaseUri;
- private long mId;
- private Uri mUri;
- private Bitmap mBitmap;
- private int mOrientation;
-
- private Thumbnail(Uri baseUri, long id, int orientation) {
- mBaseUri = baseUri;
- mId = id;
- mOrientation = orientation;
- }
-
- private Thumbnail(Uri uri, Bitmap bitmap, int orientation) {
- mUri = uri;
- mBitmap = bitmap;
- mOrientation = orientation;
- }
-
- public Uri getOriginalUri() {
- if (mUri == null && mBaseUri != null) {
- mUri = ContentUris.withAppendedId(mBaseUri, mId);
- }
- return mUri;
- }
-
- public Bitmap getBitmap(ContentResolver resolver) {
- if (mBitmap == null) {
- if (Images.Media.EXTERNAL_CONTENT_URI.equals(mBaseUri)) {
- mBitmap = Images.Thumbnails.getThumbnail(resolver, mId,
- Images.Thumbnails.MICRO_KIND, null);
- } else if (Video.Media.EXTERNAL_CONTENT_URI.equals(mBaseUri)) {
- mBitmap = Video.Thumbnails.getThumbnail(resolver, mId,
- Video.Thumbnails.MICRO_KIND, null);
- }
- }
- if (mBitmap != null && mOrientation != 0) {
- // We only rotate the thumbnail once even if we get OOM.
- Matrix m = new Matrix();
- m.setRotate(mOrientation, mBitmap.getWidth() * 0.5f,
- mBitmap.getHeight() * 0.5f);
- mOrientation = 0;
-
- try {
- Bitmap rotated = Bitmap.createBitmap(mBitmap, 0, 0,
- mBitmap.getWidth(), mBitmap.getHeight(), m, true);
- mBitmap.recycle();
- mBitmap = rotated;
- } catch (Throwable t) {
- Log.w(TAG, "Failed to rotate thumbnail", t);
- }
- }
- return mBitmap;
- }
- }
-
- public static Thumbnail getLastImageThumbnail(ContentResolver resolver) {
- Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
-
- Uri query = baseUri.buildUpon().appendQueryParameter("limit", "1").build();
- String[] projection = new String[] {ImageColumns._ID, ImageColumns.ORIENTATION};
- String selection = ImageColumns.MIME_TYPE + "='image/jpeg' AND " +
- ImageColumns.BUCKET_ID + '=' + BUCKET_ID;
- String order = ImageColumns.DATE_TAKEN + " DESC," + ImageColumns._ID + " DESC";
-
- Cursor cursor = null;
- try {
- cursor = resolver.query(query, projection, selection, null, order);
- if (cursor != null && cursor.moveToFirst()) {
- return new Thumbnail(baseUri, cursor.getLong(0), cursor.getInt(1));
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return null;
- }
-
- public static Thumbnail getLastVideoThumbnail(ContentResolver resolver) {
- Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
+ private static final int BUFSIZE = 4096;
- Uri query = baseUri.buildUpon().appendQueryParameter("limit", "1").build();
- String[] projection = new String[] {VideoColumns._ID};
- String selection = VideoColumns.BUCKET_ID + '=' + BUCKET_ID;
- String order = VideoColumns.DATE_TAKEN + " DESC," + VideoColumns._ID + " DESC";
-
- Cursor cursor = null;
- try {
- cursor = resolver.query(query, projection, selection, null, order);
- if (cursor != null && cursor.moveToFirst()) {
- return new Thumbnail(baseUri, cursor.getLong(0), 0);
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return null;
- }
-
- public static Thumbnail addImage(ContentResolver resolver, String title,
- long date, Location location, byte[] jpeg) {
+ public static Uri addImage(ContentResolver resolver, String title,
+ long date, Location location, int orientation, byte[] jpeg) {
// Save the image.
String path = DIRECTORY + '/' + title + ".jpg";
FileOutputStream out = null;
@@ -173,9 +65,6 @@ class Storage {
}
}
- // Get the orientation.
- int orientation = Exif.getOrientation(jpeg);
-
// Insert into MediaStore.
ContentValues values = new ContentValues(9);
values.put(ImageColumns.TITLE, title);
@@ -196,16 +85,7 @@ class Storage {
Log.e(TAG, "Failed to write MediaStore");
return null;
}
-
- // Create the thumbnail.
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = 16;
- Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);
- if (bitmap == null) {
- Log.e(TAG, "Failed to create thumbnail");
- return null;
- }
- return new Thumbnail(uri, bitmap, orientation);
+ return uri;
}
public static long getAvailableSpace() {
diff --git a/src/com/android/camera/Thumbnail.java b/src/com/android/camera/Thumbnail.java
new file mode 100644
index 0000000..cc9290c
--- /dev/null
+++ b/src/com/android/camera/Thumbnail.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2011 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.camera;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.net.Uri;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Images.ImageColumns;
+import android.provider.MediaStore.Video;
+import android.provider.MediaStore.Video.VideoColumns;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+class Thumbnail {
+ private static final String TAG = "Thumbnail";
+
+ private static final String DIRECTORY = Storage.DCIM + "/.thumbnails/";
+ private static final int BUFSIZE = 4096;
+
+ private Uri mUri;
+ private Bitmap mBitmap;
+
+ public Thumbnail(Uri uri, Bitmap bitmap, int orientation) {
+ mUri = uri;
+ mBitmap = rotateImage(bitmap, orientation);
+ }
+
+ public Uri getUri() {
+ return mUri;
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ private static Bitmap rotateImage(Bitmap bitmap, int orientation) {
+ if (orientation != 0) {
+ // We only rotate the thumbnail once even if we get OOM.
+ Matrix m = new Matrix();
+ m.setRotate(orientation, bitmap.getWidth() * 0.5f,
+ bitmap.getHeight() * 0.5f);
+
+ try {
+ Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), m, true);
+ bitmap.recycle();
+ return rotated;
+ } catch (Throwable t) {
+ Log.w(TAG, "Failed to rotate thumbnail", t);
+ }
+ }
+ return bitmap;
+ }
+
+ // Stores the bitmap to the specified file.
+ public void saveTo(String filename) {
+ String path = DIRECTORY + filename;
+ FileOutputStream f = null;
+ BufferedOutputStream b = null;
+ DataOutputStream d = null;
+ try {
+ f = new FileOutputStream(path);
+ b = new BufferedOutputStream(f, BUFSIZE);
+ d = new DataOutputStream(b);
+ d.writeUTF(mUri.toString());
+ mBitmap.compress(Bitmap.CompressFormat.PNG, 100, d);
+ d.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Fail to store bitmap. path=" + path, e);
+ } finally {
+ Util.closeSilently(f);
+ Util.closeSilently(b);
+ Util.closeSilently(d);
+ }
+ }
+
+
+ // Loads the data from the specified file.
+ // Returns null if failure.
+ public static Thumbnail loadFrom(String filename) {
+ Uri uri = null;
+ Bitmap bitmap = null;
+ FileInputStream f = null;
+ BufferedInputStream b = null;
+ DataInputStream d = null;
+ try {
+ f = new FileInputStream(DIRECTORY + filename);
+ b = new BufferedInputStream(f, BUFSIZE);
+ d = new DataInputStream(b);
+ uri = Uri.parse(d.readUTF());
+ bitmap = BitmapFactory.decodeStream(d);
+ d.close();
+ } catch (IOException e) {
+ Log.i(TAG, "Fail to load bitmap. " + e);
+ return null;
+ } finally {
+ Util.closeSilently(f);
+ Util.closeSilently(b);
+ Util.closeSilently(d);
+ }
+ return new Thumbnail(uri, bitmap, 0);
+ }
+
+ public static Thumbnail getLastImageThumbnail(ContentResolver resolver) {
+ Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI;
+
+ Uri query = baseUri.buildUpon().appendQueryParameter("limit", "1").build();
+ String[] projection = new String[] {ImageColumns._ID, ImageColumns.ORIENTATION};
+ String selection = ImageColumns.MIME_TYPE + "='image/jpeg' AND " +
+ ImageColumns.BUCKET_ID + '=' + Storage.BUCKET_ID;
+ String order = ImageColumns.DATE_TAKEN + " DESC," + ImageColumns._ID + " DESC";
+
+ Cursor cursor = null;
+ try {
+ cursor = resolver.query(query, projection, selection, null, order);
+ if (cursor != null && cursor.moveToFirst()) {
+ long id = cursor.getLong(0);
+ int orientation = cursor.getInt(1);
+ Bitmap bitmap = Images.Thumbnails.getThumbnail(resolver, id,
+ Images.Thumbnails.MICRO_KIND, null);
+ Uri uri = ContentUris.withAppendedId(baseUri, id);
+ // Ensure there's no OOM. Ensure database and storage are in sync.
+ if (bitmap != null && Util.isUriValid(uri, resolver)) {
+ return new Thumbnail(uri, bitmap, orientation);
+ }
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return null;
+ }
+
+ public static Thumbnail getLastVideoThumbnail(ContentResolver resolver) {
+ Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
+
+ Uri query = baseUri.buildUpon().appendQueryParameter("limit", "1").build();
+ String[] projection = new String[] {VideoColumns._ID};
+ String selection = VideoColumns.BUCKET_ID + '=' + Storage.BUCKET_ID;
+ String order = VideoColumns.DATE_TAKEN + " DESC," + VideoColumns._ID + " DESC";
+
+ Cursor cursor = null;
+ try {
+ cursor = resolver.query(query, projection, selection, null, order);
+ if (cursor != null && cursor.moveToFirst()) {
+ long id = cursor.getLong(0);
+ Bitmap bitmap = Video.Thumbnails.getThumbnail(resolver, id,
+ Video.Thumbnails.MICRO_KIND, null);
+ Uri uri = ContentUris.withAppendedId(baseUri, id);
+ // Ensure there's no OOM. Ensure database and storage are in sync.
+ if (bitmap != null && Util.isUriValid(uri, resolver)) {
+ return new Thumbnail(uri, bitmap, 0);
+ }
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return null;
+ }
+
+ public static Thumbnail createThumbnail(byte[] jpeg, int orientation, Uri uri) {
+ // Create the thumbnail.
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = 16;
+ Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);
+ if (bitmap == null) {
+ Log.e(TAG, "Failed to create thumbnail");
+ return null;
+ }
+ return new Thumbnail(uri, bitmap, orientation);
+ }
+}
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index 5d4f9b0..bf33dc9 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -18,14 +18,19 @@ package com.android.camera;
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
import android.content.Context;
+import android.content.ContentResolver;
import android.content.DialogInterface;
+import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Display;
@@ -35,6 +40,7 @@ import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import java.io.Closeable;
+import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.StringTokenizer;
@@ -399,4 +405,37 @@ public class Util {
return x >= mLocation[0] && x < (mLocation[0] + v.getWidth())
&& y >= mLocation[1] && y < (mLocation[1] + v.getHeight());
}
+
+ public static boolean isUriValid(Uri uri, ContentResolver resolver) {
+ if (uri == null) return false;
+
+ try {
+ ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r");
+ if (pfd == null) {
+ Log.e(TAG, "Fail to open URI. URI=" + uri);
+ return false;
+ }
+ pfd.close();
+ } catch (IOException ex) {
+ return false;
+ }
+ return true;
+ }
+
+ public static void viewUri(Uri uri, Context context) {
+ if (!isUriValid(uri, context.getContentResolver())) {
+ Log.e(TAG, "Uri invalid. uri=" + uri);
+ return;
+ }
+
+ try {
+ context.startActivity(new Intent(Util.REVIEW_ACTION, uri));
+ } catch (ActivityNotFoundException ex) {
+ try {
+ context.startActivity(new Intent(Intent.ACTION_VIEW, uri));
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "review image fail. uri=" + uri, e);
+ }
+ }
+ }
}
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 27d7aa6..bf8f864 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -89,8 +89,7 @@ public class VideoCamera extends ActivityBase
private static final String TAG = "videocamera";
- private static final String LAST_THUMB_PATH =
- Storage.THUMBNAILS + "/video_last_thumb";
+ private static final String LAST_THUMB_FILENAME = "video_last_thumb";
private static final int CHECK_DISPLAY_ROTATION = 3;
private static final int CLEAR_SCREEN_DELAY = 4;
@@ -151,8 +150,12 @@ public class VideoCamera extends ActivityBase
private View mReviewControl;
private Toast mNoShareToast;
- // The last recorded video.
+ // A button showing the last captured video thumbnail. Clicking on it
+ // goes to gallery.
private RotateImageView mThumbnailButton;
+ // The bitmap of the last captured video thumbnail and the URI of the
+ // original video.
+ private Thumbnail mThumbnail;
private ShutterButton mShutterButton;
private TextView mRecordingTimeView;
private SwitcherSet mSwitcher;
@@ -597,7 +600,7 @@ public class VideoCamera extends ActivityBase
Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
try {
startActivity(intent);
- } catch (android.content.ActivityNotFoundException ex) {
+ } catch (ActivityNotFoundException ex) {
Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
}
}
@@ -619,7 +622,9 @@ public class VideoCamera extends ActivityBase
doReturnToCaller(false);
break;
case R.id.review_thumbnail:
- if (!mMediaRecorderRecording) viewVideo(mThumbnailButton);
+ if (!mMediaRecorderRecording && mThumbnail != null) {
+ Util.viewUri(mThumbnail.getUri(), this);
+ }
break;
case R.id.btn_gallery:
gotoGallery();
@@ -959,8 +964,8 @@ public class VideoCamera extends ActivityBase
}
resetScreenOn();
- if (!mIsVideoCaptureIntent && mThumbnailButton != null) {
- mThumbnailButton.storeData(LAST_THUMB_PATH);
+ if (!mIsVideoCaptureIntent && mThumbnail != null) {
+ mThumbnail.saveTo(LAST_THUMB_FILENAME);
}
if (mStorageHint != null) {
@@ -1462,7 +1467,12 @@ public class VideoCamera extends ActivityBase
}
private void getThumbnail() {
- acquireVideoThumb();
+ Bitmap videoFrame = ThumbnailUtils.createVideoThumbnail(
+ mCurrentVideoFilename, Video.Thumbnails.MINI_KIND);
+ if (videoFrame != null) {
+ mThumbnail = new Thumbnail(mCurrentVideoUri, videoFrame, 0);
+ mThumbnailButton.setBitmap(mThumbnail.getBitmap());
+ }
}
private void showAlert() {
@@ -1535,24 +1545,6 @@ public class VideoCamera extends ActivityBase
return this.mVideoFrame.getVisibility() == View.VISIBLE;
}
- private void viewVideo(RotateImageView view) {
- if(view.isUriValid()) {
- Intent intent = new Intent(Util.REVIEW_ACTION, view.getUri());
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException ex) {
- try {
- intent = new Intent(Intent.ACTION_VIEW, view.getUri());
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "review video fail. uri=" + view.getUri(), e);
- }
- }
- } else {
- Log.e(TAG, "Uri invalid. uri=" + view.getUri());
- }
- }
-
private void stopVideoRecording() {
Log.v(TAG, "stopVideoRecording");
if (mMediaRecorderRecording) {
@@ -1598,39 +1590,22 @@ public class VideoCamera extends ActivityBase
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
- private void acquireVideoThumb() {
- if (mThumbnailButton != null) {
- Bitmap videoFrame = ThumbnailUtils.createVideoThumbnail(
- mCurrentVideoFilename, Video.Thumbnails.MINI_KIND);
- mThumbnailButton.setData(mCurrentVideoUri, videoFrame);
- if (videoFrame != null) {
- mThumbnailButton.setVisibility(View.VISIBLE);
- }
- }
- }
-
private void initThumbnailButton() {
- mThumbnailButton = (RotateImageView)findViewById(R.id.review_thumbnail);
- if (mThumbnailButton != null) {
- mThumbnailButton.setOnClickListener(this);
- mThumbnailButton.loadData(LAST_THUMB_PATH);
- }
+ mThumbnailButton = (RotateImageView) findViewById(R.id.review_thumbnail);
+ mThumbnailButton.setOnClickListener(this);
+ // Load the thumbnail from the disk.
+ mThumbnail = Thumbnail.loadFrom(LAST_THUMB_FILENAME);
}
private void updateThumbnailButton() {
- if (mThumbnailButton == null) return;
- if (!mThumbnailButton.isUriValid()) {
- Storage.Thumbnail thumbnail =
- Storage.getLastVideoThumbnail(mContentResolver);
- if (thumbnail != null) {
- mThumbnailButton.setData(thumbnail.getOriginalUri(),
- thumbnail.getBitmap(mContentResolver));
- } else {
- mThumbnailButton.setData(null, null);
- }
+ if (mThumbnail == null || !Util.isUriValid(mThumbnail.getUri(), mContentResolver)) {
+ mThumbnail = Thumbnail.getLastVideoThumbnail(mContentResolver);
+ }
+ if (mThumbnail != null) {
+ mThumbnailButton.setBitmap(mThumbnail.getBitmap());
+ } else {
+ mThumbnailButton.setBitmap(null);
}
- mThumbnailButton.setVisibility(
- (mThumbnailButton.getUri() != null) ? View.VISIBLE : View.GONE);
}
private static String millisecondToTimeString(long milliSeconds, boolean displayCentiSeconds) {
@@ -1918,10 +1893,10 @@ public class VideoCamera extends ActivityBase
if (mPausing) return;
// Share the last captured video.
- if (mThumbnailButton.getUri() != null) {
+ if (mThumbnail != null) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("video/*");
- intent.putExtra(Intent.EXTRA_STREAM, mThumbnailButton.getUri());
+ intent.putExtra(Intent.EXTRA_STREAM, mThumbnail.getUri());
startActivity(Intent.createChooser(intent, getString(R.string.share_video_via)));
} else { // No last picture
if (mNoShareToast == null) {
diff --git a/src/com/android/camera/RotateImageView.java b/src/com/android/camera/ui/RotateImageView.java
index 531169b..8348bf2 100644
--- a/src/com/android/camera/RotateImageView.java
+++ b/src/com/android/camera/ui/RotateImageView.java
@@ -25,22 +25,12 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.Rect;
import android.media.ThumbnailUtils;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
import android.util.AttributeSet;
import android.util.Log;
import android.view.animation.AnimationUtils;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
/**
* A @{code ImageView} which can rotate it's content.
*/
@@ -60,8 +50,6 @@ public class RotateImageView extends ImageView {
private long mAnimationStartTime = 0;
private long mAnimationEndTime = 0;
- private Uri mUri;
-
public RotateImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -137,79 +125,14 @@ public class RotateImageView extends ImageView {
private Drawable[] mThumbs;
private TransitionDrawable mThumbTransition;
- public void setData(Uri uri, Bitmap original) {
+ public void setBitmap(Bitmap bitmap) {
// Make sure uri and original are consistently both null or both
// non-null.
- if (uri == null || original == null) {
- uri = null;
- original = null;
- }
- mUri = uri;
- updateThumb(original);
- }
-
- public Uri getUri() {
- return mUri;
- }
-
- private static final int BUFSIZE = 4096;
-
- // Stores the data from the specified file.
- // Returns true for success.
- public boolean storeData(String filePath) {
- if (mUri == null) {
- return false;
- }
-
- FileOutputStream f = null;
- BufferedOutputStream b = null;
- DataOutputStream d = null;
- try {
- f = new FileOutputStream(filePath);
- b = new BufferedOutputStream(f, BUFSIZE);
- d = new DataOutputStream(b);
- d.writeUTF(mUri.toString());
- mThumb.compress(Bitmap.CompressFormat.PNG, 100, d);
- d.close();
- } catch (IOException e) {
- return false;
- } finally {
- Util.closeSilently(f);
- Util.closeSilently(b);
- Util.closeSilently(d);
- }
- return true;
- }
-
- // Loads the data from the specified file.
- // Returns true for success.
- public boolean loadData(String filePath) {
- FileInputStream f = null;
- BufferedInputStream b = null;
- DataInputStream d = null;
- try {
- f = new FileInputStream(filePath);
- b = new BufferedInputStream(f, BUFSIZE);
- d = new DataInputStream(b);
- Uri uri = Uri.parse(d.readUTF());
- Bitmap thumb = BitmapFactory.decodeStream(d);
- setData(uri, thumb);
- d.close();
- } catch (IOException e) {
- return false;
- } finally {
- Util.closeSilently(f);
- Util.closeSilently(b);
- Util.closeSilently(d);
- }
- return true;
- }
-
- private void updateThumb(Bitmap original) {
- if (original == null) {
+ if (bitmap == null) {
mThumb = null;
mThumbs = null;
setImageDrawable(null);
+ setVisibility(GONE);
return;
}
@@ -219,7 +142,7 @@ public class RotateImageView extends ImageView {
final int miniThumbHeight = param.height
- getPaddingTop() - getPaddingBottom();
mThumb = ThumbnailUtils.extractThumbnail(
- original, miniThumbWidth, miniThumbHeight);
+ bitmap, miniThumbWidth, miniThumbHeight);
Drawable drawable;
if (mThumbs == null || !mEnableAnimation) {
mThumbs = new Drawable[2];
@@ -232,23 +155,6 @@ public class RotateImageView extends ImageView {
setImageDrawable(mThumbTransition);
mThumbTransition.startTransition(500);
}
- }
-
- public boolean isUriValid() {
- if (mUri == null) {
- return false;
- }
- try {
- ParcelFileDescriptor pfd =
- getContext().getContentResolver().openFileDescriptor(mUri, "r");
- if (pfd == null) {
- Log.e(TAG, "Fail to open URI. URI=" + mUri);
- return false;
- }
- pfd.close();
- } catch (IOException ex) {
- return false;
- }
- return true;
+ setVisibility(VISIBLE);
}
}