Android Video Capture Example
In a simple and modern Android application, it is becoming very common, that the camera is used not only to capture basic portraits and landscape views, but also to be used for other reasons, for instance to capture video, produce small video clips and rendering them under various alternations, either to post on social media or for personal use.
The Android framework includes support for various cameras and camera features available on devices, allowing you to capture pictures and videos in your applications.
So, in this example, we are going to see the use of Android Video API in a more detailed way, and develop an Android application that captures video and switches between the front and the back camera of our mobile device.
For our example will use the following tools in a Windows 64-bit or an OS X platform:
- JDK 1.7
- Eclipse 4.2 Juno
- Android SDK 4.4.2
Let’s take a closer look:
1. Create a New Android Application Project
You may skip project creation and jump directly to the beginning of the example below.
Open Eclipse IDE and go to File → New → Project → Android Application Project.
Specify the name of the application, the project and the package and then click Next.
In the next window, the “Create Activity” option should be checked. The new created activity will be the main activity of your project. Then press Next button.
In “Configure Launcher Icon” window you should choose the icon you want to have in your app. We will use the default icon of android, so click Next.
Select the “Blank Activity” option and press Next.
You have to specify a name for the new Activity and a name for the layout description of your app. The .xml file for the layout will automatically be created in the res/layout folder. It will also be created a fragment layout xml, that we are not going to use in this project and you can remove it if you want. Then press Finish.
Here you can see, how will the structure of the project become when finished:
2. Creating the layout of the main AndroidVideoCaptureExample
We are going to make a simple layout xml for the AndroidVideoCaptureExample.class
, that consists of a LinearLayout
with horizontal orientation, that includes the SurfaceView
for the camera preview view on the left, and two buttons on the right. Let’s see this in detail.
Open res/layout/activity_main.xml
, go to the respective xml tab and paste the following:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <LinearLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:orientation="horizontal" /> <LinearLayout android:id="@+id/buttonsLayout" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:orientation="vertical" > <Button android:id="@+id/button_ChangeCamera" android:layout_width="72dp" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:text="Switch Camera" /> <Button android:id="@+id/button_capture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:text="Capture/Stop" /> </LinearLayout> </LinearLayout>
3. Creating the source code of the main AndroidVideoCapture Activity
As you have noticed, for the purpose of this example, we are going to have an Activity with a customized SurfaceView class for this Activity.
Open src/com.javacodegeeks.androidvideocaptureexample/AndroidVideoCapture.java
file and paste the code below.
AndroidVideoCaptureExample.java
package com.javacodegeeks.androidvideocaptureexample; import java.io.IOException; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Toast; public class AndroidVideoCaptureExample extends Activity { private Camera mCamera; private CameraPreview mPreview; private MediaRecorder mediaRecorder; private Button capture, switchCamera; private Context myContext; private LinearLayout cameraPreview; private boolean cameraFront = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); myContext = this; initialize(); } private int findFrontFacingCamera() { int cameraId = -1; // Search for the front facing camera int numberOfCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberOfCameras; i++) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { cameraId = i; cameraFront = true; break; } } return cameraId; } private int findBackFacingCamera() { int cameraId = -1; // Search for the back facing camera // get the number of cameras int numberOfCameras = Camera.getNumberOfCameras(); // for every camera check for (int i = 0; i < numberOfCameras; i++) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == CameraInfo.CAMERA_FACING_BACK) { cameraId = i; cameraFront = false; break; } } return cameraId; } public void onResume() { super.onResume(); if (!hasCamera(myContext)) { Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG); toast.show(); finish(); } if (mCamera == null) { // if the front facing camera does not exist if (findFrontFacingCamera() 1) { // release the old camera instance // switch camera, from the front and the back and vice versa releaseCamera(); chooseCamera(); } else { Toast toast = Toast.makeText(myContext, "Sorry, your phone has only one camera!", Toast.LENGTH_LONG); toast.show(); } } } }; public void chooseCamera() { // if the camera preview is the front if (cameraFront) { int cameraId = findBackFacingCamera(); if (cameraId >= 0) { // open the backFacingCamera // set a picture callback // refresh the preview mCamera = Camera.open(cameraId); // mPicture = getPictureCallback(); mPreview.refreshCamera(mCamera); } } else { int cameraId = findFrontFacingCamera(); if (cameraId >= 0) { // open the backFacingCamera // set a picture callback // refresh the preview mCamera = Camera.open(cameraId); // mPicture = getPictureCallback(); mPreview.refreshCamera(mCamera); } } } @Override protected void onPause() { super.onPause(); // when on Pause, release camera in order to be used from other // applications releaseCamera(); } private boolean hasCamera(Context context) { // check if the device has camera if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { return true; } else { return false; } } boolean recording = false; OnClickListener captrureListener = new OnClickListener() { @Override public void onClick(View v) { if (recording) { // stop recording and release camera mediaRecorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object Toast.makeText(AndroidVideoCaptureExample.this, "Video captured!", Toast.LENGTH_LONG).show(); recording = false; } else { if (!prepareMediaRecorder()) { Toast.makeText(AndroidVideoCaptureExample.this, "Fail in prepareMediaRecorder()!\n - Ended -", Toast.LENGTH_LONG).show(); finish(); } // work on UiThread for better performance runOnUiThread(new Runnable() { public void run() { // If there are stories, add them to the table try { mediaRecorder.start(); } catch (final Exception ex) { // Log.i("---","Exception in thread"); } } }); recording = true; } } }; private void releaseMediaRecorder() { if (mediaRecorder != null) { mediaRecorder.reset(); // clear recorder configuration mediaRecorder.release(); // release the recorder object mediaRecorder = null; mCamera.lock(); // lock camera for later use } } private boolean prepareMediaRecorder() { mediaRecorder = new MediaRecorder(); mCamera.unlock(); mediaRecorder.setCamera(mCamera); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_720P)); mediaRecorder.setOutputFile("/sdcard/myvideo.mp4"); mediaRecorder.setMaxDuration(600000); //set maximum duration 60 sec. mediaRecorder.setMaxFileSize(50000000); //set maximum file size 50M try { mediaRecorder.prepare(); } catch (IllegalStateException e) { releaseMediaRecorder(); return false; } catch (IOException e) { releaseMediaRecorder(); return false; } return true; } private void releaseCamera() { // stop and release camera if (mCamera != null) { mCamera.release(); mCamera = null; } } }
Let’s see in detail the code above.
We set the activity_main.xml
layout and we initialize our main layout by:
setContentView(R.layout.activity_main);
We also set the onCreate
method of the Activity:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); myContext = this; initialize(); }
And the onResume
method of the Activity:
public void onResume() { super.onResume(); if (!hasCamera(myContext)) { Toast toast = Toast.makeText(myContext, "Sorry, your phone does not have a camera!", Toast.LENGTH_LONG); toast.show(); finish(); } if (mCamera == null) { // if the front facing camera does not exist if (findFrontFacingCamera() < 0) { Toast.makeText(this, "No front facing camera found.", Toast.LENGTH_LONG).show(); switchCamera.setVisibility(View.GONE); } mCamera = Camera.open(findBackFacingCamera()); mPreview.refreshCamera(mCamera); } }
In the onResume
method we check if the device has a hardware camera. We also check if the device has a front facing camera by executing the findFrontFacingCamera()
method, which returns an integer as the id of the camera in use. If there is no second camera on the device, the switch button goes invisible.
private int findBackFacingCamera() { int cameraId = -1; // Search for the back facing camera // get the number of cameras int numberOfCameras = Camera.getNumberOfCameras(); // for every camera check for (int i = 0; i < numberOfCameras; i++) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == CameraInfo.CAMERA_FACING_BACK) { cameraId = i; cameraFront = false; break; } } return cameraId; }
Generally, when we want to initialize, or to refresh a camera instance, we use the sequence of methods:
boolean recording = false; OnClickListener captrureListener = new OnClickListener() { @Override public void onClick(View v) { if (recording) { // stop recording and release camera mediaRecorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object Toast.makeText(AndroidVideoCaptureExample.this, "Video captured!", Toast.LENGTH_LONG).show(); recording = false; } else { if (!prepareMediaRecorder()) { Toast.makeText(AndroidVideoCaptureExample.this, "Failure!", Toast.LENGTH_LONG).show(); finish(); } // work on UiThread for better performance runOnUiThread(new Runnable() { public void run() { // If there are stories, add them to the table try { mediaRecorder.start(); } catch (final Exception ex) { } } }); recording = true; } } };
In the onResume
method we check if the device has a hardware camera. We also check if the device has a front facing camera by executing the findFrontFacingCamera()
method, which returns an integer as the id of the camera in use. If there is no second camera on the device, the switch button goes invisible.
private int findBackFacingCamera() { int cameraId = -1; int numberOfCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberOfCameras; i++) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == CameraInfo.CAMERA_FACING_BACK) { cameraId = i; cameraFront = false; break; } } return cameraId; }
Here, we “prepare” the MediaRecorder
class, by setting the camera instance to the mediaRecorder class, setting the audio and video source to the one that is captured by the camera, setting the video output type at “QUALITY_720P” and setting the outputFile, as well as maximun duration and video file size.
private boolean prepareMediaRecorder() { mediaRecorder = new MediaRecorder(); mCamera.unlock(); mediaRecorder.setCamera(mCamera); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_720P)); mediaRecorder.setOutputFile("/sdcard/myvideo.mp4"); mediaRecorder.setMaxDuration(600000); // set maximum duration mediaRecorder.setMaxFileSize(50000000); // set maximum file size try { mediaRecorder.prepare(); } catch (IllegalStateException e) { releaseMediaRecorder(); return false; } catch (IOException e) { releaseMediaRecorder(); return false; } return true; }
4. Creating the source code of the class CameraPreview
Open src/com.javacodegeeks.androidvideocaptureexample/CameraPreview.java file and paste the code below.
CameraPreview.java:
package com.javacodegeeks.androidvideocaptureexample; import java.io.IOException; import android.content.Context; import android.hardware.Camera; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { try { // create the surface and start camera preview if (mCamera == null) { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } } catch (IOException e) { Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage()); } } public void refreshCamera(Camera camera) { if (mHolder.getSurface() == null) { // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e) { // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings setCamera(camera); try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e) { Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. refreshCamera(mCamera); } public void setCamera(Camera camera) { //method to set a camera instance mCamera = camera; } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub // mCamera.release(); } }
Let’s see in detail the code above.
Most of the methods that are used here were explained in a previous Android Example, the Android SurfaceView Example. However, we will explain them once again, for the use of this example.
In the code snippet that follows, we initialize the surface view that is created. We set a preview display of a camera instance. This means that our surface view will display the “camera sees”.
public void surfaceCreated(SurfaceHolder holder) { try { // create the surface and start camera preview if (mCamera == null) { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } } catch (IOException e) { Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage()); } }
When the layout of our activity changes, so does the surfaceView. The surfaceChanged
method is called when we resume the Activity (restore it from the background for example). When this happens, we “refresh” the preview view of the camera.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. refreshCamera(mCamera); }
5. Android Manifest
Because this application uses the hardware camera, the front camera (if exists) and tries to save images to the device’s external storage (SD Card), we must also specify this in the manifest. The AndroidManifest.xml of our project is simple and contains the permissions:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.javacodegeeks.androidvideocaptureexample" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.front" android:required="false" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:screenOrientation="landscape" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > <activity android:name="com.javacodegeeks.androidvideocaptureexample.AndroidVideoCaptureExample" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
5. Build, compile and run
When we build, compile and run our project, the main AndroidVideoCaptureExample should look like this:
Download the Eclipse Project
This was an example of Android Android Video Capture Example .
You can download the full source code of this example here: AndroidVideoCaptureExample,zip
Thank you,It helps me lot for,since I was struggling from past three days
where is initialiation() defined???????