Home | History | Annotate | Download | only in com.example.android.mediarecorder
      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) {
     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 
     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 
    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
    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 }