64

I am developing an application which will be able to record video from background of application by using Service.

Problem description :

In my application recording will be scheduled. If user want to record video from 1 PM to 3 PM, he will schedule the task and can exit from application. Application will automatically start recording at 1PM to 3PM.

What I did yet :

I googled about my query but didn't get solution. Many articles say that it is not possible. But in Google Play there are some applications (for eg MyCar Recorder) which can record video from background of application.

I got an article about same but its not working.

What is the way to implement this functionality?

Android Learner
  • 2,559
  • 6
  • 34
  • 43
  • 2
    im interested in knowing this too. Apparently its possible: https://play.google.com/store/apps/details?id=com.zeronoiseapps.secretvideorecorderpro&hl=en – Ian Nov 04 '12 at 20:01
  • Did you try the sample project on the article site? https://github.com/pickerweng/CameraRecorder – Ben Holland Dec 04 '12 at 03:23
  • Din't tried before. but it seems that user have to lauch every time the application and then it starts recording from background. Am I right? I will try this code soon. Thank you. – Android Learner Dec 04 '12 at 08:06
  • Can you be a little more specific on what exactly is not working when trying this article? – Lothar Dec 10 '12 at 07:11
  • Check this out...it worked on N4 and Micromax for me...havent tested on Gingerbread.... – Mrudul Parikh Mar 24 '14 at 06:50
  • In practice you have problem with moving through activities in your application, because Surface is destroyed on Activity pause. In this moment image on your video record is stopped. I asked for it in this topic: http://stackoverflow.com/questions/15049041/background-video-recording-in-android-4-0 – shamanpenza Feb 24 '13 at 06:54
  • Its 2018 and they seem to have stopped it. – Srihari Karanth Dec 18 '18 at 08:28

2 Answers2

60

1- I have created a activity to start service like this:

package com.android.camerarecorder;

import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

public class CameraRecorder extends Activity implements SurfaceHolder.Callback {
    private static final String TAG = "Recorder";
    public static SurfaceView mSurfaceView;
    public static SurfaceHolder mSurfaceHolder;
    public static Camera mCamera ;
    public static boolean mPreviewRunning;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        
        Button btnStart = (Button) findViewById(R.id.StartService);
        btnStart.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                Intent intent = new Intent(CameraRecorder.this, RecorderService.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startService(intent);
                finish();
            }
        });

        Button btnStop = (Button) findViewById(R.id.StopService);
        btnStop.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                stopService(new Intent(CameraRecorder.this, RecorderService.class));
            }
        });
    }
    
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }
    
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }
}

2 - Now I have created a service to record the video in background like this:

    package com.android.camerarecorder;
    import java.io.IOException;
    import java.util.List;
    import android.app.Service;
    import android.content.Intent;
    import android.graphics.PixelFormat;
    import android.hardware.Camera;
    import android.hardware.Camera.Size;
    import android.media.MediaRecorder;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.widget.Toast;

    public class RecorderService extends Service {
        private static final String TAG = "RecorderService";
        private SurfaceView mSurfaceView;
        private SurfaceHolder mSurfaceHolder;
        private static Camera mServiceCamera;
        private boolean mRecordingStatus;
        private MediaRecorder mMediaRecorder;
        
        @Override
        public void onCreate() {
            mRecordingStatus = false;
            //mServiceCamera = CameraRecorder.mCamera;
            mServiceCamera = Camera.open(1);
            mSurfaceView = CameraRecorder.mSurfaceView;
            mSurfaceHolder = CameraRecorder.mSurfaceHolder;
            
            super.onCreate();
            if (mRecordingStatus == false)
                startRecording();
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public void onDestroy() {
            stopRecording();
            mRecordingStatus = false;
            
            super.onDestroy();
        }   
    
        public boolean startRecording(){
            try {
                Toast.makeText(getBaseContext(), "Recording Started", Toast.LENGTH_SHORT).show();
                
                //mServiceCamera = Camera.open();
                Camera.Parameters params = mServiceCamera.getParameters();
                mServiceCamera.setParameters(params);
                Camera.Parameters p = mServiceCamera.getParameters();
                
                final List<Size> listSize = p.getSupportedPreviewSizes();
                Size mPreviewSize = listSize.get(2);
                Log.v(TAG, "use: width = " + mPreviewSize.width 
                            + " height = " + mPreviewSize.height);
                p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
                p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
                mServiceCamera.setParameters(p);
    
                try {
                    mServiceCamera.setPreviewDisplay(mSurfaceHolder);
                    mServiceCamera.startPreview();
                }
                catch (IOException e) {
                    Log.e(TAG, e.getMessage());
                    e.printStackTrace();
                }
                
                mServiceCamera.unlock();
                
                mMediaRecorder = new MediaRecorder();
                mMediaRecorder.setCamera(mServiceCamera);
                mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
                mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
                mMediaRecorder.setOutputFile("/sdcard/video.mp4");
                mMediaRecorder.setVideoFrameRate(30);
                mMediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height);
                mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
                
                mMediaRecorder.prepare();
                mMediaRecorder.start(); 
    
                mRecordingStatus = true;
                
                return true;
            } catch (IllegalStateException e) {
                Log.d(TAG, e.getMessage());
                e.printStackTrace();
                return false;
            } catch (IOException e) {
                Log.d(TAG, e.getMessage());
                e.printStackTrace();
                return false;
            }
        }
    
        public void stopRecording() {
            Toast.makeText(getBaseContext(), "Recording Stopped", Toast.LENGTH_SHORT).show();
            try {
                mServiceCamera.reconnect();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            mMediaRecorder.stop();
            mMediaRecorder.reset();
            
            mServiceCamera.stopPreview();
            mMediaRecorder.release();
            
            mServiceCamera.release();
            mServiceCamera = null;
        }
    }

It will create a file video.mp4 in your sd card. you may change the code for adding more functionality but the basic functionality is achieved through this code i.e. record video in background.

NOTE: I have started the service through button click in activity but you can start it through any other way also like broadcastreceiver etc.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Shridutt Kothari
  • 7,326
  • 3
  • 41
  • 61
  • 1
    So, it will continue writing video when i minimize the app, right? – some.birdie Feb 19 '13 at 11:37
  • 1
    But where is the magic? You just use the camera recorder in the service. I thought there should be something more mysterious. ;) Yeah, i'll give +50 for you soon. – some.birdie Feb 19 '13 at 11:46
  • 2
    I would like to play my mediaplayer on service and putting the surface view at background.. is it possible ans can u suggest me some examples – AndroidOptimist Dec 03 '13 at 06:22
  • 1
    Hi i tried to use the above code but it keeps showing ajava.io.IOException: invalid preview surface – Soham Dutta Sep 08 '14 at 04:58
  • 1
    I have a short question. Are these lines of codes really necesarry `Camera.Parameters params = mServiceCamera.getParameters(); mServiceCamera.setParameters(params); Camera.Parameters p = mServiceCamera.getParameters();`? I guess the last line would be sufficient or I'm wrong? It's just a question to get known of the functionality of the Camera API – ZeusNet Mar 04 '15 at 06:56
  • 1
    @ZeusNet if you need to set the right required camera parameters before using it, you need to use this code. – Shridutt Kothari Mar 12 '15 at 13:21
  • @ZeusNet you may want to have a look at http://developer.android.com/reference/android/hardware/Camera.Parameters.html for more details – Shridutt Kothari Mar 12 '15 at 13:26
  • but when I switch from the activity to another application, and then switch back. It seems like runtime error. – Peter Zhu Mar 18 '15 at 10:00
  • 1
    In `RecorderService.java` in `onCreate()` function, `mServiceCamera = Camera.open();` should be `mServiceCamera = Camera.open(1);` – Peter Zhu Mar 18 '15 at 10:02
  • will it run after killing application ? – Dhwanik Gandhi Oct 26 '15 at 04:18
  • 3
    @DhwanikGandhi isn't it a silly question, how can something run after killing it??? it isn't zombie.. LOL – Shridutt Kothari Oct 27 '15 at 09:47
  • if I start the service on boot ... is the activity also "running" .. I mean you are using static variable CameraRecorder.mSurfaceView , will it be available if the service is started on boot by a broadcast receiver? – yeahman Feb 06 '16 at 18:30
  • 4
    You are trying to access the Surface instance which will be destroyed when the Activity becomes onPause state! I haven't tried this code but never going to work in the background as long as your code uses SurfaceView. At first, because this is the accepted answer I thought you did some tricks but after seeing the code.. NAW. I really hope there's some work around for this btw. – Jenix May 10 '17 at 19:36
  • 1
    it works if you start recording from activity but if I wan to start it from widget or push notification or broadcast receiver? there will be null surfaceView – Choletski Aug 24 '17 at 14:42
  • for me just audio is getting recorded once I close the app please help – RAHUL MAURYA Aug 10 '19 at 13:15
  • `mRecordingStatus == false` shoud (must) be `!mRecordingStatus` – Pratik Butani Dec 13 '19 at 08:38
  • 1
    use `ImageFormat.NV21` instead `ImageFormat.NV16` [Source](https://developer.android.com/reference/android/graphics/PixelFormat#YCbCr_420_SP) – Pratik Butani Dec 13 '19 at 08:41
  • audio is getting recorded but video recording can not working properly. – Sandeep Pareek Nov 09 '21 at 08:54
4

Yes, you can record the background video like this:

First, create a video app using service. Do not set its view so that it will not be visible. If you are doing it in service then that is better because...

Second, you can use the AlarmManager for setting the alarm of particular time and then at that time, by using intent, start your service again. For stopping your app you can use AlarmManager, as well.

Lothar
  • 860
  • 6
  • 21
Rahul
  • 710
  • 1
  • 8
  • 25
  • 1
    cool... then start your video application using broadcast receiver. after completing this let me know i will tell you the next step. :) – Rahul Dec 10 '12 at 10:27
  • you are familiar with broadcastreceiver rite? – Rahul Dec 10 '12 at 10:33
  • Can you tell me the process how can I make SurfaceView instance from Service? – Android Learner Dec 10 '12 at 11:41
  • for creating surfaceview object just create surface view object in activity and place it into intent.putExtra("string", object); and then startservice(intent); from that activity and in service create intent object= getIntent(); and there you can receive your surfaceview object :) – Rahul Dec 10 '12 at 11:52
  • Can you give e the link where is putextra method which can accept object. I didn't find at http://developer.android.com/reference/android/content/Intent.html. And from service without launching my application how can I pass this object as said. – Android Learner Dec 10 '12 at 13:57
  • no, what i want to say is... create a mainactivity where you declare all your surfaceview and necessary things and then ask user to enter a time when he wants to start video. now start your AlarmManager for that particular time with pendingintent. after that register one broadcast receiver that will listen to ur alarm and then start videoActivity from that broadcast receiver using startActivity(intent). or startService(intent); there you can do all your code. in this wayyour video will start automatically everyday at that particular time. – Rahul Dec 11 '12 at 05:21
  • try to learn about intent.putExtra("string", Bundle); may be it is useful for you for passing surfaceView – Rahul Dec 11 '12 at 05:30
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20913/discussion-between-android-learner-and-rahul) – Android Learner Dec 11 '12 at 05:32
  • for getting surfaceview object you can do one thing more... suppose activity A is having SurfaceView then declare that surfaceview object as Public and assign a value. now in class B just call A.surfaceView and it will be accesible. and for service you doesnt reqiure that view object because it runs in background. – Rahul Dec 11 '12 at 05:52
  • so you are saying that surfaceView object not required for video recorder if i am using Service, right? – Android Learner Dec 11 '12 at 06:10
  • chill dude...dont be hyper...just pass your surfaceView as public. – Rahul Dec 11 '12 at 06:19