blob: d50b53ea07a8902d8ebb740fb868bdbd757671f8 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.media.recorder;
import android.annotation.TargetApi;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import com.example.android.common.media.CameraHelper;
import java.io.IOException;
import java.util.List;
/**
* This activity uses the camera/camcorder as the A/V source for the {@link MediaRecorder} API.
* A {@link TextureView} is used as the camera preview which limits the code to API 14+. This
* can be easily replaced with a {@link android.view.SurfaceView} to run on older devices.
*/
public class MainActivity extends Activity {
private Camera mCamera;
private TextureView mPreview;
private MediaRecorder mMediaRecorder;
private boolean isRecording = false;
private static final String TAG = "Recorder";
private Button captureButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPreview = (TextureView) findViewById(R.id.surface_view);
captureButton = (Button) findViewById(R.id.button_capture);
}
/**
* The capture button controls all user interaction. When recording, the button click
* stops recording, releases {@link MediaRecorder} and {@link Camera}. When not recording,
* it prepares the {@link MediaRecorder} and starts recording.
*
* @param view the view generating the event.
*/
public void onCaptureClick(View view) {
if (isRecording) {
// BEGIN_INCLUDE(stop_release_media_recorder)
// stop recording and release camera
mMediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mCamera.lock(); // take camera access back from MediaRecorder
// inform the user that recording has stopped
setCaptureButtonText("Capture");
isRecording = false;
releaseCamera();
// END_INCLUDE(stop_release_media_recorder)
} else {
// BEGIN_INCLUDE(prepare_start_media_recorder)
new MediaPrepareTask().execute(null, null, null);
// END_INCLUDE(prepare_start_media_recorder)
}
}
private void setCaptureButtonText(String title) {
captureButton.setText(title);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onPause() {
super.onPause();
// if we are using MediaRecorder, release it first
releaseMediaRecorder();
// release the camera immediately on pause event
releaseCamera();
}
private void releaseMediaRecorder(){
if (mMediaRecorder != null) {
// clear recorder configuration
mMediaRecorder.reset();
// release the recorder object
mMediaRecorder.release();
mMediaRecorder = null;
// Lock camera for later use i.e taking it back from MediaRecorder.
// MediaRecorder doesn't need it anymore and we will release it if the activity pauses.
mCamera.lock();
}
}
private void releaseCamera(){
if (mCamera != null){
// release the camera for other applications
mCamera.release();
mCamera = null;
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private boolean prepareVideoRecorder(){
// BEGIN_INCLUDE (configure_preview)
mCamera = CameraHelper.getDefaultCameraInstance();
// We need to make sure that our preview and recording video size are supported by the
// camera. Query camera to find all the sizes and choose the optimal size given the
// dimensions of our preview surface.
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSizes,
mPreview.getWidth(), mPreview.getHeight());
// Use the same size for recording profile.
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
profile.videoFrameWidth = optimalSize.width;
profile.videoFrameHeight = optimalSize.height;
// likewise for the camera object itself.
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setParameters(parameters);
try {
// Requires API level 11+, For backward compatibility use {@link setPreviewDisplay}
// with {@link SurfaceView}
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
} catch (IOException e) {
Log.e(TAG, "Surface texture is unavailable or unsuitable" + e.getMessage());
return false;
}
// END_INCLUDE (configure_preview)
// BEGIN_INCLUDE (configure_media_recorder)
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT );
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(profile);
// Step 4: Set output file
mMediaRecorder.setOutputFile(CameraHelper.getOutputMediaFile(
CameraHelper.MEDIA_TYPE_VIDEO).toString());
// END_INCLUDE (configure_media_recorder)
// Step 5: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
/**
* Asynchronous task for preparing the {@link MediaRecorder} since it's a long blocking
* operation.
*/
class MediaPrepareTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... voids) {
// initialize video camera
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
if (!result) {
MainActivity.this.finish();
}
// inform the user that recording has started
setCaptureButtonText("Stop");
}
}
}