1

I am trying to create a background video recorder in android. For this, I have created a Service class to implement the video recording. When I press button to start recording, it starts successfully but when I stop it, I get the following exception:

06-27 17:32:20.974 20244-21916/com.svtech.thirdeye.thirdeye E/MediaRecorderJNI: Application lost the surface
06-27 17:32:24.513 20244-21848/com.svtech.thirdeye.thirdeye E/NativeCrypto: ssl=0x587e0d60 cert_verify_callback x509_store_ctx=0x54ab7a48 arg=0x0
06-27 17:32:24.513 20244-21848/com.svtech.thirdeye.thirdeye E/NativeCrypto: ssl=0x587e0d60 cert_verify_callback calling verifyCertificateChain authMethod=ECDHE_ECDSA
06-27 17:32:25.009 20244-20244/com.svtech.thirdeye.thirdeye E/MediaRecorder: stop called in an invalid state: 4
06-27 17:32:25.033 20244-20244/com.svtech.thirdeye.thirdeye E/AndroidRuntime: 

FATAL EXCEPTION: main

java.lang.RuntimeException: Unable to stop service com.svtech.thirdeye.thirdeye.Services.VideoRecordingOldApiService@424cfbb8: java.lang.IllegalStateException
    at android.app.ActivityThread.handleStopService(ActivityThread.java:2894)
    at android.app.ActivityThread.access$2000(ActivityThread.java:162)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:194)
    at android.app.ActivityThread.main(ActivityThread.java:5371)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: java.lang.IllegalStateException
    at android.media.MediaRecorder.stop(Native Method)
    at com.svtech.thirdeye.thirdeye.Services.VideoRecordingOldApiService.onDestroy(VideoRecordingOldApiService.java:129)
    at android.app.ActivityThread.handleStopService(ActivityThread.java:2877)
    at android.app.ActivityThread.access$2000(ActivityThread.java:162) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:194) 
    at android.app.ActivityThread.main(ActivityThread.java:5371) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:525) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) 
    at dalvik.system.NativeStart.main(Native Method) 

Here is my VideoRecordingOldApiService class

public class VideoRecordingOldApiService extends Service {


    private Handler handler;
    protected String fileName;
    private Camera mCamera;
    private CameraPreview cameraPreview;
    private MediaRecorder videoRecorder;
    private CameraCheck cameraCheck;
    private Thread recorderThread;

    public VideoRecordingOldApiService() {
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        recorderThread = new Thread(new Runnable() {
            @Override
            public void run() {

            Looper.prepare();

                mCamera = cameraCheck.getDesiredCamera(getApplicationContext(),
                        Camera.CameraInfo.CAMERA_FACING_BACK, handler);

                cameraPreview = new CameraPreview(getApplicationContext(), mCamera);

                handler.post(new Runnable() {
                    @Override
                    public void run() {

                        Toast.makeText(getApplicationContext(), R.string.video_recorder_started, Toast.LENGTH_SHORT).show();
                    }
                });


                mCamera.unlock();
                videoRecorder.setCamera(mCamera);
                videoRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
                videoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                videoRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
                videoRecorder.setOutputFile(fileName);
                videoRecorder.setPreviewDisplay(cameraPreview.getHolder().getSurface());

                try {
                    videoRecorder.prepare();
                    videoRecorder.start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        recorderThread.start();

        return START_REDELIVER_INTENT;
    }

    @Override
    public void onCreate() {

        getFileName();
        handler = new Handler();
        videoRecorder = new MediaRecorder();
        cameraCheck = new CameraCheck();


        //Setup Notification
        final Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
        notificationIntent.addCategory("android.intent.category.LAUNCHER");

        final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

        Notification notification;

        notification = new Notification.Builder(getApplicationContext())
                .setSmallIcon(R.drawable.videorecordicon)
                .setOngoing(true)
                .setPriority(Notification.PRIORITY_DEFAULT)
                .setContentTitle(getResources().getString(R.string.video_recorder_notification))
                .setContentText(getResources().getString(R.string.notification_video_text) + "...")
                .setContentIntent(pendingIntent).build();

        startForeground(1, notification);
    }




    @Override
    public void onDestroy() {

        if (videoRecorder != null){

            videoRecorder.stop();
            videoRecorder.release();
            videoRecorder = null;

            Toast.makeText(getApplicationContext(), R.string.recording_done, Toast.LENGTH_SHORT).show();
            recorderThread.interrupt();

            mCamera.lock();

            if (mCamera != null){

                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
        }

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    public String getFileName (){

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                    + "/" + "video_record" + System.currentTimeMillis() + ".mp4";
        } else {

            Toast.makeText(getApplicationContext(), "No External Storage Found", Toast.LENGTH_LONG).show();
        }

        return fileName;
    }

}

EDITS:

Here is my revised VideoRecordingOldApiService Class:

public class VideoRecordingOldApiService extends Service implements MediaRecorder.OnInfoListener, MediaRecorder.OnErrorListener {


    private Camera mCamera;
    private String outputFile;
    private FrameLayout frameLayout;
    private MediaRecorder mMediaRecorder;
    private CameraCheck cameraCheck;
    private final static String TAG = "VideoRecorderService";
    private CameraPreview cameraPreview;


    public VideoRecordingOldApiService() {
    }


    @Override
    public void onCreate() {

        cameraCheck = new CameraCheck();
        frameLayout = MainActivity.PlaceholderFragment.previewFrameLayout;

        //Setup Notification
        final Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
        notificationIntent.addCategory("android.intent.category.LAUNCHER");

        final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

        Notification notification;

        notification = new Notification.Builder(getApplicationContext())
                .setSmallIcon(R.drawable.videorecordicon)
                .setOngoing(true)
                .setPriority(Notification.PRIORITY_DEFAULT)
                .setContentTitle(getResources().getString(R.string.video_recorder_notification))
                .setContentText(getResources().getString(R.string.notification_video_text) + "...")
                .setContentIntent(pendingIntent).build();

        startForeground(1, notification);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(getApplicationContext(), R.string.video_recorder_started, Toast.LENGTH_LONG).show();

        if (initCamera()) {

            initRecorder();

        } else {

            Toast.makeText(getApplicationContext(), "Camera not found", Toast.LENGTH_SHORT).show();
        }

        return START_REDELIVER_INTENT;
    }

    @Override
    public void onDestroy() {

        stopRecording();
    }


    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }


    public String getFileName() {

        String fileName = null;

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                    + "/" + "video_record" + System.currentTimeMillis() + ".mp4";

            Log.i("Camera Recorder", fileName);
        } else {

            Toast.makeText(getApplicationContext(), "No External Storage Found", Toast.LENGTH_LONG).show();
        }

        return fileName;
    }


    private boolean initCamera() {

        try {

            mCamera = cameraCheck.getDesiredCamera(this, Camera.CameraInfo.CAMERA_FACING_FRONT);
            cameraPreview = new CameraPreview(getApplicationContext(), mCamera);
            frameLayout.addView(cameraPreview);
        } catch (Exception e) {

            Log.v(TAG, "Could not initialise the camera");
            e.printStackTrace();
            return false;

        }

        return true;
    }

    private void initRecorder() {

        if (mMediaRecorder == null) {
            mMediaRecorder = new MediaRecorder();
            outputFile = getFileName();

            try {

                // mCamera.unlock();
                mMediaRecorder.setCamera(mCamera);

                mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
                mMediaRecorder.setOutputFile(outputFile);
                mMediaRecorder.setPreviewDisplay(cameraPreview.getHolder().getSurface());


                mMediaRecorder.prepare();
                mMediaRecorder.start();
            } catch (Exception e) {
                Log.v(TAG, "MediaRecorder failed to initialize");
                e.printStackTrace();
            }

            mMediaRecorder.setOnInfoListener(this);
            mMediaRecorder.setOnErrorListener(this);
        }
    }



        @Override
        public void onInfo (MediaRecorder mr,int what, int extra){

        }

        @Override
        public void onError (MediaRecorder mr,int what, int extra){

        }


    private void stopRecording() {

            try {
                mMediaRecorder.stop();
            } catch (Exception e) {

                //This can happen if recorder has already stopped.
                Log.e(TAG, "Got IllegalStateException in stopRecording " + e.getMessage());
            }

            releaseRecorder();
            Toast.makeText(getApplicationContext(), R.string.recording_done, Toast.LENGTH_SHORT).show();
            releaseCamera();

    }

    private void releaseRecorder() {

        if (mMediaRecorder != null) {

            mMediaRecorder.reset();
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
    }

    private void releaseCamera() {

        if (mCamera != null) {

            //mCamera.lock();

            mCamera.release();
            mCamera = null;
        }

    }
}

I am now getting camera preview. MediaRecorder is creating file in directory, but somehow I am still getting IllegalStateException on onStop(). Can anyone please help?????

Vaibhav Agarwal
  • 975
  • 1
  • 7
  • 22
  • There will be stop issue when your recording has not started properly ,pls make sure that ur recording has started properly and its creating a file for each instance of service – Auto-Droid ツ Jun 28 '16 at 06:00
  • And theres no need to start video recording in thread and no need for Looper.prepare(); If you have to record video in background thread – Auto-Droid ツ Jun 28 '16 at 06:03
  • I have revised my Service Class code. Now I am getting camera preview and file is also being created in directory, but still I am getting same exception. Pls help.. @Auto-Droidツ – Vaibhav Agarwal Jul 02 '16 at 10:23
  • How r u stopping your service coz if u are stopping it externally and if your service is already dead then it will give illegalStateException – Auto-Droid ツ Jul 04 '16 at 14:50
  • What happens is if u close the application by starting your service the surface view will get realised and your recording will stop eventually your service will end. I have also done this before your will have to create surface view dynamically in service so it persist on screen even when your application goes in background – Auto-Droid ツ Jul 04 '16 at 14:53
  • Okayy!!! Thanks buddy!!! I will try doing that and leave a comment then. @Auto-Droidツ – Vaibhav Agarwal Jul 04 '16 at 15:03
  • @VaibhavAgarwal did you find a solution? – user924 Jul 03 '18 at 07:09
  • @Auto-Droidツ and how do you know if it started properly? there is no such event or exception and mp4 is created ok but it always fails with stop and file size is only 70-110 kb, not playable of course. Though on some other devices it works ok. There is nothing difficult to configure MediaRecorder so there should no be any issues like "not started properly". – user924 Jul 03 '18 at 07:12
  • This is due to audio, comment your audio source and audio encoder line, it should work. – Jaswant Singh Nov 02 '19 at 06:27

0 Answers0