summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/camera')
-rw-r--r--src/com/android/camera/Camera.java538
-rw-r--r--src/com/android/camera/CropImage.java1
-rw-r--r--src/com/android/camera/GalleryPicker.java148
-rw-r--r--src/com/android/camera/ImageGallery2.java34
-rwxr-xr-xsrc/com/android/camera/ImageManager.java128
-rw-r--r--src/com/android/camera/MenuHelper.java75
-rw-r--r--src/com/android/camera/MovieView.java34
-rw-r--r--src/com/android/camera/SlideShow.java2
-rw-r--r--src/com/android/camera/VideoCamera.java283
-rw-r--r--src/com/android/camera/ViewImage.java174
10 files changed, 880 insertions, 537 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 11b1ccd..a6775ae 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -34,6 +34,7 @@ import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
+import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
@@ -41,6 +42,7 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.TransitionDrawable;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.location.Location;
@@ -73,6 +75,7 @@ import android.view.Window;
import android.view.WindowManager;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.ViewGroup.LayoutParams;
+import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
@@ -86,6 +89,8 @@ public class Camera extends Activity implements View.OnClickListener,
private static final String TAG = "camera";
private static final boolean DEBUG = false;
+ private static final boolean DEBUG_TIME_OPERATIONS = DEBUG && false;
+ private static final boolean DEBUG_FAKE_GPS_LOCATION = DEBUG && false;
private static final int CROP_MSG = 1;
private static final int KEEP = 2;
@@ -124,6 +129,7 @@ public class Camera extends Activity implements View.OnClickListener,
private static final String sTempCropFilename = "crop-temp";
private android.hardware.Camera mCameraDevice;
+ private android.hardware.Camera.Parameters mParameters;
private VideoPreview mSurfaceView;
private SurfaceHolder mSurfaceHolder = null;
private ImageView mBlackout = null;
@@ -152,6 +158,12 @@ public class Camera extends Activity implements View.OnClickListener,
private boolean mMenuSelectionMade;
private ImageView mLastPictureButton;
+ private LayerDrawable mVignette;
+ private Animation mShowLastPictureButtonAnimation = new AlphaAnimation(0F, 1F);
+ private boolean mShouldShowLastPictureButton;
+ private TransitionDrawable mThumbnailTransition;
+ private Drawable[] mThumbnails;
+ private boolean mShouldTransitionThumbnails;
private Uri mLastPictureUri;
private LocationManager mLocationManager = null;
@@ -170,6 +182,9 @@ public class Camera extends Activity implements View.OnClickListener,
private boolean mKeepAndRestartPreview;
+ private View mPostCaptureAlert;
+
+
private Handler mHandler = new MainHandler();
private ProgressDialog mSavingProgress;
@@ -217,6 +232,7 @@ public class Camera extends Activity implements View.OnClickListener,
mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, 100);
} else if (mStatus == SNAPSHOT_COMPLETED){
mCaptureObject.dismissFreezeFrame(true);
+ hidePostCaptureAlert();
}
break;
}
@@ -244,9 +260,11 @@ public class Camera extends Activity implements View.OnClickListener,
// TODO put up a "please wait" message
// TODO also listen for the media scanner finished message
showStorageToast();
- } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
+ } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) ||
+ action.equals(Intent.ACTION_MEDIA_CHECKING)) {
// SD card unavailable
- showStorageToast();
+ mPicturesRemaining = MenuHelper.NO_STORAGE_ERROR;
+ showStorageToast(mPicturesRemaining);
} else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
Toast.makeText(Camera.this, getResources().getString(R.string.wait), 5000);
} else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
@@ -298,7 +316,7 @@ public class Camera extends Activity implements View.OnClickListener,
private final class ShutterCallback implements android.hardware.Camera.ShutterCallback {
public void onShutter() {
- if (DEBUG) {
+ if (DEBUG_TIME_OPERATIONS) {
long now = System.currentTimeMillis();
Log.v(TAG, "********** Total shutter lag " + (now - mShutterPressTime) + " ms");
}
@@ -314,7 +332,7 @@ public class Camera extends Activity implements View.OnClickListener,
if (Config.LOGV)
Log.v(TAG, "got RawPictureCallback...");
mRawPictureCallbackTime = System.currentTimeMillis();
- mBlackout.setVisibility(View.INVISIBLE);
+ mBlackout.setVisibility(View.GONE);
}
};
@@ -428,7 +446,7 @@ public class Camera extends Activity implements View.OnClickListener,
private void storeImage(byte[] data, Location loc) {
try {
- if (DEBUG) {
+ if (DEBUG_TIME_OPERATIONS) {
startTiming();
}
long dateTaken = System.currentTimeMillis();
@@ -455,7 +473,7 @@ public class Camera extends Activity implements View.OnClickListener,
mAddImageCancelable = null;
}
- if (DEBUG) {
+ if (DEBUG_TIME_OPERATIONS) {
stopTiming();
Log.d(TAG, "Storing image took " + (mWallTimeEnd - mWallTimeStart) + " ms. " +
"Thread time was " + ((mThreadTimeEnd - mThreadTimeStart) / 1000000) +
@@ -472,19 +490,19 @@ public class Camera extends Activity implements View.OnClickListener,
if (!captureOnly) {
storeImage(data, loc);
sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", mLastContentUri));
- setLastPictureThumb(data);
+ setLastPictureThumb(data, mCaptureObject.getLastCaptureUri());
dismissFreezeFrame(true);
} else {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
- if (DEBUG) {
+ if (DEBUG_TIME_OPERATIONS) {
startTiming();
}
mCaptureOnlyBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
- if (DEBUG) {
+ if (DEBUG_TIME_OPERATIONS) {
stopTiming();
Log.d(TAG, "Decoded mCaptureOnly bitmap (" + mCaptureOnlyBitmap.getWidth() +
"x" + mCaptureOnlyBitmap.getHeight() + " ) in " +
@@ -492,56 +510,16 @@ public class Camera extends Activity implements View.OnClickListener,
((mThreadTimeEnd - mThreadTimeStart) / 1000000) + " ms.");
}
- openOptionsMenu();
+ showPostCaptureAlert();
+ cancelAutomaticPreviewRestart();
}
-
mCapturing = false;
if (mPausing) {
closeCamera();
}
}
- private void setLastPictureThumb(byte[] data) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = 16;
-
- if (DEBUG) {
- startTiming();
- }
-
- Bitmap lastPictureThumb = BitmapFactory.decodeByteArray(data, 0, data.length, options);
-
- if (DEBUG) {
- stopTiming();
- Log.d(TAG, "Decoded lastPictureThumb bitmap (" + lastPictureThumb.getWidth() +
- "x" + lastPictureThumb.getHeight() + " ) in " +
- (mWallTimeEnd - mWallTimeStart) + " ms. Thread time was " +
- ((mThreadTimeEnd - mThreadTimeStart) / 1000000) + " ms.");
- }
-
- final int PADDING_WIDTH = 2;
- final int PADDING_HEIGHT = 2;
- LayoutParams layoutParams = mLastPictureButton.getLayoutParams();
- // Make the mini-thumbnail size smaller than the button size so that the image corners
- // don't peek out from the rounded corners of the frame_thumbnail graphic:
- final int miniThumbWidth = layoutParams.width - 2 * PADDING_WIDTH;
- final int miniThumbHeight = layoutParams.height - 2 * PADDING_HEIGHT;
-
- lastPictureThumb = ImageManager.extractMiniThumb(lastPictureThumb,
- miniThumbWidth, miniThumbHeight);
-
- Drawable[] layers = new Drawable[2];
- layers[0] = new BitmapDrawable(lastPictureThumb);
- layers[1] = getResources().getDrawable(R.drawable.frame_thumbnail);
- LayerDrawable layerDrawable = new LayerDrawable(layers);
- layerDrawable.setLayerInset(0, PADDING_WIDTH, PADDING_HEIGHT,
- PADDING_WIDTH, PADDING_HEIGHT);
- mLastPictureButton.setImageDrawable(layerDrawable);
- mLastPictureButton.setVisibility(View.VISIBLE);
- mLastPictureUri = mCaptureObject.getLastCaptureUri();
- }
-
/*
* Tells the image capture thread to abort the capture of the
* current image.
@@ -589,44 +567,63 @@ public class Camera extends Activity implements View.OnClickListener,
Boolean recordLocation = mPreferences.getBoolean("pref_camera_recordlocation_key", false);
Location loc = recordLocation ? getCurrentLocation() : null;
- android.hardware.Camera.Parameters parameters = mCameraDevice.getParameters();
// Quality 75 has visible artifacts, and quality 90 looks great but the files begin to
// get large. 85 is a good compromise between the two.
- parameters.set("jpeg-quality", 85);
- parameters.set("rotation", latchedOrientation);
-
- parameters.remove("gps-latitude");
- parameters.remove("gps-longitude");
- parameters.remove("gps-altitude");
- parameters.remove("gps-timestamp");
-
- if (loc != null) {
+ mParameters.set("jpeg-quality", 85);
+ mParameters.set("rotation", latchedOrientation);
+
+ mParameters.remove("gps-latitude");
+ mParameters.remove("gps-longitude");
+ mParameters.remove("gps-altitude");
+ mParameters.remove("gps-timestamp");
+
+ if (DEBUG_FAKE_GPS_LOCATION) {
+ // Google London office, having trouble encoding longitude
+
+ if (false) {
+ // This fails:
+ mParameters.set("gps-latitude", "51.49473309516907");
+ mParameters.set("gps-longitude", "-0.14598190784454346");
+ mParameters.set("gps-altitude", "71.0"); // meters
+ mParameters.set("gps-timestamp", "1233744883");
+ } else {
+ // This works OK:
+ mParameters.set("gps-latitude", "51.49473309516907");
+ mParameters.set("gps-longitude", "-1.0");
+ mParameters.set("gps-altitude", "71.0"); // meters
+ mParameters.set("gps-timestamp", "1233744883");
+ }
+ } else if (loc != null) {
double lat = loc.getLatitude();
double lon = loc.getLongitude();
+ boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d);
- if (lat != 0D && lon != 0d) {
- parameters.set("gps-latitude", String.valueOf(lat));
- parameters.set("gps-longitude", String.valueOf(lon));
+ if (hasLatLon) {
+ String latString = String.valueOf(lat);
+ String lonString = String.valueOf(lon);
+ mParameters.set("gps-latitude", latString);
+ mParameters.set("gps-longitude", lonString);
if (loc.hasAltitude())
- parameters.set("gps-altitude", String.valueOf(loc.getAltitude()));
+ mParameters.set("gps-altitude", String.valueOf(loc.getAltitude()));
if (loc.getTime() != 0) {
// Location.getTime() is UTC in milliseconds.
// gps-timestamp is UTC in seconds.
long utcTimeSeconds = loc.getTime() / 1000;
- parameters.set("gps-timestamp", String.valueOf(utcTimeSeconds));
+ mParameters.set("gps-timestamp", String.valueOf(utcTimeSeconds));
}
} else {
loc = null;
}
}
- Size pictureSize = parameters.getPictureSize();
+
+ Size pictureSize = mParameters.getPictureSize();
// resize the SurfaceView to the aspect-ratio of the still image
// and so that we can see the full image that was taken
mSurfaceView.setAspectRatio(pictureSize.width, pictureSize.height);
- mCameraDevice.setParameters(parameters);
+ mCameraDevice.setParameters(mParameters);
mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, new JpegPictureCallback(loc));
@@ -653,9 +650,9 @@ public class Camera extends Activity implements View.OnClickListener,
// Don't check the filesystem here, we can't afford the latency. Instead, check the
// cached value which was calculated when the preview was restarted.
- if (DEBUG) mShutterPressTime = System.currentTimeMillis();
+ if (DEBUG_TIME_OPERATIONS) mShutterPressTime = System.currentTimeMillis();
if (mPicturesRemaining < 1) {
- showStorageToast();
+ showStorageToast(mPicturesRemaining);
return;
}
@@ -672,6 +669,52 @@ public class Camera extends Activity implements View.OnClickListener,
}
}
+ private void setLastPictureThumb(byte[] data, Uri uri) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = 16;
+
+ Bitmap lastPictureThumb = BitmapFactory.decodeByteArray(data, 0, data.length, options);
+
+ setLastPictureThumb(lastPictureThumb, uri);
+ }
+
+ private void setLastPictureThumb(Bitmap lastPictureThumb, Uri uri) {
+
+ final int PADDING_WIDTH = 2;
+ final int PADDING_HEIGHT = 2;
+ LayoutParams layoutParams = mLastPictureButton.getLayoutParams();
+ // Make the mini-thumbnail size smaller than the button size so that the image corners
+ // don't peek out from the rounded corners of the frame_thumbnail graphic:
+ final int miniThumbWidth = layoutParams.width - 2 * PADDING_WIDTH;
+ final int miniThumbHeight = layoutParams.height - 2 * PADDING_HEIGHT;
+
+ lastPictureThumb = ImageManager.extractMiniThumb(lastPictureThumb,
+ miniThumbWidth, miniThumbHeight);
+
+ Drawable[] vignetteLayers = new Drawable[2];
+ vignetteLayers[1] = getResources().getDrawable(R.drawable.frame_thumbnail);
+ if (mThumbnails == null) {
+ mThumbnails = new Drawable[2];
+ mThumbnails[1] = new BitmapDrawable(lastPictureThumb);
+ vignetteLayers[0] = mThumbnails[1];
+ } else {
+ mThumbnails[0] = mThumbnails[1];
+ mThumbnails[1] = new BitmapDrawable(lastPictureThumb);
+ mThumbnailTransition = new TransitionDrawable(mThumbnails);
+ mShouldTransitionThumbnails = true;
+ vignetteLayers[0] = mThumbnailTransition;
+ }
+
+ mVignette = new LayerDrawable(vignetteLayers);
+ mVignette.setLayerInset(0, PADDING_WIDTH, PADDING_HEIGHT,
+ PADDING_WIDTH, PADDING_HEIGHT);
+ mLastPictureButton.setImageDrawable(mVignette);
+
+ if (mLastPictureButton.getVisibility() != View.VISIBLE) {
+ mShouldShowLastPictureButton = true;
+ }
+ mLastPictureUri = uri;
+ }
static private String createName(long dateTaken) {
return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
@@ -741,10 +784,27 @@ public class Camera extends Activity implements View.OnClickListener,
mBlackout.setBackgroundDrawable(new ColorDrawable(0xFF000000));
mLastPictureButton = (ImageView) findViewById(R.id.last_picture_button);
- mLastPictureButton.setOnClickListener(this);
- mLastPictureButton.setVisibility(View.INVISIBLE);
+ if (!isImageCaptureIntent()) {
+ ImageManager.IImageList images = ImageManager.instance().allImages(
+ this,
+ getContentResolver(),
+ ImageManager.DataLocation.ALL,
+ ImageManager.INCLUDE_IMAGES,
+ ImageManager.SORT_DESCENDING,
+ ImageManager.CAMERA_IMAGE_BUCKET_ID);
+ ImageManager.IImage lastPicture =
+ images.isEmpty() ? null : images.getImageAt(0);
+ mLastPictureButton.setOnClickListener(this);
+ if (lastPicture == null) {
+ mLastPictureButton.setVisibility(View.GONE);
+ } else {
+ Bitmap miniThumb = lastPicture.miniThumbBitmap();
+ setLastPictureThumb(miniThumb, lastPicture.fullSizeImageUri());
+ }
+ images.deactivate();
+ }
- mShutterButton = (ShutterButton) findViewById(R.id.mode_indicator);
+ mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
mShutterButton.setOnShutterButtonListener(this);
try {
@@ -773,42 +833,22 @@ public class Camera extends Activity implements View.OnClickListener,
mFocusBlinkAnimation = AnimationUtils.loadAnimation(this, R.anim.auto_focus_blink);
mFocusBlinkAnimation.setRepeatCount(Animation.INFINITE);
mFocusBlinkAnimation.setRepeatMode(Animation.REVERSE);
+
+ mPostCaptureAlert = findViewById(R.id.post_picture_panel);
}
@Override
public void onStart() {
super.onStart();
- final View hintView = findViewById(R.id.hint_toast);
- if (hintView != null)
- hintView.setVisibility(View.GONE);
-
Thread t = new Thread(new Runnable() {
public void run() {
final boolean storageOK = calculatePicturesRemaining() > 0;
- if (hintView == null)
- return;
- if (storageOK) {
+ if (!storageOK) {
mHandler.post(new Runnable() {
public void run() {
- hintView.setVisibility(View.VISIBLE);
- }
- });
- mHandler.postDelayed(new Runnable() {
- public void run() {
- Animation a = new android.view.animation.AlphaAnimation(1F, 0F);
- a.setDuration(500);
- a.startNow();
- hintView.setAnimation(a);
- hintView.setVisibility(View.GONE);
- }
- }, 3000);
- } else {
- mHandler.post(new Runnable() {
- public void run() {
- hintView.setVisibility(View.GONE);
- showStorageToast();
+ showStorageToast(mPicturesRemaining);
}
});
}
@@ -822,12 +862,124 @@ public class Camera extends Activity implements View.OnClickListener,
case R.id.last_picture_button:
viewLastImage();
break;
+ case R.id.attach:
+ doAttach();
+ break;
+ case R.id.cancel:
+ doCancel();
}
}
+ private void doAttach() {
+ Bitmap bitmap = mImageCapture.getLastBitmap();
+ mCaptureObject.setDone(true);
+
+ String cropValue = null;
+ Uri saveUri = null;
+
+ Bundle myExtras = getIntent().getExtras();
+ if (myExtras != null) {
+ saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
+ cropValue = myExtras.getString("crop");
+ }
+
+
+ if (cropValue == null) {
+ /*
+ * First handle the no crop case -- just return the value. If the caller
+ * specifies a "save uri" then write the data to it's stream. Otherwise,
+ * pass back a scaled down version of the bitmap directly in the extras.
+ */
+ if (saveUri != null) {
+ OutputStream outputStream = null;
+ try {
+ outputStream = mContentResolver.openOutputStream(saveUri);
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outputStream);
+ outputStream.close();
+
+ setResult(RESULT_OK);
+ finish();
+ } catch (IOException ex) {
+ //
+ } finally {
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException ex) {
+
+ }
+ }
+ }
+ } else {
+ float scale = .5F;
+ Matrix m = new Matrix();
+ m.setScale(scale, scale);
+
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(),
+ bitmap.getHeight(),
+ m, true);
+
+ setResult(RESULT_OK, new Intent("inline-data").putExtra("data", bitmap));
+ finish();
+ }
+ }
+ else {
+ /*
+ * Save the image to a temp file and invoke the cropper
+ */
+ Uri tempUri = null;
+ FileOutputStream tempStream = null;
+ try {
+ File path = getFileStreamPath(sTempCropFilename);
+ path.delete();
+ tempStream = openFileOutput(sTempCropFilename, 0);
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 75, tempStream);
+ tempStream.close();
+ tempUri = Uri.fromFile(path);
+ } catch (FileNotFoundException ex) {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ return;
+ } catch (IOException ex) {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ return;
+ } finally {
+ if (tempStream != null) {
+ try {
+ tempStream.close();
+ } catch (IOException ex) {
+
+ }
+ }
+ }
+
+ Bundle newExtras = new Bundle();
+ if (cropValue.equals("circle"))
+ newExtras.putString("circleCrop", "true");
+ if (saveUri != null)
+ newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, saveUri);
+ else
+ newExtras.putBoolean("return-data", true);
+
+ Intent cropIntent = new Intent();
+ cropIntent.setClass(Camera.this, CropImage.class);
+ cropIntent.setData(tempUri);
+ cropIntent.putExtras(newExtras);
+
+ startActivityForResult(cropIntent, CROP_MSG);
+ }
+ }
+
+ private void doCancel() {
+ setResult(RESULT_CANCELED, new Intent());
+ finish();
+ }
+
public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
switch (button.getId()) {
- case R.id.mode_indicator:
+ case R.id.shutter_button:
doFocus(pressed);
break;
}
@@ -835,7 +987,7 @@ public class Camera extends Activity implements View.OnClickListener,
public void onShutterButtonClick(ShutterButton button) {
switch (button.getId()) {
- case R.id.mode_indicator:
+ case R.id.shutter_button:
doSnap(false);
break;
}
@@ -845,6 +997,10 @@ public class Camera extends Activity implements View.OnClickListener,
MenuHelper.showStorageToast(this);
}
+ private void showStorageToast(int remainingPictures) {
+ MenuHelper.showStorageToast(this, remainingPictures);
+ }
+
@Override
public void onResume() {
super.onResume();
@@ -858,6 +1014,7 @@ public class Camera extends Activity implements View.OnClickListener,
intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
+ intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING);
intentFilter.addDataScheme("file");
registerReceiver(mReceiver, intentFilter);
mDidRegister = true;
@@ -878,14 +1035,14 @@ public class Camera extends Activity implements View.OnClickListener,
mFocusToneGenerator = null;
}
- mBlackout.setVisibility(View.INVISIBLE);
+ mBlackout.setVisibility(View.GONE);
if (mLastPictureUri != null) {
IImageList list = ImageManager.makeImageList(mLastPictureUri, this,
ImageManager.SORT_ASCENDING);
if (list.getImageForUri(mLastPictureUri) == null) {
mLastPictureUri = null;
- mLastPictureButton.setVisibility(View.INVISIBLE);
+ mLastPictureButton.setVisibility(View.GONE);
}
list.deactivate();
}
@@ -996,7 +1153,7 @@ public class Camera extends Activity implements View.OnClickListener,
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
- if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
+ if (mStatus == SNAPSHOT_IN_PROGRESS) {
// ignore backs while we're taking a picture
return true;
}
@@ -1011,6 +1168,18 @@ public class Camera extends Activity implements View.OnClickListener,
doSnap(false);
}
return true;
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ // If we get a dpad center event without any focused view, move the
+ // focus to the shutter button and press it.
+ if (event.getRepeatCount() == 0) {
+ if (mShutterButton.isInTouchMode()) {
+ mShutterButton.requestFocusFromTouch();
+ } else {
+ mShutterButton.requestFocus();
+ }
+ mShutterButton.setPressed(true);
+ }
+ return true;
}
return super.onKeyDown(keyCode, event);
@@ -1053,6 +1222,7 @@ public class Camera extends Activity implements View.OnClickListener,
private void doFocus(boolean pressed) {
if (pressed) {
mIsFocusButtonPressed = true;
+ mCaptureOnFocus = false;
if (mPreviewing) {
autoFocus();
} else if (mCaptureObject != null) {
@@ -1113,6 +1283,17 @@ public class Camera extends Activity implements View.OnClickListener,
// TODO: The best longterm solution is to write a reserve file of maximum JPEG size, always
// let the user take a picture, and delete that file if needed to save the new photo.
calculatePicturesRemaining();
+
+ if (mShouldShowLastPictureButton) {
+ mShouldShowLastPictureButton = false;
+ mLastPictureButton.setVisibility(View.VISIBLE);
+ Animation a = mShowLastPictureButtonAnimation;
+ a.setDuration(500);
+ mLastPictureButton.setAnimation(a);
+ } else if (mShouldTransitionThumbnails) {
+ mShouldTransitionThumbnails = false;
+ mThumbnailTransition.reverseTransition(500);
+ }
}
private void setViewFinder(int w, int h, boolean startPreview) {
@@ -1169,10 +1350,10 @@ public class Camera extends Activity implements View.OnClickListener,
// request the preview size, the hardware may not honor it,
// if we depended on it we would have to query the size again
- android.hardware.Camera.Parameters p = mCameraDevice.getParameters();
- p.setPreviewSize(w, h);
+ mParameters = mCameraDevice.getParameters();
+ mParameters.setPreviewSize(w, h);
try {
- mCameraDevice.setParameters(p);
+ mCameraDevice.setParameters(mParameters);
} catch (IllegalArgumentException e) {
// Ignore this error, it happens in the simulator.
}
@@ -1266,6 +1447,7 @@ public class Camera extends Activity implements View.OnClickListener,
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
intent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true);
intent.putExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, true);
+ intent.putExtra("com.android.camera.ReviewMode", true);
try {
startActivity(intent);
@@ -1374,8 +1556,7 @@ public class Camera extends Activity implements View.OnClickListener,
public boolean onMenuOpened(int featureId, Menu menu) {
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
if (mStatus == SNAPSHOT_IN_PROGRESS) {
- mKeepAndRestartPreview = false;
- mHandler.removeMessages(RESTART_PREVIEW);
+ cancelAutomaticPreviewRestart();
mMenuSelectionMade = false;
}
}
@@ -1408,127 +1589,43 @@ public class Camera extends Activity implements View.OnClickListener,
return true;
}
+ private void cancelAutomaticPreviewRestart() {
+ mKeepAndRestartPreview = false;
+ mHandler.removeMessages(RESTART_PREVIEW);
+ }
+
private boolean isImageCaptureIntent() {
String action = getIntent().getAction();
return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action));
}
+ private void showPostCaptureAlert() {
+ boolean isPick = isImageCaptureIntent();
+ int pickVisible = isPick ? View.VISIBLE : View.GONE;
+ mPostCaptureAlert.setVisibility(pickVisible);
+ if (isPick) {
+ int[] pickIds = {R.id.attach, R.id.cancel};
+ for(int id : pickIds) {
+ View view = mPostCaptureAlert.findViewById(id);
+ view.setOnClickListener(this);
+ Animation animation = new AlphaAnimation(0F, 1F);
+ animation.setDuration(500);
+ view.setAnimation(animation);
+ }
+ }
+ }
+
+ private void hidePostCaptureAlert() {
+ mPostCaptureAlert.setVisibility(View.GONE);
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
if (isImageCaptureIntent()) {
- menu.add(MenuHelper.IMAGE_SAVING_ITEM, MENU_SAVE_SELECT_PHOTOS , 0, R.string.camera_selectphoto).setOnMenuItemClickListener(new OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- Bitmap bitmap = mImageCapture.getLastBitmap();
- mCaptureObject.setDone(true);
-
- String cropValue = null;
- Uri saveUri = null;
-
- Bundle myExtras = getIntent().getExtras();
- if (myExtras != null) {
- saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
- cropValue = myExtras.getString("crop");
- }
-
-
- if (cropValue == null) {
- /*
- * First handle the no crop case -- just return the value. If the caller
- * specifies a "save uri" then write the data to it's stream. Otherwise,
- * pass back a scaled down version of the bitmap directly in the extras.
- */
- if (saveUri != null) {
- OutputStream outputStream = null;
- try {
- outputStream = mContentResolver.openOutputStream(saveUri);
- bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outputStream);
- outputStream.close();
-
- setResult(RESULT_OK);
- finish();
- } catch (IOException ex) {
- //
- } finally {
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException ex) {
-
- }
- }
- }
- } else {
- float scale = .5F;
- Matrix m = new Matrix();
- m.setScale(scale, scale);
-
- bitmap = Bitmap.createBitmap(bitmap, 0, 0,
- bitmap.getWidth(),
- bitmap.getHeight(),
- m, true);
-
- setResult(RESULT_OK, new Intent("inline-data").putExtra("data", bitmap));
- finish();
- }
- }
- else {
- /*
- * Save the image to a temp file and invoke the cropper
- */
- Uri tempUri = null;
- FileOutputStream tempStream = null;
- try {
- File path = getFileStreamPath(sTempCropFilename);
- path.delete();
- tempStream = openFileOutput(sTempCropFilename, 0);
- bitmap.compress(Bitmap.CompressFormat.JPEG, 75, tempStream);
- tempStream.close();
- tempUri = Uri.fromFile(path);
- } catch (FileNotFoundException ex) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- return true;
- } catch (IOException ex) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- return true;
- } finally {
- if (tempStream != null) {
- try {
- tempStream.close();
- } catch (IOException ex) {
-
- }
- }
- }
-
- Bundle newExtras = new Bundle();
- if (cropValue.equals("circle"))
- newExtras.putString("circleCrop", "true");
- if (saveUri != null)
- newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, saveUri);
- else
- newExtras.putBoolean("return-data", true);
-
- Intent cropIntent = new Intent();
- cropIntent.setClass(Camera.this, CropImage.class);
- cropIntent.setData(tempUri);
- cropIntent.putExtras(newExtras);
-
- startActivityForResult(cropIntent, CROP_MSG);
- }
- return true;
- }
- });
-
- menu.add(MenuHelper.IMAGE_SAVING_ITEM, MENU_SAVE_NEW_PHOTO, 0, R.string.camera_takenewphoto).setOnMenuItemClickListener(new OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- keep();
- return true;
- }
- });
+ // No options menu for attach mode.
+ return false;
} else {
addBaseMenuItems(menu);
MenuHelper.addImageMenuItems(
@@ -1627,10 +1724,5 @@ public class Camera extends Activity implements View.OnClickListener,
});
item.setIcon(android.R.drawable.ic_menu_preferences);
}
-
- private void cancelRestartPreviewTimeout() {
- mHandler.removeMessages(RESTART_PREVIEW);
- }
-
}
diff --git a/src/com/android/camera/CropImage.java b/src/com/android/camera/CropImage.java
index 9542ce0..5250b56 100644
--- a/src/com/android/camera/CropImage.java
+++ b/src/com/android/camera/CropImage.java
@@ -434,6 +434,7 @@ public class CropImage extends Activity {
findViewById(R.id.discard).setOnClickListener(new android.view.View.OnClickListener() {
public void onClick(View v) {
+ setResult(RESULT_CANCELED);
finish();
}
});
diff --git a/src/com/android/camera/GalleryPicker.java b/src/com/android/camera/GalleryPicker.java
index 44f8fc2..cf883dd 100644
--- a/src/com/android/camera/GalleryPicker.java
+++ b/src/com/android/camera/GalleryPicker.java
@@ -73,7 +73,6 @@ public class GalleryPicker extends Activity {
Dialog mMediaScanningDialog;
- MenuItem mFlipItem;
SharedPreferences mPrefs;
boolean mPausing = false;
@@ -96,8 +95,49 @@ public class GalleryPicker extends Activity {
true,
true);
}
- mAdapter.notifyDataSetChanged();
- mAdapter.init(!unmounted && !scanning);
+ if (mAdapter != null) {
+ mAdapter.notifyDataSetChanged();
+ mAdapter.init(!unmounted && !scanning);
+ }
+
+ if (!unmounted) {
+ // Warn the user if space is getting low
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+
+ // Check available space only if we are writable
+ if (ImageManager.hasStorage()) {
+ String storageDirectory = Environment.getExternalStorageDirectory().toString();
+ StatFs stat = new StatFs(storageDirectory);
+ long remaining = (long)stat.getAvailableBlocks() * (long)stat.getBlockSize();
+ if (remaining < LOW_STORAGE_THRESHOLD) {
+
+ mHandler.post(new Runnable() {
+ public void run() {
+ Toast.makeText(GalleryPicker.this.getApplicationContext(),
+ R.string.not_enough_space, 5000).show();
+ }
+ });
+ }
+ }
+ }
+ });
+ t.start();
+ }
+
+ // If we just have zero or one folder, open it. (We shouldn't have just one folder
+ // any more, but we can have zero folders.)
+ mNoImagesView.setVisibility(View.GONE);
+ if (!scanning) {
+ int numItems = mAdapter.mItems.size();
+ if (numItems == 0) {
+ mNoImagesView.setVisibility(View.VISIBLE);
+ } else if (numItems == 1) {
+ mAdapter.mItems.get(0).launch(this);
+ finish();
+ return;
+ }
+ }
}
@Override
@@ -201,6 +241,7 @@ public class GalleryPicker extends Activity {
static class Item implements Comparable<Item>{
// The type is also used as the sort order
+ public final static int TYPE_NONE = -1;
public final static int TYPE_ALL_IMAGES = 0;
public final static int TYPE_ALL_VIDEOS = 1;
public final static int TYPE_CAMERA_IMAGES = 2;
@@ -329,14 +370,16 @@ public class GalleryPicker extends Activity {
images.deactivate();
notifyDataSetInvalidated();
- // If just one
- addBucketIfNotEmpty(Item.TYPE_ALL_IMAGES, null, R.string.all_images);
- addBucketIfNotEmpty(Item.TYPE_ALL_VIDEOS, null, R.string.all_videos);
+ // Conditionally add all-images and all-videos folders.
+ addBucket(Item.TYPE_ALL_IMAGES, null,
+ Item.TYPE_CAMERA_IMAGES, cameraBucketId, R.string.all_images);
+ addBucket(Item.TYPE_ALL_VIDEOS, null,
+ Item.TYPE_CAMERA_VIDEOS, cameraBucketId, R.string.all_videos);
if (cameraBucketId != null) {
- addBucketIfNotEmpty(Item.TYPE_CAMERA_IMAGES, cameraBucketId,
+ addBucket(Item.TYPE_CAMERA_IMAGES, cameraBucketId,
R.string.gallery_camera_bucket_name);
- addBucketIfNotEmpty(Item.TYPE_CAMERA_VIDEOS, cameraBucketId,
+ addBucket(Item.TYPE_CAMERA_VIDEOS, cameraBucketId,
R.string.gallery_camera_videos_bucket_name);
}
@@ -401,7 +444,36 @@ public class GalleryPicker extends Activity {
mWorkerThread.toBackground();
}
- private void addBucketIfNotEmpty(int itemType, String bucketId, int labelId) {
+ /**
+ * Add a bucket, but only if it's interesting.
+ * Interesting means non-empty and not duplicated by the
+ * corresponding camera bucket.
+ */
+ private void addBucket(int itemType, String bucketId,
+ int cameraItemType, String cameraBucketId,
+ int labelId) {
+ int itemCount = bucketItemCount(
+ Item.convertItemTypeToIncludedMediaType(itemType), bucketId);
+ if (itemCount == 0) {
+ return; // Bucket is empty, so don't show it.
+ }
+ int cameraItemCount = 0;
+ if (cameraBucketId != null) {
+ cameraItemCount = bucketItemCount(
+ Item.convertItemTypeToIncludedMediaType(cameraItemType), cameraBucketId);
+ }
+ if (cameraItemCount == itemCount) {
+ return; // Bucket is the same as the camera bucket, so don't show it.
+ }
+ mItems.add(new Item(itemType, bucketId, getResources().getString(labelId)));
+ }
+
+ /**
+ * Add a bucket, but only if it's interesting.
+ * Interesting means non-empty.
+ */
+ private void addBucket(int itemType, String bucketId,
+ int labelId) {
if (!isEmptyBucket(Item.convertItemTypeToIncludedMediaType(itemType), bucketId)) {
mItems.add(new Item(itemType, bucketId, getResources().getString(labelId)));
}
@@ -489,49 +561,10 @@ public class GalleryPicker extends Activity {
registerReceiver(mReceiver, intentFilter);
MenuHelper.requestOrientation(this, mPrefs);
-
- // Warn the user if space is getting low
- Thread t = new Thread(new Runnable() {
- public void run() {
-
- // Check available space only if we are writable
- if (ImageManager.hasStorage()) {
- String storageDirectory = Environment.getExternalStorageDirectory().toString();
- StatFs stat = new StatFs(storageDirectory);
- long remaining = (long)stat.getAvailableBlocks() * (long)stat.getBlockSize();
- if (remaining < LOW_STORAGE_THRESHOLD) {
-
- mHandler.post(new Runnable() {
- public void run() {
- Toast.makeText(GalleryPicker.this.getApplicationContext(),
- R.string.not_enough_space, 5000).show();
- }
- });
- }
- }
- }
- });
- t.start();
-
- // If we just have zero or one folder, open it. (We shouldn't have just one folder
- // any more, but we can have zero folders.)
- mNoImagesView.setVisibility(View.GONE);
- if (!scanning) {
- int numItems = mAdapter.mItems.size();
- if (numItems == 0) {
- mNoImagesView.setVisibility(View.VISIBLE);
- } else if (numItems == 1) {
- // Not sure we can ever get here any more.
- android.net.Uri uri = Images.Media.INTERNAL_CONTENT_URI;
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- startActivity(intent);
- finish();
- return;
- }
- }
}
+
private void setBackgrounds(Resources r) {
mFrameGalleryMask = r.getDrawable(R.drawable.frame_gallery_preview_album_mask);
@@ -644,7 +677,6 @@ public class GalleryPicker extends Activity {
super.onCreateOptionsMenu(menu);
MenuHelper.addCaptureMenuItems(menu, this);
- mFlipItem = MenuHelper.addFlipOrientation(menu, this, mPrefs);
menu.add(0, 0, 5, R.string.camerasettings)
.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@@ -661,12 +693,6 @@ public class GalleryPicker extends Activity {
return true;
}
- @Override
- public boolean onPrepareOptionsMenu(android.view.Menu menu) {
- MenuHelper.setFlipOrientationEnabled(this, mFlipItem);
- return true;
- }
-
private boolean isEmptyBucket(int mediaTypes, String bucketId) {
// TODO: Find a more efficient way of calculating this
ImageManager.IImageList list = createImageList(mediaTypes, bucketId);
@@ -678,6 +704,16 @@ public class GalleryPicker extends Activity {
}
}
+ private int bucketItemCount(int mediaTypes, String bucketId) {
+ // TODO: Find a more efficient way of calculating this
+ ImageManager.IImageList list = createImageList(mediaTypes, bucketId);
+ try {
+ return list.getCount();
+ }
+ finally {
+ list.deactivate();
+ }
+ }
private ImageManager.IImageList createImageList(int mediaTypes, String bucketId) {
return ImageManager.instance().allImages(
this,
diff --git a/src/com/android/camera/ImageGallery2.java b/src/com/android/camera/ImageGallery2.java
index 92e9c57..d58f04c 100644
--- a/src/com/android/camera/ImageGallery2.java
+++ b/src/com/android/camera/ImageGallery2.java
@@ -73,7 +73,6 @@ public class ImageGallery2 extends Activity {
private Dialog mMediaScanningDialog;
- private MenuItem mFlipItem;
private MenuItem mSlideShowItem;
private SharedPreferences mPrefs;
@@ -187,7 +186,10 @@ public class ImageGallery2 extends Activity {
private Runnable mDeletePhotoRunnable = new Runnable() {
public void run() {
mGvs.clearCache();
- mAllImages.removeImage(mSelectedImageGetter.getCurrentImage());
+ IImage currentImage = mSelectedImageGetter.getCurrentImage();
+ if (currentImage != null) {
+ mAllImages.removeImage(currentImage);
+ }
mGvs.invalidate();
mGvs.requestLayout();
mGvs.start();
@@ -356,8 +358,10 @@ public class ImageGallery2 extends Activity {
switch (requestCode) {
case CROP_MSG: {
if (Config.LOGV) Log.v(TAG, "onActivityResult " + data);
- setResult(resultCode, data);
- finish();
+ if (resultCode == RESULT_OK) {
+ setResult(resultCode, data);
+ finish();
+ }
break;
}
case VIEW_MSG: {
@@ -504,7 +508,6 @@ public class ImageGallery2 extends Activity {
mThumbnailCheckThread = new CameraThread(new Runnable() {
public void run() {
android.content.res.Resources resources = getResources();
- boolean loadingVideos = mInclusion == ImageManager.INCLUDE_VIDEOS;
final TextView progressTextView = (TextView) findViewById(R.id.loading_text);
final String progressTextFormatString = resources.getString(R.string.loading_progress_format_string);
@@ -547,7 +550,8 @@ public class ImageGallery2 extends Activity {
return !mPausing;
}
};
- allImages(true).checkThumbnails(r);
+ ImageManager.IImageList imageList = allImages(true);
+ imageList.checkThumbnails(r, imageList.getCount());
mWakeLock.release();
mThumbnailCheckThread = null;
mHandler.post(new Runnable() {
@@ -572,12 +576,13 @@ public class ImageGallery2 extends Activity {
@Override
public boolean onCreateOptionsMenu(android.view.Menu menu) {
MenuItem item;
- MenuHelper.addCaptureMenuItems(menu, this);
- if ((mInclusion & ImageManager.INCLUDE_IMAGES) != 0) {
- mSlideShowItem = addSlideShowMenu(menu, 5);
+ if (! isPickIntent()) {
+ MenuHelper.addCaptureMenuItems(menu, this);
+ if ((mInclusion & ImageManager.INCLUDE_IMAGES) != 0) {
+ mSlideShowItem = addSlideShowMenu(menu, 5);
+ }
}
- mFlipItem = MenuHelper.addFlipOrientation(menu, this, mPrefs);
item = menu.add(0, 0, 1000, R.string.camerasettings);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@@ -599,9 +604,10 @@ public class ImageGallery2 extends Activity {
if ((mInclusion & ImageManager.INCLUDE_IMAGES) != 0) {
boolean videoSelected = isVideoSelected();
// TODO: Only enable slide show if there is at least one image in the folder.
- mSlideShowItem.setEnabled(!videoSelected);
+ if (mSlideShowItem != null) {
+ mSlideShowItem.setEnabled(!videoSelected);
+ }
}
- MenuHelper.setFlipOrientationEnabled(this, mFlipItem);
return true;
}
@@ -745,7 +751,7 @@ public class ImageGallery2 extends Activity {
setVerticalScrollBarEnabled(true);
initializeScrollbars(context.obtainStyledAttributes(android.R.styleable.View));
- mGestureDetector = new GestureDetector(new SimpleOnGestureListener() {
+ mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
if (mScroller != null && !mScroller.isFinished()) {
@@ -1037,7 +1043,7 @@ public class ImageGallery2 extends Activity {
loadNext();
synchronized (ImageBlockManager.this) {
- if (workCounter == mWorkCounter) {
+ if ((workCounter == mWorkCounter) && (! mDone)) {
try {
ImageBlockManager.this.wait();
} catch (InterruptedException ex) {
diff --git a/src/com/android/camera/ImageManager.java b/src/com/android/camera/ImageManager.java
index 4354e92..b21b243 100755
--- a/src/com/android/camera/ImageManager.java
+++ b/src/com/android/camera/ImageManager.java
@@ -63,7 +63,7 @@ import java.util.HashMap;
*/
public class ImageManager {
public static final String CAMERA_IMAGE_BUCKET_NAME =
- Environment.getExternalStorageDirectory().toString() + "/dcim/Camera";
+ Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera";
public static final String CAMERA_IMAGE_BUCKET_ID = getBucketId(CAMERA_IMAGE_BUCKET_NAME);
/**
@@ -830,7 +830,7 @@ public class ImageManager {
}
String randomAccessFilePath(int version) {
- String directoryName = Environment.getExternalStorageDirectory().toString() + "/dcim/.thumbnails";
+ String directoryName = Environment.getExternalStorageDirectory().toString() + "/DCIM/.thumbnails";
String path = directoryName + "/.thumbdata" + version + "-" + mUri.hashCode();
return path;
}
@@ -1035,25 +1035,6 @@ public class ImageManager {
return bitmap;
}
- private Bitmap createVideoThumbnail(String filePath) {
- Bitmap bitmap = null;
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- try {
- retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
- retriever.setDataSource(filePath);
- bitmap = retriever.captureFrame();
- } catch (RuntimeException ex) {
- // Assume this is a corrupt video file.
- } finally {
- try {
- retriever.release();
- } catch (RuntimeException ex) {
- // Ignore failures while cleaning up.
- }
- }
- return bitmap;
- }
-
// returns id
public long checkThumbnail(BaseImage existingImage, Cursor c, int i) {
long magic, fileMagic = 0, id;
@@ -1114,13 +1095,13 @@ public class ImageManager {
}
}
if (filePath != null) {
- bitmap = createThumbnailFromEXIF(filePath, id);
- if (bitmap == null) {
- String mimeType = c.getString(indexMimeType());
- boolean isVideo = isVideoMimeType(mimeType);
- if (isVideo) {
- bitmap = createVideoThumbnail(filePath);
- } else {
+ String mimeType = c.getString(indexMimeType());
+ boolean isVideo = isVideoMimeType(mimeType);
+ if (isVideo) {
+ bitmap = createVideoThumbnail(filePath);
+ } else {
+ bitmap = createThumbnailFromEXIF(filePath, id);
+ if (bitmap == null) {
bitmap = createThumbnailFromUri(c, id);
}
}
@@ -1166,13 +1147,13 @@ public class ImageManager {
}
}
- public void checkThumbnails(ThumbCheckCallback cb) {
+ public void checkThumbnails(ThumbCheckCallback cb, int totalThumbnails) {
Cursor c = Images.Media.query(
mContentResolver,
mBaseUri,
new String[] { "_id", "mini_thumb_magic" },
- "mini_thumb_magic isnull and " + sWhereClause,
- sAcceptableImageTypes,
+ thumbnailWhereClause(),
+ thumbnailWhereClauseArgs(),
"_id ASC");
int count = c.getCount();
@@ -1201,7 +1182,6 @@ public class ImageManager {
c = getCursor();
try {
if (VERBOSE) Log.v(TAG, "checkThumbnails found " + c.getCount());
- int max = c.getCount();
int current = 0;
for (int i = 0; i < c.getCount(); i++) {
try {
@@ -1211,7 +1191,7 @@ public class ImageManager {
break;
}
if (cb != null) {
- if (!cb.checking(current, max)) {
+ if (!cb.checking(current, totalThumbnails)) {
if (VERBOSE) Log.v(TAG, "got false from checking... break <<<<<<<<<<<<<<<<<<<<<<<<");
break;
}
@@ -1228,6 +1208,14 @@ public class ImageManager {
}
}
+ protected String thumbnailWhereClause() {
+ return sMiniThumbIsNull + " and " + sWhereClause;
+ }
+
+ protected String[] thumbnailWhereClauseArgs() {
+ return sAcceptableImageTypes;
+ }
+
public void commitChanges() {
synchronized (mCursor) {
mCursor.commitUpdates();
@@ -1696,7 +1684,7 @@ public class ImageManager {
public boolean checking(int current, int count);
}
- public abstract void checkThumbnails(ThumbCheckCallback cb);
+ public abstract void checkThumbnails(ThumbCheckCallback cb, int totalCount);
public abstract void commitChanges();
@@ -2085,6 +2073,7 @@ public class ImageManager {
final static private String sWhereClause = "(" + Images.Media.MIME_TYPE + "=? or " + Images.Media.MIME_TYPE + "=?" + ")";
final static private String[] sAcceptableImageTypes = new String[] { "image/jpeg", "image/png" };
+ final static private String sMiniThumbIsNull = "mini_thumb_magic isnull";
private static final String[] IMAGE_PROJECTION = new String[] {
"_id",
@@ -2362,7 +2351,7 @@ public class ImageManager {
}
@Override
- public void checkThumbnails(ThumbCheckCallback cb) {
+ public void checkThumbnails(ThumbCheckCallback cb, int totalCount) {
// do nothing
}
@@ -2465,13 +2454,12 @@ public class ImageManager {
}
}
- public void checkThumbnails(ThumbCheckCallback cb) {
- // TODO this isn't quite right because we need to get the
- // total from each sub item and provide that in the callback
- final IImageList sublist[] = mSubList;
- final int length = sublist.length;
- for (int i = 0; i < length; i++)
- sublist[i].checkThumbnails(cb);
+ public void checkThumbnails(ThumbCheckCallback cb, int totalThumbnails) {
+ for (IImageList i : mSubList) {
+ int count = i.getCount();
+ i.checkThumbnails(cb, totalThumbnails);
+ totalThumbnails -= count;
+ }
}
public void commitChanges() {
@@ -3284,7 +3272,6 @@ public class ImageManager {
HashMap<String, String> hash = new HashMap<String, String>();
if (c != null && c.moveToFirst()) {
do {
- Log.e(TAG, "id: " + c.getString(1) + " display_name: " + c.getString(0));
hash.put(c.getString(1), c.getString(0));
} while (c.moveToNext());
}
@@ -3303,6 +3290,16 @@ public class ImageManager {
return null;
}
+ @Override
+ protected String thumbnailWhereClause() {
+ return sMiniThumbIsNull;
+ }
+
+ @Override
+ protected String[] thumbnailWhereClauseArgs() {
+ return null;
+ }
+
protected Cursor createCursor() {
Cursor c =
Images.Media.query(
@@ -3366,13 +3363,14 @@ public class ImageManager {
return thumbnail;
}
- private final Bitmap sDefaultThumbnail = Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565);
private String sortOrder() {
- return Video.Media.DATE_MODIFIED + (mSort == SORT_ASCENDING ? " ASC " : " DESC");
+ return Video.Media.DATE_TAKEN + (mSort == SORT_ASCENDING ? " ASC " : " DESC");
}
}
+ private final static Bitmap sDefaultThumbnail = Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565);
+
/**
* Represents a particular video and provides access
* to the underlying data and two thumbnail bitmaps
@@ -3537,10 +3535,10 @@ public class ImageManager {
sb.append("" + mId);
return sb.toString();
}
-
- private final Bitmap sNoImageBitmap = Bitmap.createBitmap(128, 128, Bitmap.Config.RGB_565);
}
+ private final static Bitmap sNoImageBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
+
/*
* How much quality to use when storing the thumbnail.
*/
@@ -3900,7 +3898,8 @@ public class ImageManager {
public IImageList emptyImageList() {
return
new IImageList() {
- public void checkThumbnails(com.android.camera.ImageManager.IImageList.ThumbCheckCallback cb) {
+ public void checkThumbnails(ImageManager.IImageList.ThumbCheckCallback cb,
+ int totalThumbnails) {
}
public void commitChanges() {
@@ -3936,10 +3935,11 @@ public class ImageManager {
public void removeImageAt(int i) {
}
- public void removeOnChangeListener(com.android.camera.ImageManager.IImageList.OnChange changeCallback) {
+ public void removeOnChangeListener(ImageManager.IImageList.OnChange changeCallback) {
}
- public void setOnChangeListener(com.android.camera.ImageManager.IImageList.OnChange changeCallback, Handler h) {
+ public void setOnChangeListener(ImageManager.IImageList.OnChange changeCallback,
+ Handler h) {
}
};
@@ -4027,7 +4027,7 @@ public class ImageManager {
// Create a temporary file to see whether a volume is really writeable. It's important not to
// put it in the root directory which may have a limit on the number of files.
static private boolean checkFsWritable() {
- String directoryName = Environment.getExternalStorageDirectory().toString() + "/dcim";
+ String directoryName = Environment.getExternalStorageDirectory().toString() + "/DCIM";
File directory = new File(directoryName);
if (!directory.isDirectory()) {
if (!directory.mkdirs()) {
@@ -4100,4 +4100,30 @@ public class ImageManager {
Log.v(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>> isMediaScannerScanning returning " + result);
return result;
}
+
+ /**
+ * Create a video thumbnail for a video. May return null if the video is corrupt.
+ * @param filePath
+ * @return
+ */
+ public static Bitmap createVideoThumbnail(String filePath) {
+ Bitmap bitmap = null;
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ try {
+ retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
+ retriever.setDataSource(filePath);
+ bitmap = retriever.captureFrame();
+ } catch(IllegalArgumentException ex) {
+ // Assume this is a corrupt video file
+ } catch (RuntimeException ex) {
+ // Assume this is a corrupt video file.
+ } finally {
+ try {
+ retriever.release();
+ } catch (RuntimeException ex) {
+ // Ignore failures while cleaning up.
+ }
+ }
+ return bitmap;
+ }
}
diff --git a/src/com/android/camera/MenuHelper.java b/src/com/android/camera/MenuHelper.java
index 1976444..d4358f6 100644
--- a/src/com/android/camera/MenuHelper.java
+++ b/src/com/android/camera/MenuHelper.java
@@ -16,13 +16,15 @@
package com.android.camera;
+import java.util.ArrayList;
+
import android.app.Activity;
import android.app.AlertDialog;
-import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Environment;
@@ -37,16 +39,10 @@ import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.MenuItem.OnMenuItemClickListener;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.EditText;
import android.widget.ImageView;
-import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
-import java.util.ArrayList;
-
import com.android.camera.ImageManager.IImage;
public class MenuHelper {
@@ -357,8 +353,14 @@ public class MenuHelper {
String codec = retriever.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_CODEC);
- ((TextView)d.findViewById(R.id.details_codec_value))
- .setText(codec);
+
+ if (codec == null) {
+ d.findViewById(R.id.details_codec_row).
+ setVisibility(View.GONE);
+ } else {
+ ((TextView)d.findViewById(R.id.details_codec_value))
+ .setText(codec);
+ }
} catch(RuntimeException ex) {
// Assume this is a corrupt video file.
} finally {
@@ -531,9 +533,26 @@ public class MenuHelper {
}
static void gotoCameraImageGallery(Activity activity) {
+ gotoGallery(activity, R.string.gallery_camera_bucket_name, ImageManager.INCLUDE_IMAGES);
+ }
+
+ static void gotoCameraVideoGallery(Activity activity) {
+ gotoGallery(activity, R.string.gallery_camera_videos_bucket_name,
+ ImageManager.INCLUDE_VIDEOS);
+ }
+
+ static private void gotoGallery(Activity activity, int windowTitleId, int mediaTypes) {
Uri target = Images.Media.INTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("bucketId",
ImageManager.CAMERA_IMAGE_BUCKET_ID).build();
Intent intent = new Intent(Intent.ACTION_VIEW, target);
+ intent.putExtra("windowTitle", activity.getString(windowTitleId));
+ intent.putExtra("mediaTypes", mediaTypes);
+ // Request unspecified so that we match the current camera orientation rather than
+ // matching the "flip orientation" preference.
+ // Disabled because people don't care for it. Also it's
+ // not as compelling now that we have implemented have quick orientation flipping.
+ // intent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
+ // android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException e) {
@@ -575,20 +594,22 @@ public class MenuHelper {
}
static MenuItem addFlipOrientation(Menu menu, final Activity activity, final SharedPreferences prefs) {
// position 41 after rotate
+ // D
return menu
.add(Menu.CATEGORY_SECONDARY, 304, 41, R.string.flip_orientation)
.setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
- int current = activity.getRequestedOrientation();
+ // Check what our actual orientation is
+ int current = activity.getResources().getConfiguration().orientation;
int newOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
- if (current == android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
+ if (current == Configuration.ORIENTATION_LANDSCAPE) {
newOrientation = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("nuorientation", newOrientation);
editor.commit();
- requestOrientation(activity, prefs);
+ requestOrientation(activity, prefs, true);
return true;
}
})
@@ -596,15 +617,24 @@ public class MenuHelper {
}
static void requestOrientation(Activity activity, SharedPreferences prefs) {
+ requestOrientation(activity, prefs, false);
+ }
+
+ static private void requestOrientation(Activity activity, SharedPreferences prefs,
+ boolean ignoreIntentExtra) {
int req = prefs.getInt("nuorientation",
android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
// A little trick: use USER instead of UNSPECIFIED, so we ignore the
// orientation set by the activity below. It may have forced a landscape
// orientation, which the user has now cleared here.
- activity.setRequestedOrientation(
- req == android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- ? android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER
- : req);
+ if (req == android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
+ req = android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
+ }
+ if (! ignoreIntentExtra) {
+ Intent intent = activity.getIntent();
+ req = intent.getIntExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, req);
+ }
+ activity.setRequestedOrientation(req);
}
static void setFlipOrientationEnabled(Activity activity, MenuItem flipItem) {
@@ -628,13 +658,20 @@ public class MenuHelper {
return durationValue;
}
-
public static void showStorageToast(Activity activity) {
+ showStorageToast(activity, calculatePicturesRemaining());
+ }
+
+ public static void showStorageToast(Activity activity, int remaining) {
String noStorageText = null;
- int remaining = calculatePicturesRemaining();
if (remaining == MenuHelper.NO_STORAGE_ERROR) {
- noStorageText = activity.getString(R.string.no_storage);
+ String state = Environment.getExternalStorageState();
+ if (state == Environment.MEDIA_CHECKING) {
+ noStorageText = activity.getString(R.string.preparing_sd);
+ } else {
+ noStorageText = activity.getString(R.string.no_storage);
+ }
} else if (remaining < 1) {
noStorageText = activity.getString(R.string.not_enough_space);
}
diff --git a/src/com/android/camera/MovieView.java b/src/com/android/camera/MovieView.java
index b93336c..091cc28 100644
--- a/src/com/android/camera/MovieView.java
+++ b/src/com/android/camera/MovieView.java
@@ -50,6 +50,11 @@ public class MovieView extends Activity implements MediaPlayer.OnErrorListener,
private View mProgressView;
private boolean mFinishOnCompletion;
private Uri mUri;
+
+ // State maintained for proper onPause/OnResume behaviour.
+ private int mPositionWhenPaused = -1;
+ private boolean mWasPlayingWhenPaused = false;
+
public MovieView()
{
}
@@ -172,17 +177,42 @@ public class MovieView extends Activity implements MediaPlayer.OnErrorListener,
if ("content".equalsIgnoreCase(scheme)) {
ContentValues values = new ContentValues();
values.put(Video.VideoColumns.BOOKMARK, Integer.toString(bookmark));
- getContentResolver().update(mUri, values, null, null);
- }
+ try {
+ getContentResolver().update(mUri, values, null, null);
+ } catch (SecurityException ex) {
+ // Ignore, can happen if we try to set the bookmark on a read-only resource
+ // such as a video attached to GMail.
+ } catch (SQLiteException e) {
+ // ignore. can happen if the content doesn't support a bookmark column.
+ }
+ }
}
@Override
public void onPause() {
mHandler.removeCallbacksAndMessages(null);
setBookmark(mVideoView.getCurrentPosition());
+
+ mPositionWhenPaused = mVideoView.getCurrentPosition();
+ mWasPlayingWhenPaused = mVideoView.isPlaying();
+ mVideoView.stopPlayback();
+
super.onPause();
}
+ @Override
+ public void onResume() {
+ if (mPositionWhenPaused >= 0) {
+ mVideoView.setVideoURI(mUri);
+ mVideoView.seekTo(mPositionWhenPaused);
+ if (mWasPlayingWhenPaused) {
+ mVideoView.start();
+ }
+ }
+
+ super.onResume();
+ }
+
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
diff --git a/src/com/android/camera/SlideShow.java b/src/com/android/camera/SlideShow.java
index 2be99ac..23c7d4a 100644
--- a/src/com/android/camera/SlideShow.java
+++ b/src/com/android/camera/SlideShow.java
@@ -284,7 +284,7 @@ public class SlideShow extends Activity implements ViewSwitcher.ViewFactory
throw new UnsupportedOperationException();
}
- public void checkThumbnails(ThumbCheckCallback cb) {
+ public void checkThumbnails(ThumbCheckCallback cb, int totalThumbnails) {
// TODO Auto-generated method stub
}
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 4828b71..3474da6 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -20,11 +20,12 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import android.app.Activity;
import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -58,12 +59,14 @@ import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-public class VideoCamera extends Activity implements View.OnClickListener, SurfaceHolder.Callback {
+public class VideoCamera extends Activity implements View.OnClickListener,
+ ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback {
private static final String TAG = "videocamera";
@@ -119,8 +122,9 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
int mCurrentZoomIndex = 0;
- private ImageView mModeIndicatorView;
+ private ShutterButton mShutterButton;
private TextView mRecordingTimeView;
+ private boolean mHasSdCard;
ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>();
@@ -136,7 +140,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
switch (msg.what) {
case CLEAR_SCREEN_DELAY: {
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ clearScreenOnFlag();
break;
}
@@ -185,9 +189,11 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
// TODO put up a "please wait" message
// TODO also listen for the media scanner finished message
showStorageToast();
+ mHasSdCard = true;
} else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
// SD card unavailable
showStorageToast();
+ mHasSdCard = false;
} else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) {
Toast.makeText(VideoCamera.this, getResources().getString(R.string.wait), 5000);
} else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) {
@@ -215,9 +221,6 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
//setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
requestWindowFeature(Window.FEATURE_PROGRESS);
-
- Window win = getWindow();
- win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.video_camera);
mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
@@ -236,12 +239,13 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
mPostPictureAlert = findViewById(R.id.post_picture_panel);
int[] ids = new int[]{R.id.play, R.id.share, R.id.discard,
- R.id.cancel, R.id.attach, R.id.mode_indicator};
+ R.id.cancel, R.id.attach};
for (int id : ids) {
findViewById(id).setOnClickListener(this);
}
- mModeIndicatorView = (ImageView) findViewById(R.id.mode_indicator);
+ mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
+ mShutterButton.setOnShutterButtonListener(this);
mRecordingTimeView = (TextView) findViewById(R.id.recording_time);
mVideoFrame = (ImageView) findViewById(R.id.video_frame);
}
@@ -253,35 +257,13 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
super.onStart();
- final View hintView = findViewById(R.id.hint_toast);
- if (hintView != null)
- hintView.setVisibility(View.GONE);
-
Thread t = new Thread(new Runnable() {
public void run() {
final boolean storageOK = getAvailableStorage() >= LOW_STORAGE_THRESHOLD;
- if (hintView == null)
- return;
- if (storageOK) {
+ if (!storageOK) {
mHandler.post(new Runnable() {
public void run() {
- hintView.setVisibility(View.VISIBLE);
- }
- });
- mHandler.postDelayed(new Runnable() {
- public void run() {
- Animation a = new android.view.animation.AlphaAnimation(1F, 0F);
- a.setDuration(500);
- a.startNow();
- hintView.setAnimation(a);
- hintView.setVisibility(View.GONE);
- }
- }, 3000);
- } else {
- mHandler.post(new Runnable() {
- public void run() {
- hintView.setVisibility(View.GONE);
showStorageToast();
}
});
@@ -325,19 +307,29 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
doPlayCurrentVideo();
break;
}
+ }
+ }
- case R.id.mode_indicator:
- if (mMediaRecorderRecording) {
- stopVideoRecordingAndDisplayDialog();
- } else if (mVideoFrame.getVisibility() == View.VISIBLE) {
- doStartCaptureMode();
- } else {
- startVideoRecording();
+ public void onShutterButtonFocus(ShutterButton button, boolean pressed) {
+ switch (button.getId()) {
+ case R.id.shutter_button:
+ if (pressed) {
+ if (mMediaRecorderRecording) {
+ stopVideoRecordingAndDisplayDialog();
+ } else if (mVideoFrame.getVisibility() == View.VISIBLE) {
+ doStartCaptureMode();
+ } else {
+ startVideoRecording();
+ }
}
break;
}
}
+ public void onShutterButtonClick(ShutterButton button) {
+ // Do nothing (everything happens in onShutterButtonFocus).
+ }
+
private void doStartCaptureMode() {
if (isVideoCaptureIntent()) {
discardCurrentVideoAndStartPreview();
@@ -379,7 +371,8 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
Log.v(TAG, "onResume " + this.hashCode());
}
super.onResume();
- mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
+
+ setScreenTimeoutLong();
mPausing = false;
@@ -391,6 +384,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
intentFilter.addDataScheme("file");
registerReceiver(mReceiver, intentFilter);
mDidRegister = true;
+ mHasSdCard = ImageManager.hasStorage();
mBlackout.setVisibility(View.INVISIBLE);
if (mVideoFrameBitmap == null) {
@@ -406,7 +400,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
Log.v(TAG, "onStop " + this.hashCode());
}
stopVideoRecording();
- mHandler.removeMessages(CLEAR_SCREEN_DELAY);
+ setScreenTimeoutSystemDefault();
super.onStop();
}
@@ -427,12 +421,12 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
mDidRegister = false;
}
mBlackout.setVisibility(View.VISIBLE);
+ setScreenTimeoutSystemDefault();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ setScreenTimeoutLong();
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
@@ -445,19 +439,31 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
return true;
}
break;
- case KeyEvent.KEYCODE_FOCUS:
- return true;
case KeyEvent.KEYCODE_CAMERA:
- case KeyEvent.KEYCODE_DPAD_CENTER:
if (event.getRepeatCount() == 0) {
- if (!mMediaRecorderRecording) {
- startVideoRecording();
+ // If we get a dpad center event without any focused view, move the
+ // focus to the shutter button and press it.
+ if (mShutterButton.isInTouchMode()) {
+ mShutterButton.requestFocusFromTouch();
} else {
- stopVideoRecordingAndDisplayDialog();
+ mShutterButton.requestFocus();
}
+ mShutterButton.setPressed(true);
return true;
}
return true;
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (event.getRepeatCount() == 0) {
+ // If we get a dpad center event without any focused view, move the
+ // focus to the shutter button and press it.
+ if (mShutterButton.isInTouchMode()) {
+ mShutterButton.requestFocusFromTouch();
+ } else {
+ mShutterButton.requestFocus();
+ }
+ mShutterButton.setPressed(true);
+ }
+ break;
case KeyEvent.KEYCODE_MENU:
if (mMediaRecorderRecording) {
stopVideoRecordingAndDisplayDialog();
@@ -469,6 +475,16 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
return super.onKeyDown(keyCode, event);
}
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch(keyCode) {
+ case KeyEvent.KEYCODE_CAMERA:
+ mShutterButton.setPressed(false);
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
stopVideoRecording();
initializeVideo();
@@ -483,13 +499,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
void gotoGallery() {
- Uri target = Video.Media.INTERNAL_CONTENT_URI;
- Intent intent = new Intent(Intent.ACTION_VIEW, target);
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "Could not start gallery activity", e);
- }
+ MenuHelper.gotoCameraVideoGallery(this);
}
@Override
@@ -509,36 +519,41 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- addBaseMenuItems(menu);
- MenuHelper.addImageMenuItems(
- menu,
- MenuHelper.INCLUDE_ALL & ~MenuHelper.INCLUDE_ROTATE_MENU,
- false,
- VideoCamera.this,
- mHandler,
-
- // Handler for deletion
- new Runnable() {
- public void run() {
- // What do we do here?
- // mContentResolver.delete(uri, null, null);
- }
- },
- new MenuHelper.MenuInvoker() {
- public void run(final MenuHelper.MenuCallback cb) {
- }
- });
- MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM, MENU_SAVE_GALLERY_PHOTO, 0,
- R.string.camera_gallery_photos_text).setOnMenuItemClickListener(
- new MenuItem.OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- gotoGallery();
- return true;
- }
- });
- gallery.setIcon(android.R.drawable.ic_menu_gallery);
+ if (isVideoCaptureIntent()) {
+ // No options menu for attach mode.
+ return false;
+ } else {
+ addBaseMenuItems(menu);
+ MenuHelper.addImageMenuItems(
+ menu,
+ MenuHelper.INCLUDE_ALL & ~MenuHelper.INCLUDE_ROTATE_MENU,
+ false,
+ VideoCamera.this,
+ mHandler,
+
+ // Handler for deletion
+ new Runnable() {
+ public void run() {
+ // What do we do here?
+ // mContentResolver.delete(uri, null, null);
+ }
+ },
+ new MenuHelper.MenuInvoker() {
+ public void run(final MenuHelper.MenuCallback cb) {
+ }
+ });
+ MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM, MENU_SAVE_GALLERY_PHOTO, 0,
+ R.string.camera_gallery_photos_text).setOnMenuItemClickListener(
+ new MenuItem.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ gotoGallery();
+ return true;
+ }
+ });
+ gallery.setIcon(android.R.drawable.ic_menu_gallery);
+ }
return true;
}
@@ -731,7 +746,11 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
File cameraDir = new File(cameraDirPath);
cameraDir.mkdirs();
- String filename = cameraDirPath + "/" + Long.toString(dateTaken) + ".3gp";
+ SimpleDateFormat dateFormat = new SimpleDateFormat(
+ getString(R.string.video_file_name_format));
+ Date date = new Date(dateTaken);
+ String filepart = dateFormat.format(date);
+ String filename = cameraDirPath + "/" + filepart + ".3gp";
ContentValues values = new ContentValues(7);
values.put(Video.Media.TITLE, title);
values.put(Video.Media.DISPLAY_NAME, displayName);
@@ -809,11 +828,17 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
Log.v(TAG, "startVideoRecording");
if (!mMediaRecorderRecording) {
+ if (!mHasSdCard) {
+ Toast.makeText(this, getString(
+ R.string.no_storage), Toast.LENGTH_LONG).show();
+ Log.v(TAG, "No SD card, ignore start recording");
+ return;
+ }
+
// Check mMediaRecorder to see whether it is initialized or not.
if (mMediaRecorder == null) {
initializeVideo();
}
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
try {
mMediaRecorder.start(); // Recording is now started
} catch (RuntimeException e) {
@@ -826,6 +851,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
mRecordingTimeView.setText("");
mRecordingTimeView.setVisibility(View.VISIBLE);
mHandler.sendEmptyMessage(UPDATE_RECORD_TIME);
+ setScreenTimeoutInfinite();
}
}
@@ -833,7 +859,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
int drawableId = showRecording ? R.drawable.ic_camera_bar_indicator_record
: R.drawable.ic_camera_indicator_video;
Drawable drawable = getResources().getDrawable(drawableId);
- mModeIndicatorView.setImageDrawable(drawable);
+ mShutterButton.setImageDrawable(drawable);
}
private void stopVideoRecordingAndDisplayDialog() {
@@ -846,16 +872,33 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
private void showPostRecordingAlert() {
- boolean isPick = isVideoCaptureIntent();
- int pickVisible = isPick ? View.VISIBLE : View.GONE;
- int normalVisible = ! isPick ? View.VISIBLE : View.GONE;
- mPostPictureAlert.findViewById(R.id.share).setVisibility(normalVisible);
- mPostPictureAlert.findViewById(R.id.discard).setVisibility(normalVisible);
- mPostPictureAlert.findViewById(R.id.attach).setVisibility(pickVisible);
- mPostPictureAlert.findViewById(R.id.cancel).setVisibility(pickVisible);
+ int[] pickIds = {R.id.attach, R.id.cancel};
+ int[] normalIds = {R.id.share, R.id.discard};
+ int[] alwaysOnIds = {R.id.play};
+ int[] hideIds = pickIds;
+ int[] connectIds = normalIds;
+ if (isVideoCaptureIntent()) {
+ hideIds = normalIds;
+ connectIds = pickIds;
+ }
+ for(int id : hideIds) {
+ mPostPictureAlert.findViewById(id).setVisibility(View.GONE);
+ }
+ connectAndFadeIn(connectIds);
+ connectAndFadeIn(alwaysOnIds);
mPostPictureAlert.setVisibility(View.VISIBLE);
}
+ private void connectAndFadeIn(int[] connectIds) {
+ for(int id : connectIds) {
+ View view = mPostPictureAlert.findViewById(id);
+ view.setOnClickListener(this);
+ Animation animation = new AlphaAnimation(0F, 1F);
+ animation.setDuration(500);
+ view.setAnimation(animation);
+ }
+ }
+
private void hidePostPictureAlert() {
mPostPictureAlert.setVisibility(View.INVISIBLE);
}
@@ -878,14 +921,44 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
releaseMediaRecorder();
updateRecordingIndicator(false);
mRecordingTimeView.setVisibility(View.GONE);
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ setScreenTimeoutLong();
}
if (mNeedToRegisterRecording) {
registerVideo();
mNeedToRegisterRecording = false;
}
- if (mCameraVideoFilename != null){
- deleteVideoFile(mCameraVideoFilename);
+ mCameraVideoFilename = null;
+ }
+
+ private void setScreenTimeoutSystemDefault() {
+ mHandler.removeMessages(CLEAR_SCREEN_DELAY);
+ clearScreenOnFlag();
+ }
+
+ private void setScreenTimeoutLong() {
+ mHandler.removeMessages(CLEAR_SCREEN_DELAY);
+ setScreenOnFlag();
+ mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
+ }
+
+ private void setScreenTimeoutInfinite() {
+ mHandler.removeMessages(CLEAR_SCREEN_DELAY);
+ setScreenOnFlag();
+ }
+
+ private void clearScreenOnFlag() {
+ Window w = getWindow();
+ final int keepScreenOnFlag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ if ((w.getAttributes().flags & keepScreenOnFlag) != 0) {
+ w.clearFlags(keepScreenOnFlag);
+ }
+ }
+
+ private void setScreenOnFlag() {
+ Window w = getWindow();
+ final int keepScreenOnFlag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ if ((w.getAttributes().flags & keepScreenOnFlag) == 0) {
+ w.addFlags(keepScreenOnFlag);
}
}
@@ -897,7 +970,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
private void acquireAndShowVideoFrame() {
recycleVideoFrameBitmap();
- mVideoFrameBitmap = createVideoThumbnail(mCurrentVideoFilename);
+ mVideoFrameBitmap = ImageManager.createVideoThumbnail(mCurrentVideoFilename);
mVideoFrame.setImageBitmap(mVideoFrameBitmap);
mVideoFrame.setVisibility(View.VISIBLE);
}
@@ -914,19 +987,5 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
mVideoFrameBitmap = null;
}
}
-
- private Bitmap createVideoThumbnail(String filePath) {
- Bitmap bitmap = null;
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- try {
- retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
- retriever.setDataSource(filePath);
- bitmap = retriever.captureFrame();
- } finally {
- retriever.release();
- }
- return bitmap;
- }
-
}
diff --git a/src/com/android/camera/ViewImage.java b/src/com/android/camera/ViewImage.java
index 9760562..293f26b 100644
--- a/src/com/android/camera/ViewImage.java
+++ b/src/com/android/camera/ViewImage.java
@@ -16,8 +16,9 @@
package com.android.camera;
+import java.util.Random;
+
import android.app.Activity;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -28,12 +29,11 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.os.PowerManager;
+import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Config;
import android.util.Log;
-import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@@ -43,21 +43,17 @@ import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
-import android.view.animation.Animation;
import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;
-import android.widget.TextView;
import android.widget.Toast;
import android.widget.ZoomControls;
-import android.preference.PreferenceManager;
import com.android.camera.ImageManager.IImage;
-import java.util.Random;
-
public class ViewImage extends Activity implements View.OnClickListener
{
static final String TAG = "ViewImage";
@@ -86,6 +82,7 @@ public class ViewImage extends Activity implements View.OnClickListener
private boolean mFullScreenInNormalMode;
private boolean mShowActionIcons;
private View mActionIconPanel;
+ private View mShutterButton;
private boolean mSortAscending = false;
private int mSlideShowInterval;
@@ -100,7 +97,6 @@ public class ViewImage extends Activity implements View.OnClickListener
private Animation [] mSlideShowOutAnimation;
private SharedPreferences mPrefs;
- private MenuItem mFlipItem;
private View mNextImageView, mPrevImageView;
private Animation mHideNextImageViewAnimation = new AlphaAnimation(1F, 0F);
@@ -130,8 +126,9 @@ public class ViewImage extends Activity implements View.OnClickListener
private MenuHelper.MenuItemsResult mImageMenuRunnable;
- Runnable mDismissOnScreenControlsRunnable;
- ZoomControls mZoomControls;
+ private Runnable mDismissOnScreenControlsRunnable;
+ private ZoomControls mZoomControls;
+ private boolean mCameraReviewMode;
public ViewImage() {
}
@@ -176,7 +173,9 @@ public class ViewImage extends Activity implements View.OnClickListener
if (mZoomControls != null) {
if (mZoomControls.getVisibility() == View.GONE) {
mZoomControls.show();
- mZoomControls.requestFocus(); // this shouldn't be necessary
+ if (! mShowActionIcons) {
+ mZoomControls.requestFocus(); // this shouldn't be necessary
+ }
}
updateNextPrevControls();
scheduleDismissOnScreenControls();
@@ -210,21 +209,22 @@ public class ViewImage extends Activity implements View.OnClickListener
mDismissOnScreenControlsRunnable = new Runnable() {
public void run() {
mZoomControls.hide();
+ if (!mShowActionIcons) {
+ if (mNextImageView.getVisibility() == View.VISIBLE) {
+ Animation a = mHideNextImageViewAnimation;
+ a.setDuration(500);
+ a.startNow();
+ mNextImageView.setAnimation(a);
+ mNextImageView.setVisibility(View.INVISIBLE);
+ }
- if (mNextImageView.getVisibility() == View.VISIBLE) {
- Animation a = mHideNextImageViewAnimation;
- a.setDuration(500);
- a.startNow();
- mNextImageView.setAnimation(a);
- mNextImageView.setVisibility(View.INVISIBLE);
- }
-
- if (mPrevImageView.getVisibility() == View.VISIBLE) {
- Animation a = mHidePrevImageViewAnimation;
- a.setDuration(500);
- a.startNow();
- mPrevImageView.setAnimation(a);
- mPrevImageView.setVisibility(View.INVISIBLE);
+ if (mPrevImageView.getVisibility() == View.VISIBLE) {
+ Animation a = mHidePrevImageViewAnimation;
+ a.setDuration(500);
+ a.startNow();
+ mPrevImageView.setAnimation(a);
+ mPrevImageView.setVisibility(View.INVISIBLE);
+ }
}
}
};
@@ -251,12 +251,12 @@ public class ViewImage extends Activity implements View.OnClickListener
return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action));
}
- private static final boolean sDragLeftRight = false;
private static final boolean sUseBounce = false;
private static final boolean sAnimateTransitions = false;
static public class ImageViewTouch extends ImageViewTouchBase {
private ViewImage mViewImage;
+ private boolean mEnableTrackballScroll;
private static int TOUCH_STATE_REST = 0;
private static int TOUCH_STATE_LEFT_PRESS = 1;
@@ -277,6 +277,10 @@ public class ViewImage extends Activity implements View.OnClickListener
mViewImage = (ViewImage) context;
}
+ public void setEnableTrackballScroll(boolean enable) {
+ mEnableTrackballScroll = enable;
+ }
+
protected void postTranslate(float dx, float dy, boolean bounceOK) {
super.postTranslate(dx, dy);
if (dx != 0F || dy != 0F)
@@ -390,6 +394,14 @@ public class ViewImage extends Activity implements View.OnClickListener
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
+ // Don't respond to arrow keys if trackball scrolling is not enabled
+ if (!mEnableTrackballScroll) {
+ if ((keyCode >= KeyEvent.KEYCODE_DPAD_UP)
+ && (keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT)) {
+ return super.onKeyDown(keyCode, event);
+ }
+ }
+
int current = mViewImage.mCurrentPosition;
int nextImagePos = -2; // default no next image
@@ -557,7 +569,7 @@ public class ViewImage extends Activity implements View.OnClickListener
{
super.onCreateOptionsMenu(menu);
- if (true) {
+ if (! mCameraReviewMode) {
MenuItem item = menu.add(Menu.CATEGORY_SECONDARY, 203, 0, R.string.slide_show);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
@@ -570,8 +582,6 @@ public class ViewImage extends Activity implements View.OnClickListener
item.setIcon(android.R.drawable.ic_menu_slideshow);
}
- mFlipItem = MenuHelper.addFlipOrientation(menu, ViewImage.this, mPrefs);
-
final SelectedImageGetter selectedImageGetter = new SelectedImageGetter() {
public ImageManager.IImage getCurrentImage() {
return mAllImages.getImageAt(mCurrentPosition);
@@ -657,8 +667,6 @@ public class ViewImage extends Activity implements View.OnClickListener
mImageMenuRunnable.gettingReadyToOpen(menu, mAllImages.getImageAt(mCurrentPosition));
}
- MenuHelper.setFlipOrientationEnabled(this, mFlipItem);
-
menu.findItem(MenuHelper.MENU_IMAGE_SHARE).setEnabled(isCurrentImageShareable());
return true;
@@ -986,8 +994,10 @@ public class ViewImage extends Activity implements View.OnClickListener
ImageGetterCallback cb = new ImageGetterCallback() {
public void completed(boolean wasCanceled) {
- mImageViews[1].setFocusableInTouchMode(true);
- mImageViews[1].requestFocus();
+ if (!mShowActionIcons) {
+ mImageViews[1].setFocusableInTouchMode(true);
+ mImageViews[1].requestFocus();
+ }
}
public boolean wantsThumbnail(int pos, int offset) {
@@ -1037,6 +1047,11 @@ public class ViewImage extends Activity implements View.OnClickListener
public void onCreate(Bundle instanceState)
{
super.onCreate(instanceState);
+ Intent intent = getIntent();
+ mCameraReviewMode = intent.getBooleanExtra("com.android.camera.ReviewMode", false);
+ mFullScreenInNormalMode = intent.getBooleanExtra(MediaStore.EXTRA_FULL_SCREEN, true);
+ mShowActionIcons = intent.getBooleanExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, false);
+
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
@@ -1047,6 +1062,10 @@ public class ViewImage extends Activity implements View.OnClickListener
mImageViews[1] = (ImageViewTouch) findViewById(R.id.image2);
mImageViews[2] = (ImageViewTouch) findViewById(R.id.image3);
+ for(ImageViewTouch v : mImageViews) {
+ v.setEnableTrackballScroll(!mShowActionIcons);
+ }
+
mScroller = (ScrollHandler)findViewById(R.id.scroller);
makeGetter();
@@ -1066,16 +1085,16 @@ public class ViewImage extends Activity implements View.OnClickListener
mSlideShowImageViews[0] = (ImageViewTouch) findViewById(R.id.image1_slideShow);
mSlideShowImageViews[1] = (ImageViewTouch) findViewById(R.id.image2_slideShow);
- for (int i = 0; i < mSlideShowImageViews.length; i++) {
- mSlideShowImageViews[i].setImageBitmapResetBase(null, true, true);
- mSlideShowImageViews[i].setVisibility(View.INVISIBLE);
+ for (ImageViewTouch v : mSlideShowImageViews) {
+ v.setImageBitmapResetBase(null, true, true);
+ v.setVisibility(View.INVISIBLE);
+ v.setEnableTrackballScroll(!mShowActionIcons);
}
mActionIconPanel = findViewById(R.id.action_icon_panel);
{
int[] pickIds = {R.id.attach, R.id.cancel};
int[] normalIds = {R.id.gallery, R.id.setas, R.id.share, R.id.discard};
- int[] alwaysOnIds = {R.id.mode_indicator };
int[] hideIds = pickIds;
int[] connectIds = normalIds;
if (isPickIntent()) {
@@ -1083,15 +1102,18 @@ public class ViewImage extends Activity implements View.OnClickListener
connectIds = pickIds;
}
for(int id : hideIds) {
- findViewById(id).setVisibility(View.GONE);
+ mActionIconPanel.findViewById(id).setVisibility(View.GONE);
}
for(int id : connectIds) {
- findViewById(id).setOnClickListener(this);
- }
- for(int id : alwaysOnIds) {
- findViewById(id).setOnClickListener(this);
+ View view = mActionIconPanel.findViewById(id);
+ view.setOnClickListener(this);
+ Animation animation = new AlphaAnimation(0F, 1F);
+ animation.setDuration(500);
+ view.setAnimation(animation);
}
}
+ mShutterButton = findViewById(R.id.shutter_button);
+ mShutterButton.setOnClickListener(this);
Uri uri = getIntent().getData();
@@ -1107,10 +1129,6 @@ public class ViewImage extends Activity implements View.OnClickListener
return;
}
init(uri);
- mFullScreenInNormalMode = getIntent().getBooleanExtra(
- MediaStore.EXTRA_SHOW_ACTION_ICONS, false);
- mShowActionIcons = getIntent().getBooleanExtra(
- MediaStore.EXTRA_SHOW_ACTION_ICONS, false);
Bundle b = getIntent().getExtras();
@@ -1124,6 +1142,7 @@ public class ViewImage extends Activity implements View.OnClickListener
}
if (mShowActionIcons) {
mActionIconPanel.setVisibility(View.VISIBLE);
+ mShutterButton.setVisibility(View.VISIBLE);
}
}
@@ -1140,6 +1159,12 @@ public class ViewImage extends Activity implements View.OnClickListener
mNextImageView = findViewById(R.id.next_image);
mPrevImageView = findViewById(R.id.prev_image);
+ if (mShowActionIcons) {
+ mNextImageView.setOnClickListener(this);
+ mNextImageView.setFocusable(true);
+ mPrevImageView.setOnClickListener(this);
+ mPrevImageView.setFocusable(true);
+ }
setOrientation();
}
@@ -1186,6 +1211,7 @@ public class ViewImage extends Activity implements View.OnClickListener
ivt.clear();
}
mActionIconPanel.setVisibility(View.GONE);
+ mShutterButton.setVisibility(View.GONE);
if (false) {
Log.v(TAG, "current is " + this.mSlideShowImageCurrent);
@@ -1237,6 +1263,7 @@ public class ViewImage extends Activity implements View.OnClickListener
}
if (mShowActionIcons) {
mActionIconPanel.setVisibility(View.VISIBLE);
+ mShutterButton.setVisibility(View.VISIBLE);
}
ImageViewTouchBase dst = mImageViews[1];
@@ -1381,12 +1408,21 @@ public class ViewImage extends Activity implements View.OnClickListener
mGetter = new ImageGetter();
}
- private void init(Uri uri) {
+ private boolean desiredSortOrder() {
String sortOrder = mPrefs.getString("pref_gallery_sort_key", null);
- mSortAscending = false;
+ boolean sortAscending = false;
if (sortOrder != null) {
- mSortAscending = sortOrder.equals("ascending");
+ sortAscending = sortOrder.equals("ascending");
}
+ if (mCameraReviewMode) {
+ // Force left-arrow older pictures, right-arrow newer pictures.
+ sortAscending = true;
+ }
+ return sortAscending;
+ }
+
+ private void init(Uri uri) {
+ mSortAscending = desiredSortOrder();
int sort = mSortAscending ? ImageManager.SORT_ASCENDING : ImageManager.SORT_DESCENDING;
mAllImages = ImageManager.makeImageList(uri, this, sort);
@@ -1436,12 +1472,7 @@ public class ViewImage extends Activity implements View.OnClickListener
ImageManager.IImage image = mAllImages.getImageAt(mCurrentPosition);
- String sortOrder = mPrefs.getString("pref_gallery_sort_key", null);
- boolean sortAscending = false;
- if (sortOrder != null) {
- sortAscending = sortOrder.equals("ascending");
- }
- if (sortAscending != mSortAscending) {
+ if (desiredSortOrder() != mSortAscending) {
init(image.fullSizeImageUri());
}
@@ -1496,8 +1527,12 @@ public class ViewImage extends Activity implements View.OnClickListener
public void onClick(View v) {
switch (v.getId()) {
- case R.id.mode_indicator: {
- MenuHelper.gotoStillImageCapture(this);
+ case R.id.shutter_button: {
+ if (mCameraReviewMode) {
+ finish();
+ } else {
+ MenuHelper.gotoStillImageCapture(this);
+ }
}
break;
@@ -1507,7 +1542,11 @@ public class ViewImage extends Activity implements View.OnClickListener
break;
case R.id.discard: {
- MenuHelper.displayDeleteDialog(this, mDeletePhotoRunnable, true);
+ if (mCameraReviewMode) {
+ mDeletePhotoRunnable.run();
+ } else {
+ MenuHelper.deletePhoto(this, mDeletePhotoRunnable);
+ }
}
break;
@@ -1535,6 +1574,23 @@ public class ViewImage extends Activity implements View.OnClickListener
}
}
break;
+
+ case R.id.next_image: {
+ moveNextOrPrevious(1);
+ }
+ break;
+
+ case R.id.prev_image: {
+ moveNextOrPrevious(-1);
+ }
+ break;
+ }
+ }
+
+ private void moveNextOrPrevious(int delta) {
+ int nextImagePos = mCurrentPosition + delta;
+ if ((0 <= nextImagePos) && (nextImagePos < mAllImages.getCount())) {
+ setImage(nextImagePos);
}
}
}