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
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
*/
69
public void onCaptureClick(View view) {
70
if (isRecording) {
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();
83
84
} else {
85
87
88
new MediaPrepareTask().execute(null, null, null);
89
91
92
}
93
}
94
95
private void setCaptureButtonText(String title) {
96
captureButton.setText(title);
97
}
98
99
@Override
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
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
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)
130
private boolean prepareVideoRecorder(){
131
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
}
160
161
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());
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
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
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
}