summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/Camera.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/camera/Camera.java')
-rw-r--r--src/com/android/camera/Camera.java215
1 files changed, 156 insertions, 59 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 079528b..9bf101c 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -16,7 +16,12 @@
package com.android.camera;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -68,12 +73,13 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.OrientationListener;
+import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -81,8 +87,6 @@ import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;
-import com.android.camera.ImageManager.IImageList;
-
public class Camera extends Activity implements View.OnClickListener,
ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback {
@@ -117,8 +121,8 @@ public class Camera extends Activity implements View.OnClickListener,
public static final int MENU_SAVE_CAMERA_VIDEO_DONE = 37;
private Toast mToast;
- private OrientationListener mOrientationListener;
- private int mLastOrientation = OrientationListener.ORIENTATION_UNKNOWN;
+ private OrientationEventListener mOrientationListener;
+ private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
private SharedPreferences mPreferences;
private static final int IDLE = 1;
@@ -132,7 +136,7 @@ public class Camera extends Activity implements View.OnClickListener,
private android.hardware.Camera.Parameters mParameters;
private VideoPreview mSurfaceView;
private SurfaceHolder mSurfaceHolder = null;
- private ImageView mBlackout = null;
+ private View mBlackout = null;
private int mOriginalViewFinderWidth, mOriginalViewFinderHeight;
private int mViewFinderWidth, mViewFinderHeight;
@@ -165,6 +169,7 @@ public class Camera extends Activity implements View.OnClickListener,
private Drawable[] mThumbnails;
private boolean mShouldTransitionThumbnails;
private Uri mLastPictureUri;
+ private Bitmap mLastPictureThumb;
private LocationManager mLocationManager = null;
private ShutterButton mShutterButton;
@@ -182,6 +187,7 @@ public class Camera extends Activity implements View.OnClickListener,
private boolean mKeepAndRestartPreview;
+ // mPostCaptureAlert is non-null only if isImageCaptureIntent() is true.
private View mPostCaptureAlert;
@@ -257,18 +263,16 @@ public class Camera extends Activity implements View.OnClickListener,
String action = intent.getAction();
if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
// SD card available
- // TODO put up a "please wait" message
- // TODO also listen for the media scanner finished message
- showStorageToast();
+ updateStorageHint();
} else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) ||
action.equals(Intent.ACTION_MEDIA_CHECKING)) {
// SD card unavailable
mPicturesRemaining = MenuHelper.NO_STORAGE_ERROR;
- showStorageToast(mPicturesRemaining);
+ updateStorageHint(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)) {
- showStorageToast();
+ updateStorageHint();
}
}
};
@@ -321,7 +325,6 @@ public class Camera extends Activity implements View.OnClickListener,
Log.v(TAG, "********** Total shutter lag " + (now - mShutterPressTime) + " ms");
}
if (mClickSound != null) {
- mClickSound.seekTo(0);
mClickSound.start();
}
}
@@ -450,17 +453,18 @@ public class Camera extends Activity implements View.OnClickListener,
startTiming();
}
long dateTaken = System.currentTimeMillis();
+ String name = createName(dateTaken) + ".jpg";
mLastContentUri = ImageManager.instance().addImage(
Camera.this,
mContentResolver,
- createName(dateTaken),
+ name,
"",
dateTaken,
// location for the database goes here
loc,
0, // the dsp will use the right orientation so don't "double set it"
ImageManager.CAMERA_IMAGE_BUCKET_NAME,
- null);
+ name);
if (mLastContentUri == null) {
// this means we got an error
@@ -626,6 +630,10 @@ public class Camera extends Activity implements View.OnClickListener,
mCameraDevice.setParameters(mParameters);
mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, new JpegPictureCallback(loc));
+ // Prepare the sound to play in shutter callback.
+ if (mClickSound != null) {
+ mClickSound.seekTo(0);
+ }
mBlackout.setVisibility(View.VISIBLE);
// Comment this out for now until we can decode the preview frame. This currently
@@ -652,7 +660,7 @@ public class Camera extends Activity implements View.OnClickListener,
// cached value which was calculated when the preview was restarted.
if (DEBUG_TIME_OPERATIONS) mShutterPressTime = System.currentTimeMillis();
if (mPicturesRemaining < 1) {
- showStorageToast(mPicturesRemaining);
+ updateStorageHint(mPicturesRemaining);
return;
}
@@ -713,6 +721,7 @@ public class Camera extends Activity implements View.OnClickListener,
if (mLastPictureButton.getVisibility() != View.VISIBLE) {
mShouldShowLastPictureButton = true;
}
+ mLastPictureThumb = lastPictureThumb;
mLastPictureUri = uri;
}
@@ -759,12 +768,21 @@ public class Camera extends Activity implements View.OnClickListener,
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ // To reduce startup time, we open camera device in another thread.
+ // We make sure the camera is opened at the end of onCreate.
+ Thread openCameraThread = new Thread(new Runnable() {
+ public void run() {
+ mCameraDevice = android.hardware.Camera.open();
+ }
+ });
+ openCameraThread.start();
+
// To reduce startup time, we run some service creation code in another thread.
// We make sure the services are loaded at the end of onCreate().
Thread loadServiceThread = new Thread(new Runnable() {
public void run() {
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
- mOrientationListener = new OrientationListener(Camera.this) {
+ mOrientationListener = new OrientationEventListener(Camera.this) {
public void onOrientationChanged(int orientation) {
mLastOrientation = orientation;
}
@@ -776,9 +794,6 @@ public class Camera extends Activity implements View.OnClickListener,
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
mContentResolver = getContentResolver();
- //setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
- requestWindowFeature(Window.FEATURE_PROGRESS);
-
Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.camera);
@@ -792,28 +807,12 @@ public class Camera extends Activity implements View.OnClickListener,
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- mBlackout = (ImageView) findViewById(R.id.blackout);
- mBlackout.setBackgroundDrawable(new ColorDrawable(0xFF000000));
+ mBlackout = findViewById(R.id.blackout);
- mLastPictureButton = (ImageView) findViewById(R.id.last_picture_button);
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 = (ImageView) findViewById(R.id.last_picture_button);
mLastPictureButton.setOnClickListener(this);
- if (lastPicture == null) {
- mLastPictureButton.setVisibility(View.GONE);
- } else {
- Bitmap miniThumb = lastPicture.miniThumbBitmap();
- setLastPictureThumb(miniThumb, lastPicture.fullSizeImageUri());
- }
- images.deactivate();
+ loadLastThumb();
}
mShutterButton = (ShutterButton) findViewById(R.id.shutter_button);
@@ -840,10 +839,17 @@ public class Camera extends Activity implements View.OnClickListener,
mFocusBlinkAnimation.setRepeatCount(Animation.INFINITE);
mFocusBlinkAnimation.setRepeatMode(Animation.REVERSE);
- mPostCaptureAlert = findViewById(R.id.post_picture_panel);
+ // We load the post_picture_panel layout only if it is needed.
+ if (isImageCaptureIntent()) {
+ ViewGroup cameraView = (ViewGroup)findViewById(R.id.camera);
+ getLayoutInflater().inflate(R.layout.post_picture_panel,
+ cameraView);
+ mPostCaptureAlert = findViewById(R.id.post_picture_panel);
+ }
// Make sure the services are loaded.
try {
+ openCameraThread.join();
loadServiceThread.join();
} catch (InterruptedException ex) {
}
@@ -860,7 +866,7 @@ public class Camera extends Activity implements View.OnClickListener,
if (!storageOK) {
mHandler.post(new Runnable() {
public void run() {
- showStorageToast(mPicturesRemaining);
+ updateStorageHint(mPicturesRemaining);
}
});
}
@@ -1005,12 +1011,37 @@ public class Camera extends Activity implements View.OnClickListener,
}
}
- private void showStorageToast() {
- MenuHelper.showStorageToast(this);
+ private void updateStorageHint() {
+ updateStorageHint(MenuHelper.calculatePicturesRemaining());
}
- private void showStorageToast(int remainingPictures) {
- MenuHelper.showStorageToast(this, remainingPictures);
+ private OnScreenHint mStorageHint;
+
+ private void updateStorageHint(int remaining) {
+ String noStorageText = null;
+
+ if (remaining == MenuHelper.NO_STORAGE_ERROR) {
+ String state = Environment.getExternalStorageState();
+ if (state == Environment.MEDIA_CHECKING) {
+ noStorageText = getString(R.string.preparing_sd);
+ } else {
+ noStorageText = getString(R.string.no_storage);
+ }
+ } else if (remaining < 1) {
+ noStorageText = getString(R.string.not_enough_space);
+ }
+
+ if (noStorageText != null) {
+ if (mStorageHint == null) {
+ mStorageHint = OnScreenHint.makeText(this, noStorageText);
+ } else {
+ mStorageHint.setText(noStorageText);
+ }
+ mStorageHint.show();
+ } else if (mStorageHint != null) {
+ mStorageHint.cancel();
+ mStorageHint = null;
+ }
}
@Override
@@ -1048,20 +1079,78 @@ public class Camera extends Activity implements View.OnClickListener,
}
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.GONE);
+ private ImageManager.DataLocation dataLocation() {
+ return ImageManager.DataLocation.EXTERNAL;
+ }
+
+ private static final int BUFSIZE = 4096;
+
+ // Stores the thumbnail and URI of last-picture-taken to SD card, so we can
+ // load it the next time the Camera app starts.
+ private void storeLastThumb() {
+ if (mLastPictureUri != null && mLastPictureThumb != null) {
+ try {
+ FileOutputStream f = new FileOutputStream(ImageManager.getLastThumbPath());
+ try {
+ BufferedOutputStream b = new BufferedOutputStream(f, BUFSIZE);
+ try {
+ DataOutputStream d = new DataOutputStream(b);
+ try {
+ d.writeUTF(mLastPictureUri.toString());
+ mLastPictureThumb.compress(Bitmap.CompressFormat.PNG, 100, d);
+ } finally {
+ d.close();
+ b = null;
+ f = null;
+ }
+ } finally {
+ if (b != null) {
+ b.close();
+ f = null;
+ }
+ }
+ } finally {
+ if (f != null) {
+ f.close();
+ }
+ }
+ } catch (IOException e) {
}
- list.deactivate();
}
}
- private ImageManager.DataLocation dataLocation() {
- return ImageManager.DataLocation.EXTERNAL;
+ // Loads the thumbnail and URI of last-picture-taken from SD card.
+ private void loadLastThumb() {
+ try {
+ FileInputStream f = new FileInputStream(ImageManager.getLastThumbPath());
+ try {
+ BufferedInputStream b = new BufferedInputStream(f, BUFSIZE);
+ try {
+ DataInputStream d = new DataInputStream(b);
+ try {
+ Uri lastUri = Uri.parse(d.readUTF());
+ Bitmap lastThumb = BitmapFactory.decodeStream(d);
+ setLastPictureThumb(lastThumb, lastUri);
+ } finally {
+ d.close();
+ b = null;
+ f = null;
+ }
+ } finally {
+ if (b != null) {
+ b.close();
+ f = null;
+ }
+ }
+ } finally {
+ if (f != null) {
+ f.close();
+ }
+ }
+ } catch (IOException e) {
+ }
}
@Override
@@ -1096,6 +1185,11 @@ public class Camera extends Activity implements View.OnClickListener,
mFocusToneGenerator = null;
}
+ storeLastThumb();
+ if (mStorageHint != null) {
+ mStorageHint.cancel();
+ mStorageHint = null;
+ }
super.onPause();
}
@@ -1184,6 +1278,9 @@ public class Camera extends Activity implements View.OnClickListener,
// 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) {
+ // Start auto-focus immediately to reduce shutter lag. After the shutter button
+ // gets the focus, doFocus() will be called again but it is fine.
+ doFocus(true);
if (mShutterButton.isInTouchMode()) {
mShutterButton.requestFocusFromTouch();
} else {
@@ -1299,7 +1396,7 @@ public class Camera extends Activity implements View.OnClickListener,
Animation a = mShowLastPictureButtonAnimation;
a.setDuration(500);
mLastPictureButton.setAnimation(a);
- }
+ }
if (mShouldTransitionThumbnails) {
mShouldTransitionThumbnails = false;
@@ -1606,10 +1703,8 @@ public class Camera extends Activity implements View.OnClickListener,
}
private void showPostCaptureAlert() {
- boolean isPick = isImageCaptureIntent();
- int pickVisible = isPick ? View.VISIBLE : View.GONE;
- mPostCaptureAlert.setVisibility(pickVisible);
- if (isPick) {
+ if (isImageCaptureIntent()) {
+ mPostCaptureAlert.setVisibility(View.VISIBLE);
int[] pickIds = {R.id.attach, R.id.cancel};
for(int id : pickIds) {
View view = mPostCaptureAlert.findViewById(id);
@@ -1622,7 +1717,9 @@ public class Camera extends Activity implements View.OnClickListener,
}
private void hidePostCaptureAlert() {
- mPostCaptureAlert.setVisibility(View.GONE);
+ if (isImageCaptureIntent()) {
+ mPostCaptureAlert.setVisibility(View.INVISIBLE);
+ }
}
@Override