VideoCamera.java revision cd65be31531717fb032b7423f8d5a77df465cfca
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() { 218cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice = CameraHolder.instance().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 case R.id.gallery: 2950a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang gotoGallery(); 296b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 297b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.attach: 298b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project doReturnToCaller(true); 299b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 300b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.cancel: 301b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project doReturnToCaller(false); 302b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 303b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.discard: { 3047638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen Runnable deleteCallback = new Runnable() { 3057638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen public void run() { 306b128446b7ef264c33e91e119391045156a19439bWu-cheng Li discardCurrentVideoAndInitRecorder(); 3077638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen } 3087638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen }; 3097638a541959f3f371b9998844a0bbef2df4aa3eeRay Chen MenuHelper.deleteVideo(this, deleteCallback); 310b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 311b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 312b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.share: { 313e3f4516c2154539cb5778ef061abf8a0ccf90a5eThe Android Open Source Project startShareVideoActivity(); 314b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 315b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 316b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case R.id.play: { 317b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project doPlayCurrentVideo(); 318b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 319b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 320059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin case R.id.review_button: { 3219bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndShowAlert(); 322de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project break; 323de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 324b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 325b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 326b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 327b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onShutterButtonFocus(ShutterButton button, boolean pressed) { 328de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // Do nothing (everything happens in onShutterButtonClick). 329de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 330de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 331de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project public void onShutterButtonClick(ShutterButton button) { 332b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch (button.getId()) { 333059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin case R.id.video_button: 334de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project if (mMediaRecorderRecording) { 3359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 336de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project stopVideoRecordingAndShowAlert(); 337b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 3389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndGetThumbnail(); 339b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 340b128446b7ef264c33e91e119391045156a19439bWu-cheng Li initializeRecorder(); 3419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 3429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else if (isAlertVisible()) { 3439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 344b128446b7ef264c33e91e119391045156a19439bWu-cheng Li discardCurrentVideoAndInitRecorder(); 3459bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 346b128446b7ef264c33e91e119391045156a19439bWu-cheng Li hideAlertAndInitializeRecorder(); 347b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 348b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } else if (mRecorderInitialized) { 349b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // If the click comes before recorder initialization, it is 350b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // ignored. If users click the button during initialization, 351b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // the event is put in the queue and record will be started 352b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // eventually. 353de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project startVideoRecording(); 354b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 355b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 356b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 357b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 358b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 359b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void doPlayCurrentVideo() { 3600a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang Log.v(TAG, "Playing current video: " + mCurrentVideoUri); 361b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri); 362b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 363b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project startActivity(intent); 364b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (android.content.ActivityNotFoundException ex) { 365b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex); 366b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 367b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 368b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 369b128446b7ef264c33e91e119391045156a19439bWu-cheng Li private void discardCurrentVideoAndInitRecorder() { 370b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project deleteCurrentVideo(); 371b128446b7ef264c33e91e119391045156a19439bWu-cheng Li hideAlertAndInitializeRecorder(); 372b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 373b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 374b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private OnScreenHint mStorageHint; 375b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 3769a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private void updateAndShowStorageHint(boolean mayHaveSd) { 3779a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project mStorageStatus = getStorageStatus(mayHaveSd); 3789a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project showStorageHint(); 3799a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 3809a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 3819a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private void showStorageHint() { 382b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String errorMessage = null; 3839a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project switch (mStorageStatus) { 3849a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project case STORAGE_STATUS_NONE: 385b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project errorMessage = getString(R.string.no_storage); 3869a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project break; 3879a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project case STORAGE_STATUS_LOW: 388b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project errorMessage = getString(R.string.spaceIsLow_content); 389b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 390b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (errorMessage != null) { 391b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mStorageHint == null) { 392b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint = OnScreenHint.makeText(this, errorMessage); 393b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 394b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.setText(errorMessage); 395b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 396b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.show(); 397b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else if (mStorageHint != null) { 398b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.cancel(); 399b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint = null; 400b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 401b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 402b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 4039a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project private int getStorageStatus(boolean mayHaveSd) { 4049a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR; 4059a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (remaining == NO_STORAGE_ERROR) { 4069a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project return STORAGE_STATUS_NONE; 4079a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 4089a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project return remaining < LOW_STORAGE_THRESHOLD 4099a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project ? STORAGE_STATUS_LOW : STORAGE_STATUS_OK; 4109a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 4119a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 412845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang private void readVideoSizePreference() { 413845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang boolean videoQualityHigh = getBooleanPreference( 414845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang CameraSettings.KEY_VIDEO_QUALITY, 415845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE); 416845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 41782ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang // 1 minute = 60000ms 41882ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang mMaxVideoDurationInMs = 60000 * getIntPreference( 41982ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang CameraSettings.KEY_VIDEO_DURATION, 42082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang CameraSettings.DEFAULT_VIDEO_DURATION_VALUE); 42182ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang 422845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Intent intent = getIntent(); 423845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) { 424845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang int extraVideoQuality = intent.getIntExtra( 425845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang MediaStore.EXTRA_VIDEO_QUALITY, 0); 426845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang videoQualityHigh = (extraVideoQuality > 0); 427845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 428845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 429845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang if (videoQualityHigh) { 430845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // CIF size 431845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoWidth = 352; 432845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoHeight = 288; 433845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } else { 434845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // QCIF size 435845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoWidth = 176; 436845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mVideoHeight = 144; 437845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 438845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 439845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 440b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 441b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onResume() { 442b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onResume(); 443845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mPausing = false; 444b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 445b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutLong(); 446845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang readVideoSizePreference(); 447b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 448b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // install an intent filter to receive SD card related events. 449d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang IntentFilter intentFilter = 450d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); 451b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_EJECT); 452b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); 453b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); 454b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); 455b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project intentFilter.addDataScheme("file"); 456b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project registerReceiver(mReceiver, intentFilter); 4579a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project mStorageStatus = getStorageStatus(true); 4589a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project 4599a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project mHandler.postDelayed(new Runnable() { 4609a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project public void run() { 4619a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project showStorageHint(); 4629a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 4639a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project }, 200); 464b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 465b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mSurfaceHolder != null) { 466b128446b7ef264c33e91e119391045156a19439bWu-cheng Li startPreview(); 467b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 468b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.sendEmptyMessage(INIT_RECORDER); 469b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 470b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 471b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 472845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang private void setCameraParameters() { 473845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang android.hardware.Camera.Parameters param; 474845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang param = mCameraDevice.getParameters(); 475845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang param.setPreviewSize(mVideoWidth, mVideoHeight); 476845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.setParameters(param); 477845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 478845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 479845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // Precondition: mSurfaceHolder != null 480acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang // Returns true if starting preview succeeds. 481acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang private boolean startPreview() { 482059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.review_indicator).setVisibility(View.INVISIBLE); 483059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.video_indicator).setVisibility(View.VISIBLE); 484059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 485845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.v(TAG, "startPreview"); 486ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li if (mPreviewing) { 4871fb8ac4e3e03f31e6e099776d1026b9cadf57610Chih-Chung Chang // After recording a video, preview is not stopped. So just return. 488acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return true; 489845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 490ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 491ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li if (mCameraDevice == null) { 492ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // If the activity is paused and resumed, camera device has been 493ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // released and we need to open the camera. 494cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang mCameraDevice = CameraHolder.instance().open(); 495ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li } 496ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 497845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang setCameraParameters(); 498845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang try { 499845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.setPreviewDisplay(mSurfaceHolder); 500845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } catch (IOException ex) { 501cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang CameraHolder.instance().release(); 502845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice = null; 503845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.e(TAG, "failed to set preview display"); 504acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return false; 505845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 506ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li 507845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang try { 508845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.startPreview(); 509ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li mPreviewing = true; 510845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } catch (Throwable ex) { 511845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // TODO: change Throwable to IOException once 512845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // android.hardware.Camera.startPreview properly declares 513845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang // that it throws IOException. 514cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang CameraHolder.instance().release(); 515845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice = null; 516845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.e(TAG, "failed to start preview"); 517acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return false; 518845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 519845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice.unlock(); 520acdd1d7d819d17f9690d9bfddb7a9aec9dd2210dChih-Chung Chang return true; 521845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 522845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 523d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang private void closeCamera() { 524d55a5e92d6065bd36a60925221d8cc9a773572ebChih-Chung Chang Log.v(TAG, "closeCamera"); 525845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang if (mCameraDevice == null) { 526845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang Log.d(TAG, "already stopped."); 527845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang return; 528845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 529fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li // If we don't lock the camera, release() will fail. 530fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li mCameraDevice.lock(); 531cd65be31531717fb032b7423f8d5a77df465cfcaChih-Chung Chang CameraHolder.instance().release(); 532845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mCameraDevice = null; 533ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li mPreviewing = false; 534845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang } 535845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 536b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 537b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onStop() { 538b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutSystemDefault(); 539b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onStop(); 540b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 541b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 542b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 543b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project protected void onPause() { 544b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onPause(); 545b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 546fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li mPausing = true; 547fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li 5489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // This is similar to what mShutterButton.performClick() does, 5499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // but not quite the same. 5509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mMediaRecorderRecording) { 5519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 5529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndShowAlert(); 5539bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 5549bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecordingAndGetThumbnail(); 5559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 5569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 5579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecording(); 5589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 559fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li closeCamera(); 560b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 5619c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project unregisterReceiver(mReceiver); 562b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutSystemDefault(); 563b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 5649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (!mIsVideoCaptureIntent) { 5659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.storeData(ImageManager.getLastVideoThumbPath()); 5669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 567095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin 568b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mStorageHint != null) { 569b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint.cancel(); 570b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mStorageHint = null; 571b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 572845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang 573b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.removeMessages(INIT_RECORDER); 574b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 575b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 576b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 577b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 578fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li // Do not handle any key if the activity is paused. 579fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li if (mPausing) { 580fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li return true; 581fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li } 582fbdbae6005e1720f2108d9bb345196cb87b22572Wu-cheng Li 583b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutLong(); 584b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 585b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch (keyCode) { 586b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_BACK: 587b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording) { 588de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 589b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 590d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } else if (isAlertVisible()) { 591b128446b7ef264c33e91e119391045156a19439bWu-cheng Li hideAlertAndInitializeRecorder(); 592b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 593b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 594b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 595b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_CAMERA: 596b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (event.getRepeatCount() == 0) { 597de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 598b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 599b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 600de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project break; 601b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 602b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (event.getRepeatCount() == 0) { 603de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 604de365d87520c97d6b1636442e6b5c82a3e036f29The 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_MENU: 608b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording) { 609de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 610b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 611b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 612b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project break; 613b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 614b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 615b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return super.onKeyDown(keyCode, event); 616b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 617b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 618b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 619b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 620b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project switch(keyCode) { 621b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project case KeyEvent.KEYCODE_CAMERA: 622b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mShutterButton.setPressed(false); 623b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 624b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 625b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return super.onKeyUp(keyCode, event); 626b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 627b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 628b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 629314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber if (mPausing) { 630314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // We're pausing, the screen is off and we already stopped 631314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // video recording. We don't want to start the camera again 632314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // in this case in order to conserve power. 633314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // The fact that surfaceChanged is called _after_ an onPause appears 634314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // to be legitimate since in that case the lockscreen always returns 635314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber // to portrait orientation possibly triggering the notification. 636314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber return; 637314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber } 638314f9a79f1395af71f2c2bb629435bfda07a55aeAndreas Huber 639b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mMediaRecorderRecording) { 640b128446b7ef264c33e91e119391045156a19439bWu-cheng Li stopVideoRecording(); 641b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 642b128446b7ef264c33e91e119391045156a19439bWu-cheng Li 643b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // Start the preview if it is not started yet. Preview may be already 644b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // started in onResume and then surfaceChanged is called due to 645b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // orientation change. 646b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (!mPreviewing) { 647b128446b7ef264c33e91e119391045156a19439bWu-cheng Li startPreview(); 648b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 649b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.sendEmptyMessage(INIT_RECORDER); 650b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 651b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 652b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 653b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void surfaceCreated(SurfaceHolder holder) { 654b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mSurfaceHolder = holder; 655b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 656b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 657b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void surfaceDestroyed(SurfaceHolder holder) { 658b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mSurfaceHolder = null; 659b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 660b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 6610a475e11e2ceadbaa70308b52e06f4e6d9e56f12Chih-Chung Chang private void gotoGallery() { 662b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project MenuHelper.gotoCameraVideoGallery(this); 663b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 664b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 665b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 666b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onPrepareOptionsMenu(Menu menu) { 667b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onPrepareOptionsMenu(menu); 668b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 669b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project for (int i = 1; i <= MenuHelper.MENU_ITEM_MAX; i++) { 670b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (i != MenuHelper.GENERIC_ITEM) { 671b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project menu.setGroupVisible(i, false); 672b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 673b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 674b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 675b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project menu.setGroupVisible(MenuHelper.VIDEO_MODE_ITEM, true); 676b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 677b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 678b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 679b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project @Override 680b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public boolean onCreateOptionsMenu(Menu menu) { 681b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project super.onCreateOptionsMenu(menu); 682b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 6839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 684b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // No options menu for attach mode. 685b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return false; 686b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 687b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project addBaseMenuItems(menu); 688d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang int menuFlags = MenuHelper.INCLUDE_ALL 689d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang & ~MenuHelper.INCLUDE_ROTATE_MENU 690095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin & ~MenuHelper.INCLUDE_DETAILS_MENU; 691b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project MenuHelper.addImageMenuItems( 692b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project menu, 693095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin menuFlags, 694b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project false, 695b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project VideoCamera.this, 69623c51b794e95c201290e36737f379c4bb8eefeaeRay Chen mHandler, 697b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Handler for deletion 698b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project new Runnable() { 699b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void run() { 700b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // What do we do here? 701b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // mContentResolver.delete(uri, null, null); 702b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 703b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project }, 704b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project new MenuHelper.MenuInvoker() { 705b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void run(final MenuHelper.MenuCallback cb) { 706b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 707b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project }); 708b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 709d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MenuItem gallery = menu.add(MenuHelper.IMAGE_SAVING_ITEM, 710d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MENU_SAVE_GALLERY_PHOTO, 0, 711d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang R.string.camera_gallery_photos_text) 712d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .setOnMenuItemClickListener( 713d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang new MenuItem.OnMenuItemClickListener() { 714d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang public boolean onMenuItemClick(MenuItem item) { 715d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang gotoGallery(); 716d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return true; 717d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 718d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang }); 719b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project gallery.setIcon(android.R.drawable.ic_menu_gallery); 720b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 721b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 722b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 723b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 724b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private boolean isVideoCaptureIntent() { 725b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String action = getIntent().getAction(); 726b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action)); 727b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 728b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 729b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void doReturnToCaller(boolean success) { 730b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Intent resultIntent = new Intent(); 731b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int resultCode; 732b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (success) { 733b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project resultCode = RESULT_OK; 734b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project resultIntent.setData(mCurrentVideoUri); 735b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 736b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project resultCode = RESULT_CANCELED; 737b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 738b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setResult(resultCode, resultIntent); 739b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project finish(); 740b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 741b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 742b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /** 743b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * Returns 744b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project * @return number of bytes available, or an ERROR code. 745b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project */ 746b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private static long getAvailableStorage() { 747b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 748b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (!ImageManager.hasStorage()) { 749b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return NO_STORAGE_ERROR; 750b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 751d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String storageDirectory = Environment 752d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .getExternalStorageDirectory().toString(); 753b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project StatFs stat = new StatFs(storageDirectory); 754d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return ((long) stat.getAvailableBlocks() 755d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang * (long) stat.getBlockSize()); 756b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 75723c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } catch (RuntimeException ex) { 758b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // if we can't stat the filesystem then we don't know how many 759b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // free bytes exist. It might be zero but just leave it 760b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // blank since we really don't know. 761b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return CANNOT_STAT_ERROR; 762b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 763b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 764b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 765b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void cleanupEmptyFile() { 766b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCameraVideoFilename != null) { 767b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project File f = new File(mCameraVideoFilename); 768b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (f.length() == 0 && f.delete()) { 769b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename); 770b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFilename = null; 771b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 772b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 773b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 774b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 775845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang private android.hardware.Camera mCameraDevice; 776b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // initializeRecorder() prepares media recorder. Return false if fails. 777b128446b7ef264c33e91e119391045156a19439bWu-cheng Li private boolean initializeRecorder() { 778b128446b7ef264c33e91e119391045156a19439bWu-cheng Li Log.v(TAG, "initializeRecorder"); 779b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mRecorderInitialized) return true; 7809bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 781b128446b7ef264c33e91e119391045156a19439bWu-cheng Li // We will call initializeRecorder() again when the alert is hidden. 78223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen if (isAlertVisible()) { 78323c51b794e95c201290e36737f379c4bb8eefeaeRay Chen return false; 78423c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } 7859bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 786b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Intent intent = getIntent(); 787b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Bundle myExtras = intent.getExtras(); 788b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 7899bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent && myExtras != null) { 790b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); 791b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (saveUri != null) { 792b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 793b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFileDescriptor = mContentResolver. 794b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project openFileDescriptor(saveUri, "rw").getFileDescriptor(); 795b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoUri = saveUri; 796d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } catch (java.io.FileNotFoundException ex) { 797b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // invalid uri 798b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, ex.toString()); 799b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 800b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 801b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 802b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project releaseMediaRecorder(); 803b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 804b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder = new MediaRecorder(); 805b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 806845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mMediaRecorder.setCamera(mCameraDevice); 807d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 808b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 809b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 81082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs); 8118d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project 8129a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (mStorageStatus != STORAGE_STATUS_OK) { 813b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFile("/dev/null"); 814b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 815d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // We try Uri in intent first. If it doesn't work, use our own 816d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // instead. 817b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCameraVideoFileDescriptor != null) { 818b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor); 819b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } else { 820b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project createVideoPath(); 821b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOutputFile(mCameraVideoFilename); 822b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 823b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 824b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 825b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Use the same frame rate for both, since internally 826b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // if the frame rate is too large, it can cause camera to become 827b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // unstable. We need to fix the MediaRecorder to disable the support 828b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // of setting frame rate for now. 829b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setVideoFrameRate(20); 830845acccf672f6b5f64381859cf932132ceaca0e1Chih-Chung Chang mMediaRecorder.setVideoSize(mVideoWidth, mVideoHeight); 831b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); 832d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 833b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 834de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 835de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project long remaining = getAvailableStorage(); 836de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter 837d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // of that to make it more likely that recording can complete 838d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // successfully. 839de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project try { 840d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mMediaRecorder.setMaxFileSize(remaining - 841d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang LOW_STORAGE_THRESHOLD / 4); 842de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } catch (RuntimeException exception) { 843de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // We are going to ignore failure of setMaxFileSize here, as 844de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // a) The composer selected may simply not support it, or 845de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // b) The underlying media framework may not handle 64-bit range 846de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project // on the size restriction. 847de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 848de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 849b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 850b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.prepare(); 851b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (IOException exception) { 852b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "prepare failed for " + mCameraVideoFilename); 853b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project releaseMediaRecorder(); 854b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // TODO: add more exception handling logic here 855b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return false; 856b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 857b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorderRecording = false; 8589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 859ac3a8c8ae81482867daa897d5d763e777430de9eWu-cheng Li // Update the last video thumbnail. 860b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (!mIsVideoCaptureIntent) { 861b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (!mThumbController.isUriValid()) { 862b128446b7ef264c33e91e119391045156a19439bWu-cheng Li updateLastVideo(); 863b128446b7ef264c33e91e119391045156a19439bWu-cheng Li } 864b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mThumbController.updateDisplayIfNeeded(); 8659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 866b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = true; 867b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return true; 868b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 869b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 870b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void releaseMediaRecorder() { 871b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Releasing media recorder."); 872b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorder != null) { 873b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project cleanupEmptyFile(); 874b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.reset(); 875b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.release(); 876b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder = null; 877b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 878b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 879b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 880b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private int getIntPreference(String key, int defaultValue) { 881b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String s = mPreferences.getString(key, ""); 882b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int result = defaultValue; 883b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 884b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project result = Integer.parseInt(s); 885b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (NumberFormatException e) { 886b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Ignore, result is already the default value. 887b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 888b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return result; 889b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 890b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 891b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private boolean getBooleanPreference(String key, boolean defaultValue) { 892b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return getIntPreference(key, defaultValue ? 1 : 0) != 0; 893b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 894b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 895b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void createVideoPath() { 896b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project long dateTaken = System.currentTimeMillis(); 897b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String title = createName(dateTaken); 898b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String displayName = title + ".3gp"; // Used when emailing. 899b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME; 900b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project File cameraDir = new File(cameraDirPath); 901b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project cameraDir.mkdirs(); 902b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project SimpleDateFormat dateFormat = new SimpleDateFormat( 903b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project getString(R.string.video_file_name_format)); 904b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Date date = new Date(dateTaken); 905b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String filepart = dateFormat.format(date); 906b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project String filename = cameraDirPath + "/" + filepart + ".3gp"; 907b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project ContentValues values = new ContentValues(7); 908b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.TITLE, title); 909b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.DISPLAY_NAME, displayName); 910b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.DATE_TAKEN, dateTaken); 911b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.MIME_TYPE, "video/3gpp"); 912b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project values.put(Video.Media.DATA, filename); 913b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFilename = filename; 914b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename); 915b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoValues = values; 916b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 917b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 918b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void registerVideo() { 919b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCameraVideoFileDescriptor == null) { 920b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Uri videoTable = Uri.parse("content://media/external/video/media"); 921b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoUri = mContentResolver.insert(videoTable, 922b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoValues); 923b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Current video URI: " + mCurrentVideoUri); 924b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 925b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoValues = null; 926b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 927b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 928b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void deleteCurrentVideo() { 929b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCurrentVideoFilename != null) { 930b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project deleteVideoFile(mCurrentVideoFilename); 931b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoFilename = null; 932b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 933b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mCurrentVideoUri != null) { 934b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mContentResolver.delete(mCurrentVideoUri, null, null); 935b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoUri = null; 936b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 937de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project updateAndShowStorageHint(true); 938b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 939b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 940b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void deleteVideoFile(String fileName) { 941b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Deleting video " + fileName); 942b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project File f = new File(fileName); 943d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (!f.delete()) { 944b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Could not delete " + fileName); 945b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 946b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 947b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 948b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void addBaseMenuItems(Menu menu) { 949b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project MenuHelper.addSwitchModeMenuItem(menu, this, false); 950b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project { 951d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MenuItem gallery = menu.add(MenuHelper.IMAGE_MODE_ITEM, 952d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MENU_GALLERY_PHOTOS, 0, R.string.camera_gallery_photos_text) 953d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .setOnMenuItemClickListener(new OnMenuItemClickListener() { 954d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang public boolean onMenuItemClick(MenuItem item) { 955d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang gotoGallery(); 956d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return true; 957d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 958d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang }); 959b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project gallery.setIcon(android.R.drawable.ic_menu_gallery); 960b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mGalleryItems.add(gallery); 961b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 962b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project { 963d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MenuItem gallery = menu.add(MenuHelper.VIDEO_MODE_ITEM, 964d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang MENU_GALLERY_VIDEOS, 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 item = menu.add(MenuHelper.GENERIC_ITEM, MENU_SETTINGS, 0, 976d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang R.string.settings) 977d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang .setOnMenuItemClickListener(new OnMenuItemClickListener() { 978d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang public boolean onMenuItemClick(MenuItem item) { 979d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang Intent intent = new Intent(); 980d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang intent.setClass(VideoCamera.this, CameraSettings.class); 981d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang startActivity(intent); 982d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang return true; 983d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 984d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang }); 985b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project item.setIcon(android.R.drawable.ic_menu_preferences); 986b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 987b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 988b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // from MediaRecorder.OnErrorListener 989b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project public void onError(MediaRecorder mr, int what, int extra) { 990b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { 991b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // We may have run out of space on the sdcard. 992b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project stopVideoRecording(); 9939a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project updateAndShowStorageHint(true); 994b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 995b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 996b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 9978d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project // from MediaRecorder.OnInfoListener 9988d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project public void onInfo(MediaRecorder mr, int what, int extra) { 9998d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { 1000de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 1001d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } else if (what 1002d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) { 1003de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mShutterButton.performClick(); 1004de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project updateAndShowStorageHint(true); 10058d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project } 10068d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project } 10078d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project 10089c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project /* 10099c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project * Make sure we're not recording music playing in the background, ask 10109c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project * the MediaPlaybackService to pause playback. 10119c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project */ 10129c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project private void pauseAudioPlayback() { 10139c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project // Shamelessly copied from MediaPlaybackService.java, which 10149c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project // should be public, but isn't. 10159c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project Intent i = new Intent("com.android.music.musicservicecommand"); 10169c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project i.putExtra("command", "pause"); 10179c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project 10189c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project sendBroadcast(i); 10199c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project } 10209c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project 1021b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void startVideoRecording() { 1022b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "startVideoRecording"); 1023b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (!mMediaRecorderRecording) { 1024b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 10259a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (mStorageStatus != STORAGE_STATUS_OK) { 1026b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "Storage issue, ignore the start request"); 1027b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return; 1028b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1029b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1030b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project // Check mMediaRecorder to see whether it is initialized or not. 1031b128446b7ef264c33e91e119391045156a19439bWu-cheng Li if (mMediaRecorder == null) { 1032b128446b7ef264c33e91e119391045156a19439bWu-cheng Li Log.e(TAG, "MediaRecorder is not initialized."); 1033b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return; 1034b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1035b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 10369c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project pauseAudioPlayback(); 10379c9be2eb4a86fc3468dbba1ec5f7bfdb37d22c74The Android Open Source Project 1038b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 1039b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOnErrorListener(this); 10408d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project mMediaRecorder.setOnInfoListener(this); 1041b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.start(); // Recording is now started 1042b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (RuntimeException e) { 1043b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "Could not start media recorder. ", e); 1044b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return; 1045b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1046b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorderRecording = true; 1047b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingStartTime = SystemClock.uptimeMillis(); 1048b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project updateRecordingIndicator(true); 1049b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingTimeView.setText(""); 1050b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingTimeView.setVisibility(View.VISIBLE); 1051b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.sendEmptyMessage(UPDATE_RECORD_TIME); 1052b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutInfinite(); 1053b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1054b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1055b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1056b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void updateRecordingIndicator(boolean showRecording) { 1057d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang int drawableId = showRecording 1058059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin ? R.drawable.ic_camera_indicator_stop 1059d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang : R.drawable.ic_camera_indicator_video; 1060b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Drawable drawable = getResources().getDrawable(drawableId); 1061b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mShutterButton.setImageDrawable(drawable); 1062b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1063b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 10649bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void stopVideoRecordingAndGetThumbnail() { 10659bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang stopVideoRecording(); 10669bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang acquireVideoThumb(); 1067b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1068b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1069de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project private void stopVideoRecordingAndShowAlert() { 1070de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project stopVideoRecording(); 10719bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang showAlert(); 1072de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1073de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 10749bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void showAlert() { 1075059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.review_indicator).setVisibility(View.VISIBLE); 1076059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin findViewById(R.id.video_indicator).setVisibility(View.INVISIBLE); 1077059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 1078b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] pickIds = {R.id.attach, R.id.cancel}; 1079b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] normalIds = {R.id.gallery, R.id.share, R.id.discard}; 1080b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] alwaysOnIds = {R.id.play}; 1081b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] hideIds = pickIds; 1082b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project int[] connectIds = normalIds; 10839bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (mIsVideoCaptureIntent) { 1084b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project hideIds = normalIds; 1085b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project connectIds = pickIds; 1086b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1087d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang for (int id : hideIds) { 1088b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mPostPictureAlert.findViewById(id).setVisibility(View.GONE); 1089b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1090b653f90f33c6f9e6b48dfab018dece9dd021a476Chih-Chung Chang 1091b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project connectAndFadeIn(connectIds); 1092b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project connectAndFadeIn(alwaysOnIds); 1093b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mPostPictureAlert.setVisibility(View.VISIBLE); 1094059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mVideoPreview.setVisibility(View.INVISIBLE); 10959bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 10969bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // There are two cases we are here: 10979bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // (1) We are in a capture video intent, and we are reviewing the video 1098095afa19556bf550262e3cccb9edacc04e6f726aOwen Lin // we just taken. 10999bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // (2) The thumbnail button is clicked: we review the video associated 11009bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // with the thumbnail. 11019bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // For the second case, we copy the associated URI and filename to 11029bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // mCurrentVideoUri and mCurrentVideoFilename, so the video frame shown 11039bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang // and the target for actions (play, delete, ...) will be correct. 11049bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 11059bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (!mIsVideoCaptureIntent) { 1106cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync if (mThumbController.isUriValid()) { 1107cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync mCurrentVideoUri = mThumbController.getUri(); 1108cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync mCurrentVideoFilename = getDataPath(mCurrentVideoUri); 1109cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync } else { 1110cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync return; 1111cb79ab13392eae4919f4dde5d109d76f78eaab9arepo sync } 11129bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 11139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 11149bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang String path = mCurrentVideoFilename; 11159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (path != null) { 1116101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap videoFrame = Util.createVideoThumbnail(path); 11179bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mVideoFrame.setImageBitmap(videoFrame); 11189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mVideoFrame.setVisibility(View.VISIBLE); 11199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 1120b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1121b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 11229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void hideAlert() { 1123059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin mVideoPreview.setVisibility(View.VISIBLE); 1124de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mVideoFrame.setVisibility(View.INVISIBLE); 1125de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project mPostPictureAlert.setVisibility(View.INVISIBLE); 1126de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project showLastPictureButton(); 1127de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1128de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 1129b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void connectAndFadeIn(int[] connectIds) { 1130d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang for (int id : connectIds) { 1131b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project View view = mPostPictureAlert.findViewById(id); 1132b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project view.setOnClickListener(this); 1133b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Animation animation = new AlphaAnimation(0F, 1F); 1134b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project animation.setDuration(500); 11359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang view.startAnimation(animation); 1136b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1137b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1138b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 11399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private boolean isAlertVisible() { 1140b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return mPostPictureAlert.getVisibility() == View.VISIBLE; 1141b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1142b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1143b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void stopVideoRecording() { 1144b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.v(TAG, "stopVideoRecording"); 1145b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project boolean needToRegisterRecording = false; 1146b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording || mMediaRecorder != null) { 1147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project if (mMediaRecorderRecording && mMediaRecorder != null) { 1148b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project try { 1149b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.setOnErrorListener(null); 11508d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project mMediaRecorder.setOnInfoListener(null); 1151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorder.stop(); 1152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } catch (RuntimeException e) { 1153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Log.e(TAG, "stop fail: " + e.getMessage()); 1154b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 11558d0dd0e2ee9a9f8d729ed96597102777cf14701fThe Android Open Source Project 1156b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCurrentVideoFilename = mCameraVideoFilename; 1157d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang Log.v(TAG, "Setting current video filename: " 1158d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang + mCurrentVideoFilename); 1159b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project needToRegisterRecording = true; 1160b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mMediaRecorderRecording = false; 1161b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1162b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project releaseMediaRecorder(); 1163b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project updateRecordingIndicator(false); 1164b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mRecordingTimeView.setVisibility(View.GONE); 1165b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenTimeoutLong(); 1166b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 11679a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) { 11689a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project registerVideo(); 11699a379bd668227d3dcea30312025f304fd248f6e3The Android Open Source Project } 1170b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1171b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFilename = null; 1172b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mCameraVideoFileDescriptor = null; 1173b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1174b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1175b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenTimeoutSystemDefault() { 1176b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.removeMessages(CLEAR_SCREEN_DELAY); 1177b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project clearScreenOnFlag(); 1178b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1179b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1180b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenTimeoutLong() { 1181b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.removeMessages(CLEAR_SCREEN_DELAY); 1182b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenOnFlag(); 1183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); 1184b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1185b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1186b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenTimeoutInfinite() { 1187b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project mHandler.removeMessages(CLEAR_SCREEN_DELAY); 1188b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project setScreenOnFlag(); 1189b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1190b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1191b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void clearScreenOnFlag() { 1192b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Window w = getWindow(); 1193d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 1194d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if ((w.getAttributes().flags & flag) != 0) { 1195d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang w.clearFlags(flag); 1196b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1197b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1198b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1199b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project private void setScreenOnFlag() { 1200b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Window w = getWindow(); 1201d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang final int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 1202d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if ((w.getAttributes().flags & flag) == 0) { 1203d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang w.addFlags(flag); 1204b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1205b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1206b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 1207b128446b7ef264c33e91e119391045156a19439bWu-cheng Li private void hideAlertAndInitializeRecorder() { 12089bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang hideAlert(); 1209b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mRecorderInitialized = false; 1210b128446b7ef264c33e91e119391045156a19439bWu-cheng Li mHandler.sendEmptyMessage(INIT_RECORDER); 1211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1212b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 12139bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void acquireVideoThumb() { 1214101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap videoFrame = Util.createVideoThumbnail(mCurrentVideoFilename); 12159bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.setData(mCurrentVideoUri, videoFrame); 1216de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1217de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 12189bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void showLastPictureButton() { 12199bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (!mIsVideoCaptureIntent) { 12209bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mLastPictureButton.setVisibility(View.VISIBLE); 1221de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 12229bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 1223de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 12249bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private static ImageManager.DataLocation dataLocation() { 12259bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang return ImageManager.DataLocation.EXTERNAL; 1226de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project } 1227de365d87520c97d6b1636442e6b5c82a3e036f29The Android Open Source Project 12289bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private void updateLastVideo() { 122958e94eddd371a9bb7c04936dbeb99615fd1a0c2cChih-Chung Chang IImageList list = ImageManager.allImages( 12309bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mContentResolver, 12319bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang dataLocation(), 12329bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang ImageManager.INCLUDE_VIDEOS, 12339bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang ImageManager.SORT_ASCENDING, 12349bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang ImageManager.CAMERA_IMAGE_BUCKET_ID); 12359bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang int count = list.getCount(); 12369bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (count > 0) { 1237d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang IImage image = list.getImageAt(count - 1); 12389bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang Uri uri = image.fullSizeImageUri(); 12399bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.setData(uri, image.miniThumbBitmap()); 12409bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 12419bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang mThumbController.setData(null, null); 12429bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 12439bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang list.deactivate(); 1244b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1245b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 12469bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private static final String[] DATA_PATH_PROJECTION = new String[] { 12479bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang "_data" 12489bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang }; 12499bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang 12509bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang private String getDataPath(Uri uri) { 12519bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang Cursor c = null; 12529bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang try { 1253d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang c = mContentResolver.query(uri, DATA_PATH_PROJECTION, null, null, 1254d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang null); 12559bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang if (c != null && c.moveToFirst()) { 12569bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang return c.getString(0); 12579bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } else { 12589bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang return null; 12599bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } 12609bc8d1b47e5bab978cc9571ddfdedc8309a0b65dChih-Chung Chang } finally { 126123c51b794e95c201290e36737f379c4bb8eefeaeRay Chen if (c != null) { 126223c51b794e95c201290e36737f379c4bb8eefeaeRay Chen c.close(); 126323c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } 1264b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1265b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1266d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1267d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang private void updateRecordingTime() { 126823c51b794e95c201290e36737f379c4bb8eefeaeRay Chen if (!mMediaRecorderRecording) { 126923c51b794e95c201290e36737f379c4bb8eefeaeRay Chen return; 127023c51b794e95c201290e36737f379c4bb8eefeaeRay Chen } 1271d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long now = SystemClock.uptimeMillis(); 1272d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long delta = now - mRecordingStartTime; 1273d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1274d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // Starting a minute before reaching the max duration 1275d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // limit, we'll countdown the remaining time instead. 1276d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang boolean countdownRemainingTime = 127782ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang (delta >= mMaxVideoDurationInMs - 60000); 1278d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1279d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (countdownRemainingTime) { 128082ded2070a47fff16e1de1c78b516eb25888b91eChih-Chung Chang delta = Math.max(0, mMaxVideoDurationInMs - delta); 1281d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1282d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1283d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long seconds = (delta + 500) / 1000; // round to nearest 1284d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long minutes = seconds / 60; 1285d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long hours = minutes / 60; 1286d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long remainderMinutes = minutes - (hours * 60); 1287d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang long remainderSeconds = seconds - (minutes * 60); 1288d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1289d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String secondsString = Long.toString(remainderSeconds); 1290d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (secondsString.length() < 2) { 1291d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang secondsString = "0" + secondsString; 1292d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1293d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String minutesString = Long.toString(remainderMinutes); 1294d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (minutesString.length() < 2) { 1295d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang minutesString = "0" + minutesString; 1296d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1297d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String text = minutesString + ":" + secondsString; 1298d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (hours > 0) { 1299d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang String hoursString = Long.toString(hours); 1300d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (hoursString.length() < 2) { 1301d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang hoursString = "0" + hoursString; 1302d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1303d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang text = hoursString + ":" + text; 1304d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1305d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mRecordingTimeView.setText(text); 1306d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1307d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang if (mRecordingTimeCountsDown != countdownRemainingTime) { 1308d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // Avoid setting the color on every update, do it only 1309d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // when it needs changing. 1310d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1311d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mRecordingTimeCountsDown = countdownRemainingTime; 1312d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1313d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang int color = getResources().getColor( 1314d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang countdownRemainingTime 1315d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang ? R.color.recording_time_remaining_text 1316d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang : R.color.recording_time_elapsed_text); 1317d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1318d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mRecordingTimeView.setTextColor(color); 1319d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1320d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang 1321d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // Work around a limitation of the T-Mobile G1: The T-Mobile 1322d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // hardware blitter can't pixel-accurately scale and clip at the 1323d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // same time, and the SurfaceFlinger doesn't attempt to work around 1324d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // this limitation. In order to avoid visual corruption we must 1325d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // manually refresh the entire surface view when changing any 1326d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang // overlapping view's contents. 1327d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mVideoPreview.invalidate(); 1328d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang mHandler.sendEmptyMessageDelayed(UPDATE_RECORD_TIME, 1000); 1329d8209aa01ae56ea27f551f621b419251bf80b265Chih-Chung Chang } 1330b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project} 1331