• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.mediarecorder;
18 
19 import android.annotation.TargetApi;
20 import android.app.Activity;
21 import android.hardware.Camera;
22 import android.media.CamcorderProfile;
23 import android.media.MediaRecorder;
24 import android.os.AsyncTask;
25 import android.os.Build;
26 import android.os.Bundle;
27 import android.util.Log;
28 import android.view.Menu;
29 import android.view.TextureView;
30 import android.view.View;
31 import android.widget.Button;
32 
33 import com.example.android.common.media.CameraHelper;
34 
35 import java.io.IOException;
36 import java.util.List;
37 
38 /**
39  *  This activity uses the camera/camcorder as the A/V source for the {@link android.media.MediaRecorder} API.
40  *  A {@link android.view.TextureView} is used as the camera preview which limits the code to API 14+. This
41  *  can be easily replaced with a {@link android.view.SurfaceView} to run on older devices.
42  */
43 public class MainActivity extends Activity {
44 
45     private Camera mCamera;
46     private TextureView mPreview;
47     private MediaRecorder mMediaRecorder;
48 
49     private boolean isRecording = false;
50     private static final String TAG = "Recorder";
51     private Button captureButton;
52 
53     @Override
onCreate(Bundle savedInstanceState)54     protected void onCreate(Bundle savedInstanceState) {
55         super.onCreate(savedInstanceState);
56         setContentView(R.layout.sample_main);
57 
58         mPreview = (TextureView) findViewById(R.id.surface_view);
59         captureButton = (Button) findViewById(R.id.button_capture);
60     }
61 
62     /**
63      * The capture button controls all user interaction. When recording, the button click
64      * stops recording, releases {@link android.media.MediaRecorder} and {@link android.hardware.Camera}. When not recording,
65      * it prepares the {@link android.media.MediaRecorder} and starts recording.
66      *
67      * @param view the view generating the event.
68      */
onCaptureClick(View view)69     public void onCaptureClick(View view) {
70         if (isRecording) {
71             // BEGIN_INCLUDE(stop_release_media_recorder)
72 
73             // stop recording and release camera
74             mMediaRecorder.stop();  // stop the recording
75             releaseMediaRecorder(); // release the MediaRecorder object
76             mCamera.lock();         // take camera access back from MediaRecorder
77 
78             // inform the user that recording has stopped
79             setCaptureButtonText("Capture");
80             isRecording = false;
81             releaseCamera();
82             // END_INCLUDE(stop_release_media_recorder)
83 
84         } else {
85 
86             // BEGIN_INCLUDE(prepare_start_media_recorder)
87 
88             new MediaPrepareTask().execute(null, null, null);
89 
90             // END_INCLUDE(prepare_start_media_recorder)
91 
92         }
93     }
94 
setCaptureButtonText(String title)95     private void setCaptureButtonText(String title) {
96         captureButton.setText(title);
97     }
98 
99     @Override
onPause()100     protected void onPause() {
101         super.onPause();
102         // if we are using MediaRecorder, release it first
103         releaseMediaRecorder();
104         // release the camera immediately on pause event
105         releaseCamera();
106     }
107 
releaseMediaRecorder()108     private void releaseMediaRecorder(){
109         if (mMediaRecorder != null) {
110             // clear recorder configuration
111             mMediaRecorder.reset();
112             // release the recorder object
113             mMediaRecorder.release();
114             mMediaRecorder = null;
115             // Lock camera for later use i.e taking it back from MediaRecorder.
116             // MediaRecorder doesn't need it anymore and we will release it if the activity pauses.
117             mCamera.lock();
118         }
119     }
120 
releaseCamera()121     private void releaseCamera(){
122         if (mCamera != null){
123             // release the camera for other applications
124             mCamera.release();
125             mCamera = null;
126         }
127     }
128 
129     @TargetApi(Build.VERSION_CODES.HONEYCOMB)
prepareVideoRecorder()130     private boolean prepareVideoRecorder(){
131 
132         // BEGIN_INCLUDE (configure_preview)
133         mCamera = CameraHelper.getDefaultCameraInstance();
134 
135         // We need to make sure that our preview and recording video size are supported by the
136         // camera. Query camera to find all the sizes and choose the optimal size given the
137         // dimensions of our preview surface.
138         Camera.Parameters parameters = mCamera.getParameters();
139         List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
140         Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSizes,
141                 mPreview.getWidth(), mPreview.getHeight());
142 
143         // Use the same size for recording profile.
144         CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
145         profile.videoFrameWidth = optimalSize.width;
146         profile.videoFrameHeight = optimalSize.height;
147 
148         // likewise for the camera object itself.
149         parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
150         mCamera.setParameters(parameters);
151         try {
152                 // Requires API level 11+, For backward compatibility use {@link setPreviewDisplay}
153                 // with {@link SurfaceView}
154                 mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
155         } catch (IOException e) {
156             Log.e(TAG, "Surface texture is unavailable or unsuitable" + e.getMessage());
157             return false;
158         }
159         // END_INCLUDE (configure_preview)
160 
161 
162         // BEGIN_INCLUDE (configure_media_recorder)
163         mMediaRecorder = new MediaRecorder();
164 
165         // Step 1: Unlock and set camera to MediaRecorder
166         mCamera.unlock();
167         mMediaRecorder.setCamera(mCamera);
168 
169         // Step 2: Set sources
170         mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT );
171         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
172 
173         // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
174         mMediaRecorder.setProfile(profile);
175 
176         // Step 4: Set output file
177         mMediaRecorder.setOutputFile(CameraHelper.getOutputMediaFile(
178                 CameraHelper.MEDIA_TYPE_VIDEO).toString());
179         // END_INCLUDE (configure_media_recorder)
180 
181         // Step 5: Prepare configured MediaRecorder
182         try {
183             mMediaRecorder.prepare();
184         } catch (IllegalStateException e) {
185             Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
186             releaseMediaRecorder();
187             return false;
188         } catch (IOException e) {
189             Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
190             releaseMediaRecorder();
191             return false;
192         }
193         return true;
194     }
195 
196     /**
197      * Asynchronous task for preparing the {@link android.media.MediaRecorder} since it's a long blocking
198      * operation.
199      */
200     class MediaPrepareTask extends AsyncTask<Void, Void, Boolean> {
201 
202         @Override
doInBackground(Void... voids)203         protected Boolean doInBackground(Void... voids) {
204             // initialize video camera
205             if (prepareVideoRecorder()) {
206                 // Camera is available and unlocked, MediaRecorder is prepared,
207                 // now you can start recording
208                 mMediaRecorder.start();
209 
210                 isRecording = true;
211             } else {
212                 // prepare didn't work, release the camera
213                 releaseMediaRecorder();
214                 return false;
215             }
216             return true;
217         }
218 
219         @Override
onPostExecute(Boolean result)220         protected void onPostExecute(Boolean result) {
221             if (!result) {
222                 MainActivity.this.finish();
223             }
224             // inform the user that recording has started
225             setCaptureButtonText("Stop");
226 
227         }
228     }
229 
230 }