VideoCamera.java revision b128446b7ef264c33e91e119391045156a19439b
1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project/* 2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * 4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * you may not use this file except in compliance with the License. 6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * You may obtain a copy of the License at 7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * 8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * 10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * See the License for the specific language governing permissions and 14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * limitations under the License. 15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpackage com.android.camera; 18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 19101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImage; 20101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport com.android.camera.gallery.IImageList; 21101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 22b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.app.Activity; 23b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.BroadcastReceiver; 24b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentResolver; 25b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.ContentValues; 26b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Context; 27b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.Intent; 28b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.IntentFilter; 29b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.content.SharedPreferences; 30095afa19556bf550262e3cccb9edacc04e6f726aOwen Linimport android.database.Cursor; 31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.Bitmap; 32b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.graphics.drawable.Drawable; 33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.media.MediaRecorder; 34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.net.Uri; 35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Bundle; 36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Environment; 37b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Handler; 38b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.Message; 39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.StatFs; 40b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.os.SystemClock; 41b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.preference.PreferenceManager; 42b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore; 43b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.provider.MediaStore.Video; 44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.text.format.DateFormat; 45b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.util.Log; 46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.KeyEvent; 47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Menu; 48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.MenuItem; 49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.SurfaceHolder; 50b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.View; 51b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.Window; 52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.WindowManager; 53059daa36dc6e83ca24a16d9b99925e71010bccebOwen Linimport android.view.MenuItem.OnMenuItemClickListener; 54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.AlphaAnimation; 55b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.view.animation.Animation; 56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.ImageView; 57b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.TextView; 58b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectimport android.widget.Toast; 59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 60d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.File; 61d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.FileDescriptor; 62d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.io.IOException; 63d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.text.SimpleDateFormat; 64d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.ArrayList; 65d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Changimport java.util.Date; 66d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 6723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen/** 6823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen * The Camcorder activity. 6923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen */ 70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Projectpublic class VideoCamera extends Activity implements View.OnClickListener, 71d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback, 72d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener { 73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final String TAG = "videocamera"; 75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 76b128446b7ef264c33e91e119391045156a19439bWu-cheng Li private static final int INIT_RECORDER = 3; 77b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final int CLEAR_SCREEN_DELAY = 4; 78b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final int UPDATE_RECORD_TIME = 5; 79b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 80b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final int SCREEN_DELAY = 2 * 60 * 1000; 81b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 82b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final long NO_STORAGE_ERROR = -1L; 83b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final long CANNOT_STAT_ERROR = -2L; 84b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final long LOW_STORAGE_THRESHOLD = 512L * 1024L; 85b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private static final int STORAGE_STATUS_OK = 0; 879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private static final int STORAGE_STATUS_LOW = 1; 889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private static final int STORAGE_STATUS_NONE = 2; 899a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 90b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public static final int MENU_SETTINGS = 6; 91b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public static final int MENU_GALLERY_PHOTOS = 7; 92b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public static final int MENU_GALLERY_VIDEOS = 8; 93b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public static final int MENU_SAVE_GALLERY_PHOTO = 34; 94b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public static final int MENU_SAVE_PLAY_VIDEO = 35; 95b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public static final int MENU_SAVE_SELECT_VIDEO = 36; 96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public static final int MENU_SAVE_NEW_VIDEO = 37; 97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project SharedPreferences mPreferences; 99b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static final float VIDEO_ASPECT_RATIO = 176.0f / 144.0f; 101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project VideoPreview mVideoPreview; 102b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project SurfaceHolder mSurfaceHolder = null; 103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project ImageView mVideoFrame; 1049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 1059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private boolean mIsVideoCaptureIntent; 1069bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // mLastPictureButton and mThumbController 1070a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang // are non-null only if mIsVideoCaptureIntent is true. 108de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project private ImageView mLastPictureButton; 1099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private ThumbnailController mThumbController; 110b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private int mStorageStatus = STORAGE_STATUS_OK; 1129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 113b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private MediaRecorder mMediaRecorder; 114b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private boolean mMediaRecorderRecording = false; 115b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private long mRecordingStartTime; 116b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // The video file that the hardware camera is about to record into 117b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // (or is recording into.) 118b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private String mCameraVideoFilename; 119b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private FileDescriptor mCameraVideoFileDescriptor; 120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // The video file that has already been recorded, and that is being 122b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // examined by the user. 123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private String mCurrentVideoFilename; 124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private Uri mCurrentVideoUri; 125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private ContentValues mCurrentVideoValues; 126b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 127845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // The video frame size we will record (like 352x288). 128845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang private int mVideoWidth, mVideoHeight; 129845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 13082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang // The video duration limit. 13182ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang private int mMaxVideoDurationInMs; 13282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang 133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project boolean mPausing = false; 134ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li boolean mPreviewing = false; // True if preview is started. 135b128446b7ef264c33e91e119391045156a19439bWu-cheng Li boolean mRecorderInitialized = false; 136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 137d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang private ContentResolver mContentResolver; 138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 139b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private ShutterButton mShutterButton; 140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private TextView mRecordingTimeView; 1418d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project private boolean mRecordingTimeCountsDown = false; 142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>(); 144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project View mPostPictureAlert; 146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 147059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin private final Handler mHandler = new MainHandler(); 148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 149d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // This Handler is used to post message back onto the main thread of the 150d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // application 151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private class MainHandler extends Handler { 152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void handleMessage(Message msg) { 154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch (msg.what) { 155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case CLEAR_SCREEN_DELAY: { 157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project clearScreenOnFlag(); 158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case UPDATE_RECORD_TIME: { 162d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang updateRecordingTime(); 163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 166b128446b7ef264c33e91e119391045156a19439bWu-cheng Li case INIT_RECORDER: { 167b128446b7ef264c33e91e119391045156a19439bWu-cheng Li initializeRecorder(); 168ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li break; 169ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li } 170ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project default: 172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Unhandled message: " + msg.what); 1730a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang break; 174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 176937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Lin } 177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onReceive(Context context, Intent intent) { 181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String action = intent.getAction(); 182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (action.equals(Intent.ACTION_MEDIA_EJECT)) { 1839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project updateAndShowStorageHint(false); 184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project stopVideoRecording(); 185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { 1869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project updateAndShowStorageHint(true); 187b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 188b128446b7ef264c33e91e119391045156a19439bWu-cheng Li initializeRecorder(); 189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) { 190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // SD card unavailable 1919a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project // handled in ACTION_MEDIA_EJECT 192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) { 193d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang Toast.makeText(VideoCamera.this, 194d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang getResources().getString(R.string.wait), 5000); 195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) { 1969a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project updateAndShowStorageHint(true); 197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project }; 200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 201d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang private static String createName(long dateTaken) { 202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString(); 203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /** Called with the activity is first created. */ 206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 207b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onCreate(Bundle icicle) { 208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onCreate(icicle); 209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 210ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li /* 211ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li * To reduce startup time, we open camera device in another thread. 212ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li * Camera is opened in onCreate instead of onResume because there are 213ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li * lots of things to do here and camera open can be done in parallel. 214ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li * We will make sure the camera is opened at the end of onCreate. 215ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li */ 216ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li Thread openCameraThread = new Thread(new Runnable() { 217ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li public void run() { 218ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li mCameraDevice = android.hardware.Camera.open(); 219ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li } 220ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li }); 221ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li openCameraThread.start(); 222ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mPreferences = PreferenceManager.getDefaultSharedPreferences(this); 224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mContentResolver = getContentResolver(); 225b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 226b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project requestWindowFeature(Window.FEATURE_PROGRESS); 227b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setContentView(R.layout.video_camera); 228b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 229b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview); 230b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mVideoPreview.setAspectRatio(VIDEO_ASPECT_RATIO); 231b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 232b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // don't set mSurfaceHolder here. We have it set ONLY within 233b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // surfaceCreated / surfaceDestroyed, other parts of the code 234b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // assume that when it is set, the surface is also set. 235b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project SurfaceHolder holder = mVideoPreview.getHolder(); 236b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project holder.addCallback(this); 237b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 238b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 239b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mPostPictureAlert = findViewById(R.id.post_picture_panel); 240b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 241b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] ids = new int[]{R.id.play, R.id.share, R.id.discard, 242b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project R.id.cancel, R.id.attach}; 243b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project for (int id : ids) { 244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project findViewById(id).setOnClickListener(this); 245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 246b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 247059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.video_indicator).setVisibility(View.VISIBLE); 248059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mShutterButton = (ShutterButton) findViewById(R.id.video_button); 249b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mShutterButton.setOnShutterButtonListener(this); 250059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mShutterButton.requestFocus(); 251059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 252b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingTimeView = (TextView) findViewById(R.id.recording_time); 253b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mVideoFrame = (ImageView) findViewById(R.id.video_frame); 2549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mIsVideoCaptureIntent = isVideoCaptureIntent(); 2559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (!mIsVideoCaptureIntent) { 256059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mLastPictureButton = (ImageView) findViewById(R.id.review_button); 2579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mLastPictureButton.setOnClickListener(this); 258059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mThumbController = new ThumbnailController( 259059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mLastPictureButton, mContentResolver); 2609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.loadData(ImageManager.getLastVideoThumbPath()); 261059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.camera_button).setOnClickListener(this); 262059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin } else { 263059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.camera_button).setVisibility(View.INVISIBLE); 264059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.review_button).setVisibility(View.INVISIBLE); 2659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 266ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 267ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // Make sure the camera is opened. 268ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li try { 269ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li openCameraThread.join(); 270ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li } catch (InterruptedException ex) { 271ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // ignore 272ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li } 273b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 274b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 275e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project private void startShareVideoActivity() { 276e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project Intent intent = new Intent(); 277e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project intent.setAction(Intent.ACTION_SEND); 278e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project intent.setType("video/3gpp"); 279e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project intent.putExtra(Intent.EXTRA_STREAM, mCurrentVideoUri); 280e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project try { 281d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang startActivity(Intent.createChooser( 282d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang intent, getText(R.string.sendVideo))); 283e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project } catch (android.content.ActivityNotFoundException ex) { 284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang Toast.makeText(VideoCamera.this, R.string.no_way_to_share_video, 285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang Toast.LENGTH_SHORT).show(); 286e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project } 287e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project } 288e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project 289b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onClick(View v) { 290b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch (v.getId()) { 291059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin case R.id.camera_button: 292059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin MenuHelper.gotoCameraMode(this); 293059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin break; 294b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 295b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.gallery: 2960a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang gotoGallery(); 297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.attach: 300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project doReturnToCaller(true); 301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.cancel: 304b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project doReturnToCaller(false); 305b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 306b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 307b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.discard: { 3087638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen Runnable deleteCallback = new Runnable() { 3097638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen public void run() { 310b128446b7ef264c33e91e119391045156a19439bWu-cheng Li discardCurrentVideoAndInitRecorder(); 3117638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen } 3127638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen }; 3137638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen MenuHelper.deleteVideo(this, deleteCallback); 314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.share: { 318e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project startShareVideoActivity(); 319b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 320b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 321b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 322b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.play: { 323b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project doPlayCurrentVideo(); 324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 326de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 327059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin case R.id.review_button: { 3289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndShowAlert(); 329de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project break; 330de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 331b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 333b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 334b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onShutterButtonFocus(ShutterButton button, boolean pressed) { 335de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // Do nothing (everything happens in onShutterButtonClick). 336de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 337de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 338de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project public void onShutterButtonClick(ShutterButton button) { 339b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch (button.getId()) { 340059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin case R.id.video_button: 341de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project if (mMediaRecorderRecording) { 3429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 343de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project stopVideoRecordingAndShowAlert(); 344b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 3459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndGetThumbnail(); 346b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 347b128446b7ef264c33e91e119391045156a19439bWu-cheng Li initializeRecorder(); 3489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 3499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else if (isAlertVisible()) { 3509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 351b128446b7ef264c33e91e119391045156a19439bWu-cheng Li discardCurrentVideoAndInitRecorder(); 3529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 353b128446b7ef264c33e91e119391045156a19439bWu-cheng Li hideAlertAndInitializeRecorder(); 354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 355b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } else if (mRecorderInitialized) { 356b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // If the click comes before recorder initialization, it is 357b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // ignored. If users click the button during initialization, 358b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // the event is put in the queue and record will be started 359b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // eventually. 360de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project startVideoRecording(); 361b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 363b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void doPlayCurrentVideo() { 3670a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang Log.v(TAG, "Playing current video: " + mCurrentVideoUri); 368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri); 369b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project startActivity(intent); 371b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (android.content.ActivityNotFoundException ex) { 372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex); 373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 376b128446b7ef264c33e91e119391045156a19439bWu-cheng Li private void discardCurrentVideoAndInitRecorder() { 377b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project deleteCurrentVideo(); 378b128446b7ef264c33e91e119391045156a19439bWu-cheng Li hideAlertAndInitializeRecorder(); 379b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 380b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 381b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private OnScreenHint mStorageHint; 382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 3839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private void updateAndShowStorageHint(boolean mayHaveSd) { 3849a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project mStorageStatus = getStorageStatus(mayHaveSd); 3859a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project showStorageHint(); 3869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 3889a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private void showStorageHint() { 389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String errorMessage = null; 3909a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project switch (mStorageStatus) { 3919a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project case STORAGE_STATUS_NONE: 392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project errorMessage = getString(R.string.no_storage); 3939a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project break; 3949a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project case STORAGE_STATUS_LOW: 395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project errorMessage = getString(R.string.spaceIsLow_content); 396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (errorMessage != null) { 398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mStorageHint == null) { 399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint = OnScreenHint.makeText(this, errorMessage); 400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.setText(errorMessage); 402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 403b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.show(); 404b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else if (mStorageHint != null) { 405b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.cancel(); 406b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint = null; 407b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 408b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 409b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 4109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private int getStorageStatus(boolean mayHaveSd) { 4119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR; 4129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (remaining == NO_STORAGE_ERROR) { 4139a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project return STORAGE_STATUS_NONE; 4149a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 4159a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project return remaining < LOW_STORAGE_THRESHOLD 4169a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK; 4179a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 4189a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 419845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang private void readVideoSizePreference() { 420845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang boolean videoQualityHigh = getBooleanPreference( 421845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang CameraSettings.KEY_VIDEO_QUALITY, 422845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE); 423845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 42482ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang // 1 minute = 60000ms 42582ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang mMaxVideoDurationInMs = 60000 * getIntPreference( 42682ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang CameraSettings.KEY_VIDEO_DURATION, 42782ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang CameraSettings.DEFAULT_VIDEO_DURATION_VALUE); 42882ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang 429845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Intent intent = getIntent(); 430845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) { 431845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang int extraVideoQuality = intent.getIntExtra( 432845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang MediaStore.EXTRA_VIDEO_QUALITY, 0); 433845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang videoQualityHigh = (extraVideoQuality > 0); 434845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 435845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 436845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang if (videoQualityHigh) { 437845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // CIF size 438845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoWidth = 352; 439845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoHeight = 288; 440845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } else { 441845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // QCIF size 442845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoWidth = 176; 443845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoHeight = 144; 444845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 445845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 446845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onResume() { 449b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onResume(); 450845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mPausing = false; 451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutLong(); 453845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang readVideoSizePreference(); 454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // install an intent filter to receive SD card related events. 456d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang IntentFilter intentFilter = 457d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); 458b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_EJECT); 459b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); 460b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); 461b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); 462b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addDataScheme("file"); 463b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project registerReceiver(mReceiver, intentFilter); 4649a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project mStorageStatus = getStorageStatus(true); 4659a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 4669a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project mHandler.postDelayed(new Runnable() { 4679a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project public void run() { 4689a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project showStorageHint(); 4699a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 4709a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project }, 200); 471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 472b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mSurfaceHolder != null) { 473b128446b7ef264c33e91e119391045156a19439bWu-cheng Li startPreview(); 474b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 475b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.sendEmptyMessage(INIT_RECORDER); 476b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 477b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 478b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 479845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang private void setCameraParameters() { 480845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang android.hardware.Camera.Parameters param; 481845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang param = mCameraDevice.getParameters(); 482845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang param.setPreviewSize(mVideoWidth, mVideoHeight); 483845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.setParameters(param); 484845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 485845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 486845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // Precondition: mSurfaceHolder != null 487acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang // Returns true if starting preview succeeds. 488acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang private boolean startPreview() { 489059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.review_indicator).setVisibility(View.INVISIBLE); 490059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.video_indicator).setVisibility(View.VISIBLE); 491059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 492845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.v(TAG, "startPreview"); 493ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li if (mPreviewing) { 494d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang // We should just return here, but we stop and start again to avoid 495d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang // the bug in driver. 496d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang mCameraDevice.lock(); 497d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang mCameraDevice.stopPreview(); 498d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang mCameraDevice.startPreview(); 499d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang mCameraDevice.unlock(); 500acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return true; 501845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 502ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 503ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li if (mCameraDevice == null) { 504ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // If the activity is paused and resumed, camera device has been 505ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // released and we need to open the camera. 506ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li mCameraDevice = android.hardware.Camera.open(); 507ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li } 508ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 509845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang setCameraParameters(); 510845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang try { 511845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.setPreviewDisplay(mSurfaceHolder); 512845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } catch (IOException ex) { 513845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.release(); 514845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice = null; 515845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.e(TAG, "failed to set preview display"); 516acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return false; 517845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 518ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 519845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang try { 520845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.startPreview(); 521ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li mPreviewing = true; 522845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } catch (Throwable ex) { 523845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // TODO: change Throwable to IOException once 524845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // android.hardware.Camera.startPreview properly declares 525845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // that it throws IOException. 526845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.release(); 527845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice = null; 528845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.e(TAG, "failed to start preview"); 529acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return false; 530845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 531845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.unlock(); 532acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return true; 533845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 534845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 535d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang private void closeCamera() { 536d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang Log.v(TAG, "closeCamera"); 537845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang if (mCameraDevice == null) { 538845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.d(TAG, "already stopped."); 539845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang return; 540845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 541fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li // If we don't lock the camera, release() will fail. 542fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li mCameraDevice.lock(); 543845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.release(); 544845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice = null; 545ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li mPreviewing = false; 546845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 547845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 548b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 549b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onStop() { 550b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutSystemDefault(); 551b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onStop(); 552b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 553b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 554b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 555b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project protected void onPause() { 556b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onPause(); 557b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 558fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li mPausing = true; 559fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li 5609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // This is similar to what mShutterButton.performClick() does, 5619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // but not quite the same. 5629bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mMediaRecorderRecording) { 5639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 5649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndShowAlert(); 5659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 5669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndGetThumbnail(); 5679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 5689bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 5699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecording(); 5709bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 571fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li closeCamera(); 572b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 5739c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project unregisterReceiver(mReceiver); 574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutSystemDefault(); 575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 5769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (!mIsVideoCaptureIntent) { 5779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.storeData(ImageManager.getLastVideoThumbPath()); 5789bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 579095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin 580b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mStorageHint != null) { 581b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.cancel(); 582b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint = null; 583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 584845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 585b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.removeMessages(INIT_RECORDER); 586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 588b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 590fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li // Do not handle any key if the activity is paused. 591fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li if (mPausing) { 592fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li return true; 593fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li } 594fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li 595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutLong(); 596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 597b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch (keyCode) { 598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_BACK: 599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording) { 600de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 602d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } else if (isAlertVisible()) { 603b128446b7ef264c33e91e119391045156a19439bWu-cheng Li hideAlertAndInitializeRecorder(); 604b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 605b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 606b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 607b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_CAMERA: 608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (event.getRepeatCount() == 0) { 609de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 612de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project break; 613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (event.getRepeatCount() == 0) { 615de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 616de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project return true; 617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_MENU: 620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording) { 621de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return super.onKeyDown(keyCode, event); 628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 629b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 630b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 631b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 632b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch(keyCode) { 633b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_CAMERA: 634b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mShutterButton.setPressed(false); 635b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 636b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 637b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return super.onKeyUp(keyCode, event); 638b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 639b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 640b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 641314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber if (mPausing) { 642314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // We're pausing, the screen is off and we already stopped 643314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // video recording. We don't want to start the camera again 644314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // in this case in order to conserve power. 645314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // The fact that surfaceChanged is called _after_ an onPause appears 646314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // to be legitimate since in that case the lockscreen always returns 647314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // to portrait orientation possibly triggering the notification. 648314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber return; 649314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber } 650314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber 651b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mMediaRecorderRecording) { 652b128446b7ef264c33e91e119391045156a19439bWu-cheng Li stopVideoRecording(); 653b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 654b128446b7ef264c33e91e119391045156a19439bWu-cheng Li 655b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // Start the preview if it is not started yet. Preview may be already 656b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // started in onResume and then surfaceChanged is called due to 657b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // orientation change. 658b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (!mPreviewing) { 659b128446b7ef264c33e91e119391045156a19439bWu-cheng Li startPreview(); 660b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 661b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.sendEmptyMessage(INIT_RECORDER); 662b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void surfaceCreated(SurfaceHolder holder) { 666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mSurfaceHolder = holder; 667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void surfaceDestroyed(SurfaceHolder holder) { 670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mSurfaceHolder = null; 671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 6730a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang private void gotoGallery() { 674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project MenuHelper.gotoCameraVideoGallery(this); 675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onPrepareOptionsMenu(Menu menu) { 679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onPrepareOptionsMenu(menu); 680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) { 682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (i != MenuHelper.GENERIC_ITEM) { 683b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project menu.setGroupVisible(i, false); 684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true); 688b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 689b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 690b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onCreateOptionsMenu(Menu menu) { 693b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onCreateOptionsMenu(menu); 694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 6959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 696b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // No options menu for attach mode. 697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return false; 698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project addBaseMenuItems(menu); 700d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang int menuFlags = MenuHelper.INCLUDE_ALL 701d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang & ~MenuHelper.INCLUDE_ROTATE_MENU 702095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin & ~MenuHelper.INCLUDE_DETAILS_MENU; 703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project MenuHelper.addImageMenuItems( 704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project menu, 705095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin menuFlags, 706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project false, 707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project VideoCamera.this, 70823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen mHandler, 709b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Handler for deletion 710b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project new Runnable() { 711b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void run() { 712b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // What do we do here? 713b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // mContentResolver.delete(uri, null, null); 714b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 715b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project }, 716b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project new MenuHelper.MenuInvoker() { 717b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void run(final MenuHelper.MenuCallback cb) { 718b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 719b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project }); 720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 721d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM, 722d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MENU_SAVE_GALLERY_PHOTO, 0, 723d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang R.string.camera_gallery_photos_text) 724d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .setOnMenuItemClickListener( 725d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang new MenuItem.OnMenuItemClickListener() { 726d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang public boolean onMenuItemClick(MenuItem item) { 727d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang gotoGallery(); 728d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return true; 729d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 730d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang }); 731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project gallery.setIcon(android.R.drawable.ic_menu_gallery); 732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private boolean isVideoCaptureIntent() { 737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String action = getIntent().getAction(); 738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action)); 739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void doReturnToCaller(boolean success) { 742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Intent resultIntent = new Intent(); 743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int resultCode; 744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (success) { 745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project resultCode = RESULT_OK; 746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project resultIntent.setData(mCurrentVideoUri); 747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project resultCode = RESULT_CANCELED; 749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setResult(resultCode, resultIntent); 751b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project finish(); 752b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 754b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /** 755b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Returns 756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * @return number of bytes available, or an ERROR code. 757b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static long getAvailableStorage() { 759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (!ImageManager.hasStorage()) { 761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return NO_STORAGE_ERROR; 762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 763d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String storageDirectory = Environment 764d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .getExternalStorageDirectory().toString(); 765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project StatFs stat = new StatFs(storageDirectory); 766d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return ((long) stat.getAvailableBlocks() 767d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang * (long) stat.getBlockSize()); 768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 76923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } catch (RuntimeException ex) { 770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // if we can't stat the filesystem then we don't know how many 771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // free bytes exist. It might be zero but just leave it 772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // blank since we really don't know. 773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return CANNOT_STAT_ERROR; 774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 775b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 776b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 777b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void cleanupEmptyFile() { 778b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCameraVideoFilename != null) { 779b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project File f = new File(mCameraVideoFilename); 780b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (f.length() == 0 && f.delete()) { 781b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename); 782b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFilename = null; 783b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 784b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 785b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 787845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang private android.hardware.Camera mCameraDevice; 788b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // initializeRecorder() prepares media recorder. Return false if fails. 789b128446b7ef264c33e91e119391045156a19439bWu-cheng Li private boolean initializeRecorder() { 790b128446b7ef264c33e91e119391045156a19439bWu-cheng Li Log.v(TAG, "initializeRecorder"); 791b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mRecorderInitialized) return true; 7929bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 793b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // We will call initializeRecorder() again when the alert is hidden. 79423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen if (isAlertVisible()) { 79523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen return false; 79623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } 7979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Intent intent = getIntent(); 799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Bundle myExtras = intent.getExtras(); 800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 8019bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent && myExtras != null) { 802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); 803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (saveUri != null) { 804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFileDescriptor = mContentResolver. 806b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project openFileDescriptor(saveUri, "rw").getFileDescriptor(); 807b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoUri = saveUri; 808d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } catch (java.io.FileNotFoundException ex) { 809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // invalid uri 810b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, ex.toString()); 811b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 812b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project releaseMediaRecorder(); 815b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 816b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder = new MediaRecorder(); 817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 818845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mMediaRecorder.setCamera(mCameraDevice); 819d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 82282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs); 8238d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project 8249a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (mStorageStatus != STORAGE_STATUS_OK) { 825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFile("/dev/null"); 826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 827d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // We try Uri in intent first. If it doesn't work, use our own 828d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // instead. 829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCameraVideoFileDescriptor != null) { 830b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor); 831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 832b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project createVideoPath(); 833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFile(mCameraVideoFilename); 834b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 835b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 836b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 837b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Use the same frame rate for both, since internally 838b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // if the frame rate is too large, it can cause camera to become 839b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // unstable. We need to fix the MediaRecorder to disable the support 840b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // of setting frame rate for now. 841b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setVideoFrameRate(20); 842845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mMediaRecorder.setVideoSize(mVideoWidth, mVideoHeight); 843b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); 844d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 845b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 846de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 847de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project long remaining = getAvailableStorage(); 848de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter 849d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // of that to make it more likely that recording can complete 850d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // successfully. 851de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project try { 852d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mMediaRecorder.setMaxFileSize(remaining - 853d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang LOW_STORAGE_THRESHOLD / 4); 854de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } catch (RuntimeException exception) { 855de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // We are going to ignore failure of setMaxFileSize here, as 856de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // a) The composer selected may simply not support it, or 857de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // b) The underlying media framework may not handle 64-bit range 858de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // on the size restriction. 859de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 860de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 861b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 862b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.prepare(); 863b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (IOException exception) { 864b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "prepare failed for " + mCameraVideoFilename); 865b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project releaseMediaRecorder(); 866b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // TODO: add more exception handling logic here 867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return false; 868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorderRecording = false; 8709bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 871ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // Update the last video thumbnail. 872b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (!mIsVideoCaptureIntent) { 873b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (!mThumbController.isUriValid()) { 874b128446b7ef264c33e91e119391045156a19439bWu-cheng Li updateLastVideo(); 875b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 876b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mThumbController.updateDisplayIfNeeded(); 8779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 878b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = true; 879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void releaseMediaRecorder() { 883b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Releasing media recorder."); 884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorder != null) { 885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project cleanupEmptyFile(); 886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.reset(); 887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.release(); 888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder = null; 889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private int getIntPreference(String key, int defaultValue) { 893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String s = mPreferences.getString(key, ""); 894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int result = defaultValue; 895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project result = Integer.parseInt(s); 897b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (NumberFormatException e) { 898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Ignore, result is already the default value. 899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return result; 901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private boolean getBooleanPreference(String key, boolean defaultValue) { 904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return getIntPreference(key, defaultValue ? 1 : 0) != 0; 905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void createVideoPath() { 908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project long dateTaken = System.currentTimeMillis(); 909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String title = createName(dateTaken); 910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String displayName = title + ".3gp"; // Used when emailing. 911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME; 912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project File cameraDir = new File(cameraDirPath); 913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project cameraDir.mkdirs(); 914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project SimpleDateFormat dateFormat = new SimpleDateFormat( 915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project getString(R.string.video_file_name_format)); 916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Date date = new Date(dateTaken); 917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String filepart = dateFormat.format(date); 918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String filename = cameraDirPath + "/" + filepart + ".3gp"; 919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project ContentValues values = new ContentValues(7); 920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.TITLE, title); 921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.DISPLAY_NAME, displayName); 922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.DATE_TAKEN, dateTaken); 923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.MIME_TYPE, "video/3gpp"); 924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.DATA, filename); 925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFilename = filename; 926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename); 927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoValues = values; 928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void registerVideo() { 931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCameraVideoFileDescriptor == null) { 932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Uri videoTable = Uri.parse("content://media/external/video/media"); 933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoUri = mContentResolver.insert(videoTable, 934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoValues); 935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Current video URI: " + mCurrentVideoUri); 936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 937b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoValues = null; 938b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void deleteCurrentVideo() { 941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCurrentVideoFilename != null) { 942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project deleteVideoFile(mCurrentVideoFilename); 943b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoFilename = null; 944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCurrentVideoUri != null) { 946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mContentResolver.delete(mCurrentVideoUri, null, null); 947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoUri = null; 948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 949de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project updateAndShowStorageHint(true); 950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 951b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 952b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void deleteVideoFile(String fileName) { 953b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Deleting video " + fileName); 954b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project File f = new File(fileName); 955d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (!f.delete()) { 956b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Could not delete " + fileName); 957b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 958b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void addBaseMenuItems(Menu menu) { 961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project MenuHelper.addSwitchModeMenuItem(menu, this, false); 962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project { 963d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM, 964d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text) 965d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .setOnMenuItemClickListener(new OnMenuItemClickListener() { 966d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang public boolean onMenuItemClick(MenuItem item) { 967d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang gotoGallery(); 968d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return true; 969d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 970d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang }); 971b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project gallery.setIcon(android.R.drawable.ic_menu_gallery); 972b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mGalleryItems.add(gallery); 973b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 974b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project { 975d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM, 976d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MENU_GALLERY_VIDEOS, 0, R.string.camera_gallery_photos_text) 977d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .setOnMenuItemClickListener(new OnMenuItemClickListener() { 978d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang public boolean onMenuItemClick(MenuItem item) { 979d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang gotoGallery(); 980d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return true; 981d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 982d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang }); 983b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project gallery.setIcon(android.R.drawable.ic_menu_gallery); 984b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mGalleryItems.add(gallery); 985b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 987d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MenuItem item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0, 988d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang R.string.settings) 989d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .setOnMenuItemClickListener(new OnMenuItemClickListener() { 990d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang public boolean onMenuItemClick(MenuItem item) { 991d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang Intent intent = new Intent(); 992d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang intent.setClass(VideoCamera.this, CameraSettings.class); 993d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang startActivity(intent); 994d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return true; 995d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 996d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang }); 997b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project item.setIcon(android.R.drawable.ic_menu_preferences); 998b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 999b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1000b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // from MediaRecorder.OnErrorListener 1001b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onError(MediaRecorder mr, int what, int extra) { 1002b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { 1003b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // We may have run out of space on the sdcard. 1004b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project stopVideoRecording(); 10059a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project updateAndShowStorageHint(true); 1006b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1007b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1008b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 10098d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project // from MediaRecorder.OnInfoListener 10108d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project public void onInfo(MediaRecorder mr, int what, int extra) { 10118d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { 1012de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 1013d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } else if (what 1014d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) { 1015de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 1016de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project updateAndShowStorageHint(true); 10178d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project } 10188d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project } 10198d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project 10209c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project /* 10219c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project * Make sure we're not recording music playing in the background, ask 10229c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project * the MediaPlaybackService to pause playback. 10239c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project */ 10249c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project private void pauseAudioPlayback() { 10259c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project // Shamelessly copied from MediaPlaybackService.java, which 10269c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project // should be public, but isn't. 10279c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project Intent i = new Intent("com.android.music.musicservicecommand"); 10289c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project i.putExtra("command", "pause"); 10299c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project 10309c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project sendBroadcast(i); 10319c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project } 10329c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project 1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void startVideoRecording() { 1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "startVideoRecording"); 1035b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (!mMediaRecorderRecording) { 1036b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 10379a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (mStorageStatus != STORAGE_STATUS_OK) { 1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Storage issue, ignore the start request"); 1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return; 1040b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1041b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Check mMediaRecorder to see whether it is initialized or not. 1043b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mMediaRecorder == null) { 1044b128446b7ef264c33e91e119391045156a19439bWu-cheng Li Log.e(TAG, "MediaRecorder is not initialized."); 1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return; 1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 10489c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project pauseAudioPlayback(); 10499c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project 1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOnErrorListener(this); 10528d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project mMediaRecorder.setOnInfoListener(this); 1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.start(); // Recording is now started 1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (RuntimeException e) { 1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "Could not start media recorder. ", e); 1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return; 1057b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1058b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorderRecording = true; 1059b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingStartTime = SystemClock.uptimeMillis(); 1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project updateRecordingIndicator(true); 1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingTimeView.setText(""); 1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingTimeView.setVisibility(View.VISIBLE); 1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.sendEmptyMessage(UPDATE_RECORD_TIME); 1064b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutInfinite(); 1065b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1066b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void updateRecordingIndicator(boolean showRecording) { 1069d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang int drawableId = showRecording 1070059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin ? R.drawable.ic_camera_indicator_stop 1071d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang : R.drawable.ic_camera_indicator_video; 1072b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Drawable drawable = getResources().getDrawable(drawableId); 1073b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mShutterButton.setImageDrawable(drawable); 1074b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1075b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 10769bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void stopVideoRecordingAndGetThumbnail() { 10779bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecording(); 10789bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang acquireVideoThumb(); 1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1081de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project private void stopVideoRecordingAndShowAlert() { 1082de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project stopVideoRecording(); 10839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang showAlert(); 1084de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1085de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 10869bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void showAlert() { 1087059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.review_indicator).setVisibility(View.VISIBLE); 1088059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.video_indicator).setVisibility(View.INVISIBLE); 1089059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 1090b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] pickIds = {R.id.attach, R.id.cancel}; 1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] normalIds = {R.id.gallery, R.id.share, R.id.discard}; 1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] alwaysOnIds = {R.id.play}; 1093b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] hideIds = pickIds; 1094b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] connectIds = normalIds; 10959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 1096b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project hideIds = normalIds; 1097b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project connectIds = pickIds; 1098b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1099d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang for (int id : hideIds) { 1100b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mPostPictureAlert.findViewById(id).setVisibility(View.GONE); 1101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1102b653f90f33c6f9e6b48dfab018dece9dd021a476Chih-Chung Chang 1103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project connectAndFadeIn(connectIds); 1104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project connectAndFadeIn(alwaysOnIds); 1105b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mPostPictureAlert.setVisibility(View.VISIBLE); 1106059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mVideoPreview.setVisibility(View.INVISIBLE); 11079bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 11089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // There are two cases we are here: 11099bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // (1) We are in a capture video intent, and we are reviewing the video 1110095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin // we just taken. 11119bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // (2) The thumbnail button is clicked: we review the video associated 11129bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // with the thumbnail. 11139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // For the second case, we copy the associated URI and filename to 11149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown 11159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // and the target for actions (play, delete, ...) will be correct. 11169bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 11179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (!mIsVideoCaptureIntent) { 1118cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync if (mThumbController.isUriValid()) { 1119cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync mCurrentVideoUri = mThumbController.getUri(); 1120cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync mCurrentVideoFilename = getDataPath(mCurrentVideoUri); 1121cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync } else { 1122cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync return; 1123cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync } 11249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 11259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 11269bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang String path = mCurrentVideoFilename; 11279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (path != null) { 1128101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap videoFrame = Util.createVideoThumbnail(path); 11299bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mVideoFrame.setImageBitmap(videoFrame); 11309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mVideoFrame.setVisibility(View.VISIBLE); 11319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 1132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 11349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void hideAlert() { 1135059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mVideoPreview.setVisibility(View.VISIBLE); 1136de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mVideoFrame.setVisibility(View.INVISIBLE); 1137de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mPostPictureAlert.setVisibility(View.INVISIBLE); 1138de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project showLastPictureButton(); 1139de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1140de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void connectAndFadeIn(int[] connectIds) { 1142d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang for (int id : connectIds) { 1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project View view = mPostPictureAlert.findViewById(id); 1144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project view.setOnClickListener(this); 1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Animation animation = new AlphaAnimation(0F, 1F); 1146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project animation.setDuration(500); 11479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang view.startAnimation(animation); 1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1150b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 11519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private boolean isAlertVisible() { 1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return mPostPictureAlert.getVisibility() == View.VISIBLE; 1153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void stopVideoRecording() { 1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "stopVideoRecording"); 1157b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project boolean needToRegisterRecording = false; 1158b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording || mMediaRecorder != null) { 1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording && mMediaRecorder != null) { 1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOnErrorListener(null); 11628d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project mMediaRecorder.setOnInfoListener(null); 1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.stop(); 1164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (RuntimeException e) { 1165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "stop fail: " + e.getMessage()); 1166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 11678d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project 1168b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoFilename = mCameraVideoFilename; 1169d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang Log.v(TAG, "Setting current video filename: " 1170d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang + mCurrentVideoFilename); 1171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project needToRegisterRecording = true; 1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorderRecording = false; 1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project releaseMediaRecorder(); 1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project updateRecordingIndicator(false); 1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingTimeView.setVisibility(View.GONE); 1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutLong(); 1178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 11799a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) { 11809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project registerVideo(); 11819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 1182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFilename = null; 1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFileDescriptor = null; 1185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenTimeoutSystemDefault() { 1188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.removeMessages(CLEAR_SCREEN_DELAY); 1189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project clearScreenOnFlag(); 1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenTimeoutLong() { 1193b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.removeMessages(CLEAR_SCREEN_DELAY); 1194b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenOnFlag(); 1195b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); 1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenTimeoutInfinite() { 1199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.removeMessages(CLEAR_SCREEN_DELAY); 1200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenOnFlag(); 1201b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1202b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1203b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void clearScreenOnFlag() { 1204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Window w = getWindow(); 1205d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 1206d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if ((w.getAttributes().flags & flag) != 0) { 1207d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang w.clearFlags(flag); 1208b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1209b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1210b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenOnFlag() { 1212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Window w = getWindow(); 1213d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 1214d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if ((w.getAttributes().flags & flag) == 0) { 1215d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang w.addFlags(flag); 1216b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1217b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1218b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1219b128446b7ef264c33e91e119391045156a19439bWu-cheng Li private void hideAlertAndInitializeRecorder() { 12209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang hideAlert(); 1221b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 1222b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.sendEmptyMessage(INIT_RECORDER); 1223b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1224b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 12259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void acquireVideoThumb() { 1226101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename); 12279bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.setData(mCurrentVideoUri, videoFrame); 1228de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1229de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 12309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void showLastPictureButton() { 12319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (!mIsVideoCaptureIntent) { 12329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mLastPictureButton.setVisibility(View.VISIBLE); 1233de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 12349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 1235de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 12369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private static ImageManager.DataLocation dataLocation() { 12379bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang return ImageManager.DataLocation.EXTERNAL; 1238de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1239de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 12409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void updateLastVideo() { 124158e94eddd371a9bb7c04936dbeb99615fd1a0c2cChih-Chung Chang IImageList list = ImageManager.allImages( 12429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mContentResolver, 12439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang dataLocation(), 12449bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang ImageManager.INCLUDE_VIDEOS, 12459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang ImageManager.SORT_ASCENDING, 12469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang ImageManager.CAMERA_IMAGE_BUCKET_ID); 12479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang int count = list.getCount(); 12489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (count > 0) { 1249d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang IImage image = list.getImageAt(count - 1); 12509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang Uri uri = image.fullSizeImageUri(); 12519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.setData(uri, image.miniThumbBitmap()); 12529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 12539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.setData(null, null); 12549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 12559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang list.deactivate(); 1256b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1257b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 12589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private static final String[] DATA_PATH_PROJECTION = new String[] { 12599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang "_data" 12609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang }; 12619bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 12629bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private String getDataPath(Uri uri) { 12639bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang Cursor c = null; 12649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang try { 1265d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null, 1266d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang null); 12679bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (c != null && c.moveToFirst()) { 12689bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang return c.getString(0); 12699bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 12709bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang return null; 12719bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 12729bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } finally { 127323c51b794e95c201290e36737f379c4bb8eefeaeRay Chen if (c != null) { 127423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen c.close(); 127523c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } 1276b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1277b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1278d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1279d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang private void updateRecordingTime() { 128023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen if (!mMediaRecorderRecording) { 128123c51b794e95c201290e36737f379c4bb8eefeaeRay Chen return; 128223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } 1283d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long now = SystemClock.uptimeMillis(); 1284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long delta = now - mRecordingStartTime; 1285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1286d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // Starting a minute before reaching the max duration 1287d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // limit, we'll countdown the remaining time instead. 1288d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang boolean countdownRemainingTime = 128982ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang (delta >= mMaxVideoDurationInMs - 60000); 1290d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1291d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (countdownRemainingTime) { 129282ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang delta = Math.max(0, mMaxVideoDurationInMs - delta); 1293d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1294d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1295d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long seconds = (delta + 500) / 1000; // round to nearest 1296d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long minutes = seconds / 60; 1297d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long hours = minutes / 60; 1298d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long remainderMinutes = minutes - (hours * 60); 1299d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long remainderSeconds = seconds - (minutes * 60); 1300d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1301d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String secondsString = Long.toString(remainderSeconds); 1302d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (secondsString.length() < 2) { 1303d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang secondsString = "0" + secondsString; 1304d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1305d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String minutesString = Long.toString(remainderMinutes); 1306d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (minutesString.length() < 2) { 1307d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang minutesString = "0" + minutesString; 1308d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1309d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String text = minutesString + ":" + secondsString; 1310d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (hours > 0) { 1311d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String hoursString = Long.toString(hours); 1312d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (hoursString.length() < 2) { 1313d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang hoursString = "0" + hoursString; 1314d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1315d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang text = hoursString + ":" + text; 1316d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1317d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mRecordingTimeView.setText(text); 1318d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1319d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (mRecordingTimeCountsDown != countdownRemainingTime) { 1320d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // Avoid setting the color on every update, do it only 1321d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // when it needs changing. 1322d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1323d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mRecordingTimeCountsDown = countdownRemainingTime; 1324d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1325d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang int color = getResources().getColor( 1326d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang countdownRemainingTime 1327d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang ? R.color.recording_time_remaining_text 1328d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang : R.color.recording_time_elapsed_text); 1329d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1330d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mRecordingTimeView.setTextColor(color); 1331d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1332d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1333d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // Work around a limitation of the T-Mobile G1: The T-Mobile 1334d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // hardware blitter can't pixel-accurately scale and clip at the 1335d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // same time, and the SurfaceFlinger doesn't attempt to work around 1336d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // this limitation. In order to avoid visual corruption we must 1337d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // manually refresh the entire surface view when changing any 1338d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // overlapping view's contents. 1339d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mVideoPreview.invalidate(); 1340d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000); 1341d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1342b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project} 1343