summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:25 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:25 -0800
commitb97ccf3f20bee44daf70f10966809e39e30ab4f7 (patch)
treefb6c421cd04ffed74e50cd62e4fdab34d5a9f448 /src/com/android/camera
parent0eaec58e292ce4eaa6baadecf643f0f65e48d278 (diff)
downloadLegacyCamera-b97ccf3f20bee44daf70f10966809e39e30ab4f7.zip
LegacyCamera-b97ccf3f20bee44daf70f10966809e39e30ab4f7.tar.gz
LegacyCamera-b97ccf3f20bee44daf70f10966809e39e30ab4f7.tar.bz2
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'src/com/android/camera')
-rw-r--r--src/com/android/camera/Camera.java215
-rw-r--r--src/com/android/camera/CameraSettings.java59
-rw-r--r--src/com/android/camera/GalleryPicker.java7
-rw-r--r--src/com/android/camera/GalleryPickerItem.java1
-rw-r--r--src/com/android/camera/GallerySettings.java13
-rw-r--r--src/com/android/camera/ImageGallery2.java70
-rwxr-xr-xsrc/com/android/camera/ImageManager.java80
-rw-r--r--src/com/android/camera/MenuHelper.java192
-rw-r--r--src/com/android/camera/VideoCamera.java252
-rw-r--r--src/com/android/camera/ViewImage.java102
-rw-r--r--src/com/android/camera/Wallpaper.java24
11 files changed, 697 insertions, 318 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index b79e7d1..993e15c 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -25,19 +25,22 @@ import java.util.ArrayList;
import android.app.Activity;
import android.app.ProgressDialog;
-import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.location.Location;
@@ -65,17 +68,18 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.OrientationListener;
import android.view.SurfaceHolder;
-import android.view.SurfaceView;
import android.view.View;
-import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
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, SurfaceHolder.Callback {
private static final String TAG = "camera";
@@ -88,7 +92,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
private static final int CLEAR_SCREEN_DELAY = 4;
private static final int SCREEN_DELAY = 2 * 60 * 1000;
- private static final int POST_PICTURE_ALERT_TIMEOUT = 6 * 1000;
private static final int FOCUS_BEEP_VOLUME = 100;
private static final int NO_STORAGE_ERROR = -1;
@@ -105,8 +108,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
public static final int MENU_GALLERY_VIDEOS = 8;
public static final int MENU_SAVE_SELECT_PHOTOS = 30;
public static final int MENU_SAVE_NEW_PHOTO = 31;
- public static final int MENU_SAVE_SELECTVIDEO = 32;
- public static final int MENU_SAVE_TAKE_NEW_VIDEO = 33;
public static final int MENU_SAVE_GALLERY_PHOTO = 34;
public static final int MENU_SAVE_GALLERY_VIDEO_PHOTO = 35;
public static final int MENU_SAVE_CAMERA_DONE = 36;
@@ -154,7 +155,8 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
boolean mMenuSelectionMade;
- View mPostPictureAlert;
+ ImageView mLastPictureButton;
+ Uri mLastPictureUri;
LocationManager mLocationManager = null;
private Animation mFocusBlinkAnimation;
@@ -216,7 +218,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
// TODO remove polling
mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, 100);
} else if (mStatus == SNAPSHOT_COMPLETED){
- hidePostPictureAlert();
mCaptureObject.dismissFreezeFrame(true);
}
break;
@@ -316,9 +317,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
Log.v(TAG, "got RawPictureCallback...");
mRawPictureCallbackTime = System.currentTimeMillis();
mBlackout.setVisibility(View.INVISIBLE);
- if (!isPickIntent() && mPreferences.getBoolean("pref_camera_postpicturemenu_key", true)) {
- showPostPictureAlert();
- }
}
};
@@ -337,23 +335,10 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
mStatus = SNAPSHOT_COMPLETED;
- if (!mPreferences.getBoolean("pref_camera_postpicturemenu_key", true)) {
- if (mKeepAndRestartPreview) {
- long delay = 1500 - (System.currentTimeMillis() - mRawPictureCallbackTime);
- mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, Math.max(delay, 0));
- }
- return;
- }
-
if (mKeepAndRestartPreview) {
- mKeepAndRestartPreview = false;
- mPostPictureAlert.setVisibility(View.INVISIBLE);
-
- // Post this message so that we can finish processing the request. This also
- // prevents the preview from showing up before mPostPictureAlert is dismissed.
- mHandler.sendEmptyMessage(RESTART_PREVIEW);
+ long delay = 1500 - (System.currentTimeMillis() - mRawPictureCallbackTime);
+ mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, Math.max(delay, 0));
}
-
}
};
@@ -489,6 +474,8 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
if (!captureOnly) {
storeImage(data, loc);
sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", mLastContentUri));
+ setLastPictureThumb(data);
+ dismissFreezeFrame(true);
} else {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
@@ -517,6 +504,46 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
}
}
+ 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.
@@ -619,7 +646,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
mKeepAndRestartPreview = true;
mHandler.sendEmptyMessage(RESTART_PREVIEW);
- mPostPictureAlert.setVisibility(View.INVISIBLE);
return;
}
@@ -633,7 +659,7 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
mStatus = SNAPSHOT_IN_PROGRESS;
- mKeepAndRestartPreview = !mPreferences.getBoolean("pref_camera_postpicturemenu_key", true);
+ mKeepAndRestartPreview = true;
boolean getContentAction = isPickIntent();
if (getContentAction) {
@@ -712,17 +738,9 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
mBlackout = (ImageView) findViewById(R.id.blackout);
mBlackout.setBackgroundDrawable(new ColorDrawable(0xFF000000));
- mPostPictureAlert = findViewById(R.id.post_picture_panel);
- View b;
-
- b = findViewById(R.id.discard);
- b.setOnClickListener(this);
-
- b = findViewById(R.id.share);
- b.setOnClickListener(this);
-
- b = findViewById(R.id.setas);
- b.setOnClickListener(this);
+ mLastPictureButton = (ImageView) findViewById(R.id.last_picture_button);
+ mLastPictureButton.setOnClickListener(this);
+ mLastPictureButton.setVisibility(View.INVISIBLE);
try {
mClickSound = new MediaPlayer();
@@ -796,59 +814,9 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
public void onClick(View v) {
switch (v.getId()) {
- /*
- case R.id.save: {
- mPostPictureAlert.setVisibility(View.GONE);
- postAfterKeep(null);
- break;
- }
- */
- case R.id.discard: {
- if (mCaptureObject != null) {
- mCaptureObject.cancelSave();
- Uri uri = mCaptureObject.getLastCaptureUri();
- if (uri != null) {
- mContentResolver.delete(uri, null, null);
- }
- mCaptureObject.dismissFreezeFrame(true);
- }
- mPostPictureAlert.setVisibility(View.GONE);
- break;
- }
-
- case R.id.share: {
- mPostPictureAlert.setVisibility(View.GONE);
- postAfterKeep(new Runnable() {
- public void run() {
- Uri u = mCaptureObject.getLastCaptureUri();
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_SEND);
- intent.setType("image/jpeg");
- intent.putExtra(Intent.EXTRA_STREAM, u);
- try {
- startActivity(Intent.createChooser(intent, getText(R.string.sendImage)));
- } catch (android.content.ActivityNotFoundException ex) {
- Toast.makeText(Camera.this, R.string.no_way_to_share_image, Toast.LENGTH_SHORT).show();
- }
- }
- });
- break;
- }
-
- case R.id.setas: {
- mPostPictureAlert.setVisibility(View.GONE);
- postAfterKeep(new Runnable() {
- public void run() {
- Uri u = mCaptureObject.getLastCaptureUri();
- Intent intent = new Intent(Intent.ACTION_ATTACH_DATA, u);
- try {
- startActivity(Intent.createChooser(intent, getText(R.string.setImage)));
- } catch (android.content.ActivityNotFoundException ex) {
- Toast.makeText(Camera.this, R.string.no_way_to_share_video, Toast.LENGTH_SHORT).show();
- }
- }
- });
+ case R.id.last_picture_button: {
+ viewLastImage();
break;
}
}
@@ -903,6 +871,16 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
}
mBlackout.setVisibility(View.INVISIBLE);
+
+ if (mLastPictureUri != null) {
+ IImageList list = ImageManager.makeImageList(mLastPictureUri, this,
+ ImageManager.SORT_ASCENDING);
+ if (list.getImageForUri(mLastPictureUri) == null) {
+ mLastPictureUri = null;
+ mLastPictureButton.setVisibility(View.INVISIBLE);
+ }
+ list.deactivate();
+ }
}
private ImageManager.DataLocation dataLocation() {
@@ -921,7 +899,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
@Override
protected void onPause() {
keep();
- mPostPictureAlert.setVisibility(View.INVISIBLE);
mPausing = true;
mOrientationListener.disable();
@@ -1012,11 +989,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mStatus == SNAPSHOT_IN_PROGRESS || mStatus == SNAPSHOT_COMPLETED) {
- if (mPostPictureAlert.getVisibility() == View.VISIBLE) {
- keep();
- mPostPictureAlert.setVisibility(View.INVISIBLE);
- restartPreview();
- }
// ignore backs while we're taking a picture
return true;
}
@@ -1058,9 +1030,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
}
}
return true;
- case KeyEvent.KEYCODE_MENU:
- mPostPictureAlert.setVisibility(View.INVISIBLE);
- break;
}
return super.onKeyDown(keyCode, event);
@@ -1260,12 +1229,30 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
}
void gotoGallery() {
- Uri target = Images.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.gotoCameraImageGallery(this);
+ }
+
+ private void viewLastImage() {
+ Uri targetUri = mLastPictureUri;
+ if (targetUri != null) {
+ Uri thisUri = Images.Media.INTERNAL_CONTENT_URI;
+ if (thisUri != null) {
+ String bucket = thisUri.getQueryParameter("bucketId");
+ if (bucket != null) {
+ targetUri = targetUri.buildUpon().appendQueryParameter("bucketId", bucket).build();
+ }
+ }
+ Intent intent = new Intent(Intent.ACTION_VIEW, targetUri);
+ intent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ intent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true);
+ intent.putExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, true);
+
+ try {
+ startActivity(intent);
+ } catch (android.content.ActivityNotFoundException ex) {
+ // ignore.
+ }
}
}
@@ -1523,12 +1510,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
return true;
}
});
- menu.add(MenuHelper.VIDEO_SAVING_ITEM, MENU_SAVE_TAKE_NEW_VIDEO, 0, R.string.camera_takenewvideo).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- toss();
- return true;
- }
- });
} else {
addBaseMenuItems(menu);
MenuHelper.addImageMenuItems(
@@ -1642,16 +1623,6 @@ public class Camera extends Activity implements View.OnClickListener, SurfaceHol
item.setIcon(android.R.drawable.ic_menu_preferences);
}
- private void showPostPictureAlert() {
- mPostPictureAlert.setVisibility(View.VISIBLE);
- mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, POST_PICTURE_ALERT_TIMEOUT);
- }
-
- private void hidePostPictureAlert() {
- cancelRestartPreviewTimeout();
- mPostPictureAlert.setVisibility(View.INVISIBLE);
- }
-
private void cancelRestartPreviewTimeout() {
mHandler.removeMessages(RESTART_PREVIEW);
}
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index 0c0f31b..0145d64 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -16,28 +16,77 @@
package com.android.camera;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
+import android.preference.ListPreference;
import android.preference.PreferenceActivity;
/**
* CameraSettings
*/
public class CameraSettings extends PreferenceActivity
+ implements OnSharedPreferenceChangeListener
{
+ public static final String KEY_VIDEO_QUALITY = "pref_camera_videoquality_key";
+ public static final boolean DEFAULT_VIDEO_QUALITY_VALUE = true;
+
+ private ListPreference mVideoQuality;
+
public CameraSettings()
{
}
- protected int resourceId() {
- return R.xml.camera_preferences;
- }
-
/** Called with the activity is first created. */
@Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
- addPreferencesFromResource(resourceId());
+ addPreferencesFromResource(R.xml.camera_preferences);
+
+ initUI();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ updateVideoQuality();
+ }
+
+ private void initUI() {
+ mVideoQuality = (ListPreference) findPreference(KEY_VIDEO_QUALITY);
+ getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
+ }
+
+ private void updateVideoQuality() {
+ boolean vidQualityValue = getBooleanPreference(mVideoQuality, DEFAULT_VIDEO_QUALITY_VALUE);
+ int vidQualityIndex = vidQualityValue ? 1 : 0;
+ String[] vidQualities =
+ getResources().getStringArray(R.array.pref_camera_videoquality_entries);
+ String vidQuality = vidQualities[vidQualityIndex];
+ mVideoQuality.setSummary(vidQuality);
+ }
+
+ private static int getIntPreference(ListPreference preference, int defaultValue) {
+ String s = preference.getValue();
+ int result = defaultValue;
+ try {
+ result = Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ // Ignore, result is already the default value.
+ }
+ return result;
+ }
+
+ private boolean getBooleanPreference(ListPreference preference, boolean defaultValue) {
+ return getIntPreference(preference, defaultValue ? 1 : 0) != 0;
+ }
+
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.equals(KEY_VIDEO_QUALITY)) {
+ updateVideoQuality();
+ }
}
}
diff --git a/src/com/android/camera/GalleryPicker.java b/src/com/android/camera/GalleryPicker.java
index da946a0..df9049f 100644
--- a/src/com/android/camera/GalleryPicker.java
+++ b/src/com/android/camera/GalleryPicker.java
@@ -315,6 +315,9 @@ public class GalleryPicker extends Activity {
String cameraBucketId = null;
for (Map.Entry<String, String> entry: hashMap.entrySet()) {
String key = entry.getKey();
+ if (key == null) {
+ continue;
+ }
if (key.equals(cameraItem)) {
cameraBucketId = key;
} else {
@@ -651,9 +654,7 @@ public class GalleryPicker extends Activity {
@Override
public boolean onPrepareOptionsMenu(android.view.Menu menu) {
- int keyboard = getResources().getConfiguration().keyboardHidden;
- mFlipItem.setEnabled(keyboard == android.content.res.Configuration.KEYBOARDHIDDEN_YES);
-
+ MenuHelper.setFlipOrientationEnabled(this, mFlipItem);
return true;
}
diff --git a/src/com/android/camera/GalleryPickerItem.java b/src/com/android/camera/GalleryPickerItem.java
index 3fc9678..c3b5df1 100644
--- a/src/com/android/camera/GalleryPickerItem.java
+++ b/src/com/android/camera/GalleryPickerItem.java
@@ -41,6 +41,7 @@ public class GalleryPickerItem extends ImageView {
super(context, attrs, defStyle);
mFrame = getResources().getDrawable(R.drawable.frame_gallery_preview);
+ mFrame.setCallback(this);
}
@Override
diff --git a/src/com/android/camera/GallerySettings.java b/src/com/android/camera/GallerySettings.java
index 8cbeba2..14cff3a 100644
--- a/src/com/android/camera/GallerySettings.java
+++ b/src/com/android/camera/GallerySettings.java
@@ -16,31 +16,24 @@
package com.android.camera;
-import android.content.SharedPreferences;
import android.os.Bundle;
-import android.preference.Preference;
import android.preference.PreferenceActivity;
-import android.content.Context;
/**
* GallerySettings
*/
-public class GallerySettings extends CameraSettings
+public class GallerySettings extends PreferenceActivity
{
public GallerySettings()
{
}
-
- @Override
- protected int resourceId() {
- return R.xml.gallery_preferences;
- }
-
+
/** Called with the activity is first created. */
@Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
+ addPreferencesFromResource(R.xml.gallery_preferences);
}
}
diff --git a/src/com/android/camera/ImageGallery2.java b/src/com/android/camera/ImageGallery2.java
index 44d297b..92e9c57 100644
--- a/src/com/android/camera/ImageGallery2.java
+++ b/src/com/android/camera/ImageGallery2.java
@@ -113,14 +113,15 @@ public class ImageGallery2 extends Activity {
if (mSelectedImageGetter.getCurrentImage() == null)
return;
- menu.add(0, 0, 0, R.string.view).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
- mGvs.onSelect(mGvs.mCurrentSelection);
- return true;
- }
- });
-
boolean isImage = ImageManager.isImage(mSelectedImageGetter.getCurrentImage());
+ if (isImage) {
+ menu.add(0, 0, 0, R.string.view).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ mGvs.onSelect(mGvs.mCurrentSelection);
+ return true;
+ }
+ });
+ }
menu.setHeaderTitle(isImage ? R.string.context_menu_header
: R.string.video_context_menu_header);
@@ -138,6 +139,7 @@ public class ImageGallery2 extends Activity {
mGvs.clearCache();
mGvs.invalidate();
+ mGvs.requestLayout();
mGvs.start();
mNoImagesView.setVisibility(mAllImages.getCount() > 0 ? View.GONE : View.VISIBLE);
}
@@ -187,8 +189,9 @@ public class ImageGallery2 extends Activity {
mGvs.clearCache();
mAllImages.removeImage(mSelectedImageGetter.getCurrentImage());
mGvs.invalidate();
+ mGvs.requestLayout();
mGvs.start();
- mNoImagesView.setVisibility(mAllImages.getCount() > 0 ? View.GONE : View.VISIBLE);
+ mNoImagesView.setVisibility(mAllImages.isEmpty() ? View.VISIBLE : View.GONE);
}
};
@@ -217,6 +220,7 @@ public class ImageGallery2 extends Activity {
private Runnable mLongPressCallback = new Runnable() {
public void run() {
+ mGvs.select(-2, false);
mGvs.showContextMenu();
}
};
@@ -224,6 +228,7 @@ public class ImageGallery2 extends Activity {
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ mGvs.select(-2, false);
// The keyUp doesn't get called when the longpress menu comes up. We only get here when the user
// lets go of the center key before the longpress menu comes up.
mHandler.removeCallbacks(mLongPressCallback);
@@ -243,6 +248,7 @@ public class ImageGallery2 extends Activity {
int sel = mGvs.mCurrentSelection;
int columns = mGvs.mCurrentSpec.mColumns;
int count = mAllImages.getCount();
+ boolean pressed = false;
if (mGvs.mShowSelection) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_RIGHT:
@@ -266,6 +272,7 @@ public class ImageGallery2 extends Activity {
}
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
+ pressed = true;
mHandler.postDelayed(mLongPressCallback, ViewConfiguration.getLongPressTimeout());
break;
case KeyEvent.KEYCODE_DEL:
@@ -300,7 +307,7 @@ public class ImageGallery2 extends Activity {
}
}
if (handled) {
- mGvs.select(sel);
+ mGvs.select(sel, pressed);
return true;
}
else
@@ -368,13 +375,15 @@ public class ImageGallery2 extends Activity {
super.onPause();
mPausing = true;
stopCheckingThumbnails();
- mAllImages.deactivate();
mGvs.onPause();
if (mReceiver != null) {
unregisterReceiver(mReceiver);
mReceiver = null;
}
+ // Now that we've paused the threads that are using the cursor it is safe
+ // to deactivate it.
+ mAllImages.deactivate();
}
private void rebake(boolean unmounted, boolean scanning) {
@@ -567,8 +576,8 @@ public class ImageGallery2 extends Activity {
if ((mInclusion & ImageManager.INCLUDE_IMAGES) != 0) {
mSlideShowItem = addSlideShowMenu(menu, 5);
- mFlipItem = MenuHelper.addFlipOrientation(menu, this, mPrefs);
}
+ mFlipItem = MenuHelper.addFlipOrientation(menu, this, mPrefs);
item = menu.add(0, 0, 1000, R.string.camerasettings);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@@ -588,14 +597,11 @@ public class ImageGallery2 extends Activity {
@Override
public boolean onPrepareOptionsMenu(android.view.Menu menu) {
if ((mInclusion & ImageManager.INCLUDE_IMAGES) != 0) {
- boolean imageSelected = isImageSelected();
boolean videoSelected = isVideoSelected();
- int keyboard = getResources().getConfiguration().keyboardHidden;
- mFlipItem.setEnabled(imageSelected
- && (keyboard == android.content.res.Configuration.KEYBOARDHIDDEN_YES));
// TODO: Only enable slide show if there is at least one image in the folder.
mSlideShowItem.setEnabled(!videoSelected);
}
+ MenuHelper.setFlipOrientationEnabled(this, mFlipItem);
return true;
}
@@ -685,6 +691,7 @@ public class ImageGallery2 extends Activity {
private LayoutSpec mCurrentSpec;
private boolean mShowSelection = false;
private int mCurrentSelection = -1;
+ private boolean mCurrentSelectionPressed;
private boolean mDirectionBiasDown = true;
private final static boolean sDump = false;
@@ -748,9 +755,9 @@ public class ImageGallery2 extends Activity {
int pos = computeSelectedIndex(e);
if (pos >= 0 && pos < mGallery.mAllImages.getCount()) {
- select(pos);
+ select(pos, true);
} else {
- select(-1);
+ select(-1, false);
}
if (mImageBlockManager != null)
mImageBlockManager.repaintSelection(mCurrentSelection);
@@ -766,7 +773,7 @@ public class ImageGallery2 extends Activity {
else if (velocityY < -maxVelocity)
velocityY = -maxVelocity;
- select(-1);
+ select(-1, false);
if (mFling) {
mScroller = new Scroller(getContext());
mScroller.fling(0, mScrollY, 0, -(int)velocityY, 0, 0, 0, mMaxScrollY);
@@ -782,7 +789,7 @@ public class ImageGallery2 extends Activity {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- select(-1);
+ select(-1, false);
scrollBy(0, (int)distanceY);
invalidate();
return true;
@@ -795,6 +802,7 @@ public class ImageGallery2 extends Activity {
@Override
public boolean onSingleTapUp(MotionEvent e) {
+ select(mCurrentSelection, false);
int index = computeSelectedIndex(e);
if (index >= 0 && index < mGallery.mAllImages.getCount()) {
onSelect(index);
@@ -834,13 +842,22 @@ public class ImageGallery2 extends Activity {
invalidate();
}
- public void select(int newSel) {
+ /**
+ *
+ * @param newSel -2 means use old selection, -1 means remove selection
+ * @param newPressed
+ */
+ public void select(int newSel, boolean newPressed) {
+ if (newSel == -2) {
+ newSel = mCurrentSelection;
+ }
int oldSel = mCurrentSelection;
- if (oldSel == newSel)
+ if ((oldSel == newSel) && (mCurrentSelectionPressed == newPressed))
return;
mShowSelection = (newSel != -1);
mCurrentSelection = newSel;
+ mCurrentSelectionPressed = newPressed;
if (mImageBlockManager != null) {
mImageBlockManager.repaintSelection(oldSel);
mImageBlockManager.repaintSelection(newSel);
@@ -1527,11 +1544,16 @@ public class ImageGallery2 extends Activity {
}
private void paintSel(int pos, int xPos, int yPos) {
+ int[] stateSet = EMPTY_STATE_SET;
if (pos == mCurrentSelection && mShowSelection) {
- mCellOutline.setState(ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET);
- } else {
- mCellOutline.setState(EMPTY_STATE_SET);
+ if (mCurrentSelectionPressed) {
+ stateSet = PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ } else {
+ stateSet = ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
+ }
}
+
+ mCellOutline.setState(stateSet);
mCanvas.setBitmap(mBitmap);
mCellOutline.setBounds(xPos, yPos, xPos+mCurrentSpec.mCellWidth, yPos+mCurrentSpec.mCellHeight);
mCellOutline.draw(mCanvas);
diff --git a/src/com/android/camera/ImageManager.java b/src/com/android/camera/ImageManager.java
index 1fe93b5..4ceedb8 100755
--- a/src/com/android/camera/ImageManager.java
+++ b/src/com/android/camera/ImageManager.java
@@ -62,8 +62,17 @@ import java.util.HashMap;
*
*/
public class ImageManager {
- public static final String CAMERA_IMAGE_BUCKET_NAME = "/sdcard/dcim/camera";
- public static final String CAMERA_IMAGE_BUCKET_ID = String.valueOf(CAMERA_IMAGE_BUCKET_NAME.hashCode());
+ public static final String CAMERA_IMAGE_BUCKET_NAME =
+ Environment.getExternalStorageDirectory().toString() + "/dcim/Camera";
+ public static final String CAMERA_IMAGE_BUCKET_ID = getBucketId(CAMERA_IMAGE_BUCKET_NAME);
+
+ /**
+ * Matches code in MediaProvider.computeBucketValues. Should be a common function.
+ */
+
+ public static String getBucketId(String path) {
+ return String.valueOf(path.toLowerCase().hashCode());
+ }
// To enable verbose logging for this class, change false to true. The other logic ensures that
// this logging can be disabled by turned off DEBUG and lower, and that it can be enabled by
@@ -1431,7 +1440,7 @@ public class ImageManager {
requery();
}
}
- return false;
+ return true;
}
@@ -1716,6 +1725,11 @@ public class ImageManager {
*/
public abstract IImage getImageForUri(Uri uri);;
+ /**
+ *
+ * @param image
+ * @return true if the image was removed.
+ */
public abstract boolean removeImage(IImage image);
/**
* Removes the image at the ith position.
@@ -2252,6 +2266,7 @@ public class ImageManager {
protected int indexDisplayName() { return -1; }
protected int indexThumbId() { return INDEX_THUMB_ID; }
+ @Override
protected IImage make(long id, long miniThumbId, ContentResolver cr, IImageList list, long timestamp, int index, int rotation) {
return new Image(id, miniThumbId, mContentResolver, this, index, rotation);
}
@@ -2627,12 +2642,20 @@ public class ImageManager {
}
public boolean removeImage(IImage image) {
+ IImageList parent = image.getContainer();
int pos = -1;
+ int baseIndex = 0;
while (++pos < mSubList.length) {
IImageList sub = mSubList[pos];
- if (sub.removeImage(image)) {
- return true;
+ if (sub == parent) {
+ if (sub.removeImage(image)) {
+ modifySkipCountForDeletedImage(baseIndex);
+ return true;
+ } else {
+ break;
+ }
}
+ baseIndex += sub.getCount();
}
return false;
}
@@ -3303,8 +3326,9 @@ public class ImageManager {
protected int indexDisplayName() { return -1; }
protected int indexThumbId() { return INDEX_THUMB_ID; }
+ @Override
protected IImage make(long id, long miniThumbId, ContentResolver cr, IImageList list,
- long timestamp, int index) {
+ long timestamp, int index, int rotation) {
return new VideoObject(id, miniThumbId, mContentResolver, this, timestamp, index);
}
@@ -3572,24 +3596,13 @@ public class ImageManager {
return sInstance;
}
+
static public byte [] miniThumbData(Bitmap source) {
if (source == null)
return null;
- float scale;
- if (source.getWidth() < source.getHeight()) {
- scale = MINI_THUMB_TARGET_SIZE / (float)source.getWidth();
- } else {
- scale = MINI_THUMB_TARGET_SIZE / (float)source.getHeight();
- }
- Matrix matrix = new Matrix();
- matrix.setScale(scale, scale);
- Bitmap miniThumbnail = ImageLoader.transform(matrix, source,
- MINI_THUMB_TARGET_SIZE, MINI_THUMB_TARGET_SIZE, false);
-
- if (miniThumbnail != source) {
- source.recycle();
- }
+ Bitmap miniThumbnail = extractMiniThumb(source, MINI_THUMB_TARGET_SIZE,
+ MINI_THUMB_TARGET_SIZE);
java.io.ByteArrayOutputStream miniOutStream = new java.io.ByteArrayOutputStream();
miniThumbnail.compress(Bitmap.CompressFormat.JPEG, 75, miniOutStream);
miniThumbnail.recycle();
@@ -3604,6 +3617,33 @@ public class ImageManager {
return null;
}
+ /**
+ * Creates a centered bitmap of the desired size. Recycles the input.
+ * @param source
+ * @return
+ */
+ static public Bitmap extractMiniThumb(Bitmap source, int width, int height) {
+ if (source == null) {
+ return null;
+ }
+
+ float scale;
+ if (source.getWidth() < source.getHeight()) {
+ scale = width / (float)source.getWidth();
+ } else {
+ scale = height / (float)source.getHeight();
+ }
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ Bitmap miniThumbnail = ImageLoader.transform(matrix, source,
+ width, height, false);
+
+ if (miniThumbnail != source) {
+ source.recycle();
+ }
+ return miniThumbnail;
+ }
+
static Bitmap rotate(Bitmap b, int degrees) {
if (degrees != 0 && b != null) {
Matrix m = new Matrix();
diff --git a/src/com/android/camera/MenuHelper.java b/src/com/android/camera/MenuHelper.java
index 9e4fb82..f8e1658 100644
--- a/src/com/android/camera/MenuHelper.java
+++ b/src/com/android/camera/MenuHelper.java
@@ -19,11 +19,15 @@ package com.android.camera;
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.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Handler;
import android.provider.MediaStore;
+import android.provider.MediaStore.Images;
import android.util.Config;
import android.util.Log;
import android.view.Menu;
@@ -266,18 +270,107 @@ public class MenuHelper {
} finally {
}
- ((TextView)d.findViewById(R.id.details_attrname_1)).setText(R.string.details_file_size);
- ((TextView)d.findViewById(R.id.details_attrvalu_1)).setText(lengthString);
+ ((TextView)d.findViewById(R.id.details_file_size_value))
+ .setText(lengthString);
+ int dimensionWidth = 0;
+ int dimensionHeight = 0;
if (isImage) {
- String dimensionsString = String.valueOf(image.getWidth() + " X " + image.getHeight());
- ((TextView)d.findViewById(R.id.details_attrname_2)).setText(R.string.details_image_resolution);
- ((TextView)d.findViewById(R.id.details_attrvalu_2)).setText(dimensionsString);
+ dimensionWidth = image.getWidth();
+ dimensionHeight = image.getHeight();
+ d.findViewById(R.id.details_duration_row).setVisibility(View.GONE);
+ d.findViewById(R.id.details_frame_rate_row).setVisibility(View.GONE);
+ d.findViewById(R.id.details_bit_rate_row).setVisibility(View.GONE);
+ d.findViewById(R.id.details_format_row).setVisibility(View.GONE);
+ d.findViewById(R.id.details_codec_row).setVisibility(View.GONE);
} else {
- d.findViewById(R.id.details_attrname_2).setVisibility(View.GONE);
- d.findViewById(R.id.details_attrvalu_2).setVisibility(View.GONE);
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
+ retriever.setDataSource(image.getDataPath());
+ try {
+ dimensionWidth = Integer.parseInt(
+ retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
+ dimensionHeight = Integer.parseInt(
+ retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
+ } catch (NumberFormatException e) {
+ dimensionWidth = 0;
+ dimensionHeight = 0;
+ }
+
+ try {
+ long durationMs = Long.parseLong(retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_DURATION));
+ long duration = durationMs / 1000;
+ long h = duration / 3600;
+ long m = (duration - h * 3600) / 60;
+ long s = duration - (h * 3600 + m * 60);
+ String durationValue;
+ if (h == 0) {
+ durationValue = String.format(
+ activity.getString(R.string.details_ms), m, s);
+ } else {
+ durationValue = String.format(
+ activity.getString(R.string.details_hms), h, m, s);
+ }
+ ((TextView)d.findViewById(R.id.details_duration_value))
+ .setText(durationValue);
+ } catch (NumberFormatException e) {
+ d.findViewById(R.id.details_frame_rate_row)
+ .setVisibility(View.GONE);
+ }
+
+ try {
+ String frame_rate = String.format(
+ activity.getString(R.string.details_fps),
+ Integer.parseInt(
+ retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_FRAME_RATE)));
+ ((TextView)d.findViewById(R.id.details_frame_rate_value))
+ .setText(frame_rate);
+ } catch (NumberFormatException e) {
+ d.findViewById(R.id.details_frame_rate_row)
+ .setVisibility(View.GONE);
+ }
+
+ try {
+ long bitRate = Long.parseLong(retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_BIT_RATE));
+ String bps;
+ if (bitRate < 1000000) {
+ bps = String.format(
+ activity.getString(R.string.details_kbps),
+ bitRate / 1000);
+ } else {
+ bps = String.format(
+ activity.getString(R.string.details_mbps),
+ ((double) bitRate) / 1000000.0);
+ }
+ ((TextView)d.findViewById(R.id.details_bit_rate_value))
+ .setText(bps);
+ } catch (NumberFormatException e) {
+ d.findViewById(R.id.details_bit_rate_row)
+ .setVisibility(View.GONE);
+ }
+
+ String format = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_VIDEO_FORMAT);
+ ((TextView)d.findViewById(R.id.details_format_value))
+ .setText(format);
+
+ String codec = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_CODEC);
+ ((TextView)d.findViewById(R.id.details_codec_value))
+ .setText(codec);
}
+ String dimensionsString = String.format(
+ activity.getString(R.string.details_dimension_x),
+ dimensionWidth, dimensionHeight);
+ ((TextView)d.findViewById(R.id.details_resolution_value))
+ .setText(dimensionsString);
+
String dateString = "";
long dateTaken = image.getDateTaken();
if (dateTaken != 0) {
@@ -285,12 +378,19 @@ public class MenuHelper {
java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat();
dateString = dateFormat.format(date);
- ((TextView)d.findViewById(R.id.details_attrname_3)).setText(R.string.details_date_taken);
- ((TextView)d.findViewById(R.id.details_attrvalu_3)).setText(dateString);
+ ((TextView)d.findViewById(R.id.details_date_taken_value))
+ .setText(dateString);
} else {
- d.findViewById(R.id.details_daterow).setVisibility(View.GONE);
+ d.findViewById(R.id.details_date_taken_row)
+ .setVisibility(View.GONE);
}
+ builder.setNeutralButton(R.string.details_ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
builder.setIcon(android.R.drawable.ic_dialog_info)
.setTitle(R.string.details_panel_title)
@@ -356,7 +456,9 @@ public class MenuHelper {
}
static void deleteImage(Activity activity, Runnable onDelete, IImage image) {
- deleteImageImpl(activity, onDelete, ImageManager.isImage(image));
+ if (image != null) {
+ deleteImageImpl(activity, onDelete, ImageManager.isImage(image));
+ }
}
private static void deleteImageImpl(Activity activity, final Runnable onDelete, boolean isPhoto) {
@@ -365,33 +467,38 @@ public class MenuHelper {
if (onDelete != null)
onDelete.run();
} else {
- android.app.AlertDialog.Builder b = new android.app.AlertDialog.Builder(activity);
- b.setIcon(android.R.drawable.ic_dialog_alert);
- b.setTitle(R.string.confirm_delete_title);
- b.setMessage(isPhoto? R.string.confirm_delete_message
- : R.string.confirm_delete_video_message);
- b.setPositiveButton(android.R.string.ok, new android.content.DialogInterface.OnClickListener() {
- public void onClick(android.content.DialogInterface v, int x) {
- if (onDelete != null)
- onDelete.run();
- }
- });
- b.setNegativeButton(android.R.string.cancel, new android.content.DialogInterface.OnClickListener() {
- public void onClick(android.content.DialogInterface v, int x) {
-
- }
- });
- b.create().show();
+ displayDeleteDialog(activity, onDelete, isPhoto);
}
}
+ public static void displayDeleteDialog(Activity activity,
+ final Runnable onDelete, boolean isPhoto) {
+ android.app.AlertDialog.Builder b = new android.app.AlertDialog.Builder(activity);
+ b.setIcon(android.R.drawable.ic_dialog_alert);
+ b.setTitle(R.string.confirm_delete_title);
+ b.setMessage(isPhoto? R.string.confirm_delete_message
+ : R.string.confirm_delete_video_message);
+ b.setPositiveButton(android.R.string.ok, new android.content.DialogInterface.OnClickListener() {
+ public void onClick(android.content.DialogInterface v, int x) {
+ if (onDelete != null)
+ onDelete.run();
+ }
+ });
+ b.setNegativeButton(android.R.string.cancel, new android.content.DialogInterface.OnClickListener() {
+ public void onClick(android.content.DialogInterface v, int x) {
+
+ }
+ });
+ b.create().show();
+ }
+
static void addSwitchModeMenuItem(Menu menu, final Activity activity,
final boolean switchToVideo) {
int group = switchToVideo ? MenuHelper.IMAGE_MODE_ITEM : MenuHelper.VIDEO_MODE_ITEM;
int labelId = switchToVideo ? R.string.switch_to_video_lable
: R.string.switch_to_camera_lable;
int iconId = switchToVideo ? R.drawable.ic_menu_camera_video_view
- : R.drawable.ic_menu_camera;
+ : android.R.drawable.ic_menu_camera;
MenuItem item = menu.add(group, MENU_SWITCH_CAMERA_MODE, 0,
labelId).setOnMenuItemClickListener(
new OnMenuItemClickListener() {
@@ -408,6 +515,26 @@ public class MenuHelper {
item.setIcon(iconId);
}
+ static void gotoStillImageCapture(Activity activity) {
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+ try {
+ activity.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Could not start still image capture activity", e);
+ }
+ }
+
+ static void gotoCameraImageGallery(Activity activity) {
+ Uri target = Images.Media.INTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("bucketId",
+ ImageManager.CAMERA_IMAGE_BUCKET_ID).build();
+ Intent intent = new Intent(Intent.ACTION_VIEW, target);
+ try {
+ activity.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Could not start gallery activity", e);
+ }
+ }
+
static void addCaptureMenuItems(Menu menu, final Activity activity) {
menu.add(0, MENU_CAPTURE_PICTURE, 1, R.string.capture_picture)
@@ -423,7 +550,7 @@ public class MenuHelper {
return true;
}
})
- .setIcon(R.drawable.ic_menu_camera);
+ .setIcon(android.R.drawable.ic_menu_camera);
menu.add(0, MENU_CAPTURE_VIDEO, 2, R.string.capture_video)
.setOnMenuItemClickListener(
@@ -473,5 +600,10 @@ public class MenuHelper {
? android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER
: req);
}
+
+ static void setFlipOrientationEnabled(Activity activity, MenuItem flipItem) {
+ int keyboard = activity.getResources().getConfiguration().hardKeyboardHidden;
+ flipItem.setEnabled(keyboard != android.content.res.Configuration.HARDKEYBOARDHIDDEN_NO);
+ }
}
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 7fcab9a..9da1f49 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -17,11 +17,11 @@
package com.android.camera;
import java.io.File;
-import java.util.ArrayList;
import java.io.IOException;
+import java.util.ArrayList;
import android.app.Activity;
-import android.app.ProgressDialog;
+import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -30,7 +30,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.ColorDrawable;
import android.location.LocationManager;
@@ -44,16 +43,14 @@ import android.os.Message;
import android.os.StatFs;
import android.os.SystemClock;
import android.preference.PreferenceManager;
-import android.provider.MediaStore.Images;
+import android.provider.MediaStore;
import android.provider.MediaStore.Video;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.MotionEvent;
import android.view.SurfaceHolder;
-import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@@ -62,40 +59,32 @@ import android.view.animation.Animation;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-import android.widget.RelativeLayout.LayoutParams;
public class VideoCamera extends Activity implements View.OnClickListener, SurfaceHolder.Callback {
private static final String TAG = "videocamera";
private static final boolean DEBUG = true;
- private static final boolean DEBUG_SUPPRESS_AUDIO_RECORDING = DEBUG && true;
+ private static final boolean DEBUG_SUPPRESS_AUDIO_RECORDING = DEBUG && false;
private static final boolean DEBUG_DO_NOT_REUSE_MEDIA_RECORDER = DEBUG && true;
private static final int KEEP = 2;
private static final int CLEAR_SCREEN_DELAY = 4;
private static final int UPDATE_RECORD_TIME = 5;
- private static final int RESTART_PREVIEW = 6;
private static final int SCREEN_DELAY = 2 * 60 * 1000;
- private static final int POST_PICTURE_ALERT_TIMEOUT = 6 * 1000;
- private static final int NO_STORAGE_ERROR = -1;
- private static final int CANNOT_STAT_ERROR = -2;
+ private static final long NO_STORAGE_ERROR = -1L;
+ private static final long CANNOT_STAT_ERROR = -2L;
+ private static final long LOW_STORAGE_THRESHOLD = 512L * 1024L;
- public static final int MENU_SWITCH_TO_VIDEO = 0;
- public static final int MENU_SWITCH_TO_CAMERA = 1;
public static final int MENU_SETTINGS = 6;
public static final int MENU_GALLERY_PHOTOS = 7;
public static final int MENU_GALLERY_VIDEOS = 8;
- public static final int MENU_SAVE_SELECT_PHOTOS = 30;
- public static final int MENU_SAVE_NEW_PHOTO = 31;
- public static final int MENU_SAVE_SELECTVIDEO = 32;
- public static final int MENU_SAVE_TAKE_NEW_VIDEO = 33;
public static final int MENU_SAVE_GALLERY_PHOTO = 34;
- public static final int MENU_SAVE_GALLERY_VIDEO_PHOTO = 35;
- public static final int MENU_SAVE_CAMERA_DONE = 36;
- public static final int MENU_SAVE_CAMERA_VIDEO_DONE = 37;
+ public static final int MENU_SAVE_PLAY_VIDEO = 35;
+ public static final int MENU_SAVE_SELECT_VIDEO = 36;
+ public static final int MENU_SAVE_NEW_VIDEO = 37;
Toast mToast;
SharedPreferences mPreferences;
@@ -109,9 +98,12 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
private MediaRecorder mMediaRecorder;
private boolean mMediaRecorderRecording = false;
+ private boolean mNeedToDeletePartialRecording;
+ private boolean mNeedToRegisterRecording;
private long mRecordingStartTime;
private String mCurrentVideoFilename;
private Uri mCurrentVideoUri;
+ private ContentValues mCurrentVideoValues;
boolean mPausing = false;
@@ -129,8 +121,6 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
View mPostPictureAlert;
LocationManager mLocationManager = null;
- private int mPicturesRemaining;
-
private Handler mHandler = new MainHandler();
private void cancelSavingNotification() {
@@ -177,15 +167,17 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
String text = minutesString + ":" + secondsString;
mRecordingTimeView.setText(text);
+ // Work around a limitation of the T-Mobile G1: The T-Mobile
+ // hardware blitter can't pixel-accurately scale and clip at the same time,
+ // and the SurfaceFlinger doesn't attempt to work around this limitation.
+ // In order to avoid visual corruption we must manually refresh the entire
+ // surface view when changing any overlapping view's contents.
+ mVideoPreview.invalidate();
mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000);
}
break;
}
- case RESTART_PREVIEW:
- hideVideoFrameAndStartPreview();
- break;
-
default:
Log.v(TAG, "Unhandled message: " + msg.what);
break;
@@ -254,16 +246,12 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
mBlackout.setBackgroundDrawable(new ColorDrawable(0xFF000000));
mPostPictureAlert = findViewById(R.id.post_picture_panel);
- View b;
-
- b = findViewById(R.id.play);
- b.setOnClickListener(this);
- b = findViewById(R.id.share);
- b.setOnClickListener(this);
-
- b = findViewById(R.id.discard);
- b.setOnClickListener(this);
+ int[] ids = new int[]{R.id.play, R.id.share, R.id.discard,
+ R.id.capture, R.id.cancel, R.id.accept};
+ for (int id : ids) {
+ findViewById(id).setOnClickListener(this);
+ }
mModeIndicatorView = (ImageView) findViewById(R.id.mode_indicator);
mRecordingIndicatorView = (ImageView) findViewById(R.id.recording_indicator);
@@ -281,7 +269,7 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
Thread t = new Thread(new Runnable() {
public void run() {
- final boolean storageOK = calculatePicturesRemaining() > 0;
+ final boolean storageOK = getAvailableStorage() >= LOW_STORAGE_THRESHOLD;
if (hintView == null)
return;
@@ -315,12 +303,20 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
public void onClick(View v) {
switch (v.getId()) {
- case R.id.discard: {
- File f = new File(mCurrentVideoFilename);
- f.delete();
- mContentResolver.delete(mCurrentVideoUri, null, null);
+ case R.id.capture:
+ doDiscardCurrentVideo();
+ break;
- hideVideoFrameAndStartPreview();
+ case R.id.accept:
+ doReturnToPicker(true);
+ break;
+
+ case R.id.cancel:
+ doReturnToPicker(false);
+ break;
+
+ case R.id.discard: {
+ doDiscardCurrentVideo();
break;
}
@@ -339,29 +335,35 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
case R.id.play: {
- Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
- try {
- startActivity(intent);
- } catch (android.content.ActivityNotFoundException ex) {
- Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
- }
+ doPlayCurrentVideo();
break;
}
}
}
+ private void doPlayCurrentVideo() {
+ Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri);
+ try {
+ startActivity(intent);
+ } catch (android.content.ActivityNotFoundException ex) {
+ Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex);
+ }
+ }
+
+ private void doDiscardCurrentVideo() {
+ deleteCurrentVideo();
+ hideVideoFrameAndStartPreview();
+ }
+
private void showStorageToast() {
- String noStorageText = null;
- int remaining = calculatePicturesRemaining();
+ long remaining = getAvailableStorage();
if (remaining == NO_STORAGE_ERROR) {
- noStorageText = getString(R.string.no_storage);
- } else if (remaining < 1) {
- noStorageText = getString(R.string.not_enough_space);
- }
-
- if (noStorageText != null) {
- Toast.makeText(this, noStorageText, 5000).show();
+ Toast.makeText(this, getString(R.string.no_storage), Toast.LENGTH_LONG).show();
+ } else if (remaining < LOW_STORAGE_THRESHOLD) {
+ new AlertDialog.Builder(this).setTitle(R.string.spaceIsLow_title)
+ .setMessage(R.string.spaceIsLow_content)
+ .show();
}
}
@@ -456,12 +458,6 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
return super.onKeyDown(keyCode, event);
}
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- cancelRestartPreviewTimeout();
- return super.onTrackballEvent(event);
- }
-
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
stopVideoRecording();
initializeVideo();
@@ -511,7 +507,6 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
-
addBaseMenuItems(menu);
MenuHelper.addImageMenuItems(
menu,
@@ -545,26 +540,47 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
});
gallery.setIcon(android.R.drawable.ic_menu_gallery);
+
return true;
}
- private int calculatePicturesRemaining() {
+ private boolean isPickIntent() {
+ String action = getIntent().getAction();
+ return (Intent.ACTION_PICK.equals(action) || MediaStore.ACTION_VIDEO_CAPTURE.equals(action));
+ }
+
+ private void doReturnToPicker(boolean success) {
+ Intent resultIntent = new Intent();
+ int resultCode;
+ if (success) {
+ resultCode = RESULT_OK;
+ resultIntent.setData(mCurrentVideoUri);
+ } else {
+ resultCode = RESULT_CANCELED;
+ }
+ setResult(resultCode, resultIntent);
+ finish();
+ }
+
+ /**
+ * Returns
+ * @return number of bytes available, or an ERROR code.
+ */
+ private static long getAvailableStorage() {
try {
if (!ImageManager.hasStorage()) {
- mPicturesRemaining = NO_STORAGE_ERROR;
+ return NO_STORAGE_ERROR;
} else {
String storageDirectory = Environment.getExternalStorageDirectory().toString();
StatFs stat = new StatFs(storageDirectory);
- float remaining = ((float)stat.getAvailableBlocks() * (float)stat.getBlockSize()) / 400000F;
- mPicturesRemaining = (int)remaining;
+ return ((long)stat.getAvailableBlocks() * (long)stat.getBlockSize());
}
} catch (Exception ex) {
// if we can't stat the filesystem then we don't know how many
- // pictures are remaining. it might be zero but just leave it
+ // free bytes exist. It might be zero but just leave it
// blank since we really don't know.
- mPicturesRemaining = CANNOT_STAT_ERROR;
+ return CANNOT_STAT_ERROR;
}
- return mPicturesRemaining;
}
private void initializeVideo() {
@@ -577,6 +593,8 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
mMediaRecorder = new MediaRecorder();
+ mNeedToDeletePartialRecording = true;
+ mNeedToRegisterRecording = false;
if (DEBUG_SUPPRESS_AUDIO_RECORDING) {
Log.v(TAG, "DEBUG_SUPPRESS_AUDIO_RECORDING is true.");
@@ -588,17 +606,26 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
Log.v(TAG, "before setOutputFile");
createVideoPath();
mMediaRecorder.setOutputFile(mCurrentVideoFilename);
- Boolean videoQualityLow = getIntPreference("pref_camera_videoquality_key") == 0;
+ boolean videoQualityHigh = getBooleanPreference(CameraSettings.KEY_VIDEO_QUALITY,
+ CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE);
+
+ {
+ Intent intent = getIntent();
+ if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
+ int extraVideoQuality = intent.getIntExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
+ videoQualityHigh = (extraVideoQuality > 0);
+ }
+ }
// Use the same frame rate for both, since internally
// if the frame rate is too large, it can cause camera to become
// unstable. We need to fix the MediaRecorder to disable the support
// of setting frame rate for now.
mMediaRecorder.setVideoFrameRate(20);
- if (videoQualityLow) {
- mMediaRecorder.setVideoSize(176,144);
- } else {
+ if (videoQualityHigh) {
mMediaRecorder.setVideoSize(352,288);
+ } else {
+ mMediaRecorder.setVideoSize(176,144);
}
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
if (!DEBUG_SUPPRESS_AUDIO_RECORDING) {
@@ -641,17 +668,29 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
}
- private int getIntPreference(String key) {
- String s = mPreferences.getString(key, "0");
- return Integer.parseInt(s);
+ private int getIntPreference(String key, int defaultValue) {
+ String s = mPreferences.getString(key, "");
+ int result = defaultValue;
+ try {
+ result = Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ // Ignore, result is already the default value.
+ }
+ return result;
+ }
+
+ private boolean getBooleanPreference(String key, boolean defaultValue) {
+ return getIntPreference(key, defaultValue ? 1 : 0) != 0;
}
private void createVideoPath() {
long dateTaken = System.currentTimeMillis();
String title = createName(dateTaken);
String displayName = title + ".3gp"; // Used when emailing.
- String filename = ImageManager.CAMERA_IMAGE_BUCKET_NAME + "/"
- + Long.toString(dateTaken) + ".3gp";
+ String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME;
+ File cameraDir = new File(cameraDirPath);
+ cameraDir.mkdirs();
+ String filename = cameraDirPath + "/" + Long.toString(dateTaken) + ".3gp";
ContentValues values = new ContentValues(7);
values.put(Video.Media.TITLE, title);
values.put(Video.Media.DISPLAY_NAME, displayName);
@@ -659,10 +698,31 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
values.put(Video.Media.DATE_TAKEN, dateTaken);
values.put(Video.Media.MIME_TYPE, "video/3gpp");
values.put(Video.Media.DATA, filename);
- Uri videoTable = Uri.parse("content://media/external/video/media");
- Uri item = mContentResolver.insert(videoTable, values);
mCurrentVideoFilename = filename;
- mCurrentVideoUri = item;
+ mCurrentVideoValues = values;
+ mCurrentVideoUri = null;
+ }
+
+ private void registerVideo() {
+ Uri videoTable = Uri.parse("content://media/external/video/media");
+ mCurrentVideoUri = mContentResolver.insert(videoTable,
+ mCurrentVideoValues);
+ mCurrentVideoValues = null;
+ }
+
+ private void deleteCurrentVideo() {
+ if (mCurrentVideoFilename != null) {
+ Log.v(TAG, "Deleting stub video " + mCurrentVideoFilename);
+ File f = new File(mCurrentVideoFilename);
+ if (! f.delete()) {
+ Log.v(TAG, "Could not delete " + mCurrentVideoFilename);
+ }
+ mCurrentVideoFilename = null;
+ }
+ if (mCurrentVideoUri != null) {
+ mContentResolver.delete(mCurrentVideoUri, null, null);
+ mCurrentVideoUri = null;
+ }
}
private void addBaseMenuItems(Menu menu) {
@@ -734,20 +794,20 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
}
private void showPostRecordingAlert() {
- cancelRestartPreviewTimeout();
+ boolean isPick = isPickIntent();
+ 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.accept).setVisibility(pickVisible);
+ mPostPictureAlert.findViewById(R.id.cancel).setVisibility(pickVisible);
mPostPictureAlert.setVisibility(View.VISIBLE);
- mHandler.sendEmptyMessageDelayed(RESTART_PREVIEW, POST_PICTURE_ALERT_TIMEOUT);
}
private void hidePostPictureAlert() {
- cancelRestartPreviewTimeout();
mPostPictureAlert.setVisibility(View.INVISIBLE);
}
- private void cancelRestartPreviewTimeout() {
- mHandler.removeMessages(RESTART_PREVIEW);
- }
-
private boolean isPostRecordingAlertVisible() {
return mPostPictureAlert.getVisibility() == View.VISIBLE;
}
@@ -757,14 +817,24 @@ public class VideoCamera extends Activity implements View.OnClickListener, Surfa
if (mMediaRecorderRecording || mMediaRecorder != null) {
if (mMediaRecorderRecording) {
mMediaRecorder.stop();
+ mNeedToDeletePartialRecording = false;
+ mNeedToRegisterRecording = true;
+ mMediaRecorderRecording = false;
}
releaseMediaRecorder();
- mMediaRecorderRecording = false;
mModeIndicatorView.setVisibility(View.VISIBLE);
mRecordingIndicatorView.setVisibility(View.GONE);
mRecordingTimeView.setVisibility(View.GONE);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
+ if (mNeedToRegisterRecording) {
+ registerVideo();
+ mNeedToRegisterRecording = false;
+ }
+ if (mNeedToDeletePartialRecording){
+ deleteCurrentVideo();
+ mNeedToDeletePartialRecording = false;
+ }
}
private void hideVideoFrameAndStartPreview() {
diff --git a/src/com/android/camera/ViewImage.java b/src/com/android/camera/ViewImage.java
index 9579f19..d1ef142 100644
--- a/src/com/android/camera/ViewImage.java
+++ b/src/com/android/camera/ViewImage.java
@@ -21,6 +21,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.net.Uri;
@@ -49,6 +50,7 @@ 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;
@@ -56,7 +58,7 @@ import com.android.camera.ImageManager.IImage;
import java.util.Random;
-public class ViewImage extends Activity
+public class ViewImage extends Activity implements View.OnClickListener
{
static final String TAG = "ViewImage";
private ImageGetter mGetter;
@@ -81,6 +83,9 @@ public class ViewImage extends Activity
private static final int MODE_NORMAL = 1;
private static final int MODE_SLIDESHOW = 2;
private int mMode = MODE_NORMAL;
+ private boolean mFullScreenInNormalMode;
+ private boolean mShowActionIcons;
+ private View mActionIconPanel;
private boolean mSortAscending = false;
private int mSlideShowInterval;
@@ -652,8 +657,7 @@ public class ViewImage extends Activity
mImageMenuRunnable.gettingReadyToOpen(menu, mAllImages.getImageAt(mCurrentPosition));
}
- int keyboard = getResources().getConfiguration().keyboardHidden;
- mFlipItem.setEnabled(keyboard == android.content.res.Configuration.KEYBOARDHIDDEN_YES);
+ MenuHelper.setFlipOrientationEnabled(this, mFlipItem);
menu.findItem(MenuHelper.MENU_IMAGE_SHARE).setEnabled(isCurrentImageShareable());
@@ -1067,6 +1071,12 @@ public class ViewImage extends Activity
mSlideShowImageViews[i].setVisibility(View.INVISIBLE);
}
+ mActionIconPanel = findViewById(R.id.action_icon_panel);
+ int[] ids = {R.id.capture, R.id.gallery, R.id.discard, R.id.share, R.id.setas};
+ for(int id : ids) {
+ findViewById(id).setOnClickListener(this);
+ }
+
Uri uri = getIntent().getData();
if (Config.LOGV)
@@ -1081,12 +1091,24 @@ public class ViewImage extends Activity
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();
+
boolean slideShow = b != null ? b.getBoolean("slideshow", false) : false;
if (slideShow) {
setMode(MODE_SLIDESHOW);
loadNextImage(mCurrentPosition, 0, true);
+ } else {
+ if (mFullScreenInNormalMode) {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+ if (mShowActionIcons) {
+ mActionIconPanel.setVisibility(View.VISIBLE);
+ }
}
// Get the zoom controls and add them to the bottom of the map
@@ -1102,7 +1124,20 @@ public class ViewImage extends Activity
mNextImageView = findViewById(R.id.next_image);
mPrevImageView = findViewById(R.id.prev_image);
- MenuHelper.requestOrientation(this, mPrefs);
+ setOrientation();
+ }
+
+ private void setOrientation() {
+ Intent intent = getIntent();
+ if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) {
+ int orientation = intent.getIntExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ if (orientation != getRequestedOrientation()) {
+ setRequestedOrientation(orientation);
+ }
+ } else {
+ MenuHelper.requestOrientation(this, mPrefs);
+ }
}
private Animation makeInAnimation(int id) {
@@ -1134,6 +1169,7 @@ public class ViewImage extends Activity
for (ImageViewTouchBase ivt: mImageViews) {
ivt.clear();
}
+ mActionIconPanel.setVisibility(View.GONE);
if (false) {
Log.v(TAG, "current is " + this.mSlideShowImageCurrent);
@@ -1170,8 +1206,12 @@ public class ViewImage extends Activity
} else {
if (Config.LOGV)
Log.v(TAG, "slide show mode off, mCurrentPosition == " + mCurrentPosition);
- win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ win.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ if (mFullScreenInNormalMode) {
+ win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ } else {
+ win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
if (mGetter != null)
mGetter.cancelCurrent();
@@ -1179,6 +1219,9 @@ public class ViewImage extends Activity
if (sSlideShowHidesStatusBar) {
win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
+ if (mShowActionIcons) {
+ mActionIconPanel.setVisibility(View.VISIBLE);
+ }
ImageViewTouchBase dst = mImageViews[1];
dst.mLastXTouchPos = -1;
@@ -1403,7 +1446,7 @@ public class ViewImage extends Activity
});
setImage(mCurrentPosition);
- MenuHelper.requestOrientation(this, mPrefs);
+ setOrientation();
}
@Override
@@ -1433,4 +1476,49 @@ public class ViewImage extends Activity
public void onStop() {
super.onStop();
}
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+
+ case R.id.capture: {
+ MenuHelper.gotoStillImageCapture(this);
+ }
+ break;
+
+ case R.id.gallery: {
+ MenuHelper.gotoCameraImageGallery(this);
+ }
+ break;
+
+ case R.id.discard: {
+ MenuHelper.displayDeleteDialog(this, mDeletePhotoRunnable, true);
+ }
+ break;
+
+ case R.id.share: {
+ Uri u = mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri();
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_SEND);
+ intent.setType("image/jpeg");
+ intent.putExtra(Intent.EXTRA_STREAM, u);
+ try {
+ startActivity(Intent.createChooser(intent, getText(R.string.sendImage)));
+ } catch (android.content.ActivityNotFoundException ex) {
+ Toast.makeText(this, R.string.no_way_to_share_image, Toast.LENGTH_SHORT).show();
+ }
+ }
+ break;
+
+ case R.id.setas: {
+ Uri u = mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri();
+ Intent intent = new Intent(Intent.ACTION_ATTACH_DATA, u);
+ try {
+ startActivity(Intent.createChooser(intent, getText(R.string.setImage)));
+ } catch (android.content.ActivityNotFoundException ex) {
+ Toast.makeText(this, R.string.no_way_to_share_video, Toast.LENGTH_SHORT).show();
+ }
+ }
+ break;
+ }
+ }
}
diff --git a/src/com/android/camera/Wallpaper.java b/src/com/android/camera/Wallpaper.java
index ff41242..1cc12fb 100644
--- a/src/com/android/camera/Wallpaper.java
+++ b/src/com/android/camera/Wallpaper.java
@@ -74,14 +74,16 @@ public class Wallpaper extends Activity {
};
static class SetWallpaperThread extends Thread {
- private Bitmap mBitmap;
- private Handler mHandler;
- private Context mContext;
+ private final Bitmap mBitmap;
+ private final Handler mHandler;
+ private final Context mContext;
+ private final File mFile;
- public SetWallpaperThread(Bitmap bitmap, Handler handler, Context context) {
+ public SetWallpaperThread(Bitmap bitmap, Handler handler, Context context, File file) {
mBitmap = bitmap;
mHandler = handler;
mContext = context;
+ mFile = file;
}
@Override
@@ -92,6 +94,7 @@ public class Wallpaper extends Activity {
Log.e(LOG_TAG, "Failed to set wallpaper.", e);
} finally {
mHandler.sendEmptyMessage(FINISH);
+ mFile.delete();
}
}
}
@@ -148,6 +151,10 @@ public class Wallpaper extends Activity {
}
protected void formatIntent(Intent intent) {
+ // TODO: A temporary file is NOT necessary
+ // The CropImage intent should be able to set the wallpaper directly
+ // without writing to a file, which we then need to read here to write
+ // it again as the final wallpaper, this is silly
File f = getFileStreamPath("temp-wallpaper");
(new File(f.getParent())).mkdirs();
mTempFilePath = f.toString();
@@ -162,6 +169,10 @@ public class Wallpaper extends Activity {
intent.putExtra("scale", true);
intent.putExtra("noFaceDetection", true);
intent.putExtra("output", Uri.parse("file:/" + mTempFilePath));
+ intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.name());
+ // TODO: we should have an extra called "setWallpaper" to ask CropImage to
+ // set the cropped image as a wallpaper directly
+ // This means the SetWallpaperThread should be moved out of this class to CropImage
}
@Override
@@ -169,7 +180,8 @@ public class Wallpaper extends Activity {
if ((requestCode == PHOTO_PICKED || requestCode == CROP_DONE) && (resultCode == RESULT_OK)
&& (data != null)) {
try {
- InputStream s = new FileInputStream(mTempFilePath);
+ File tempFile = new File(mTempFilePath);
+ InputStream s = new FileInputStream(tempFile);
Bitmap bitmap = BitmapFactory.decodeStream(s);
if (bitmap == null) {
Log.e(LOG_TAG, "Failed to set wallpaper. Couldn't get bitmap for path " + mTempFilePath);
@@ -177,7 +189,7 @@ public class Wallpaper extends Activity {
if (android.util.Config.LOGV)
Log.v(LOG_TAG, "bitmap size is " + bitmap.getWidth() + " / " + bitmap.getHeight());
mHandler.sendEmptyMessage(SHOW_PROGRESS);
- new SetWallpaperThread(bitmap, mHandler, this).start();
+ new SetWallpaperThread(bitmap, mHandler, this, tempFile).start();
}
mDoLaunch = false;
} catch (FileNotFoundException ex) {