如何从应用程序后台录制视频:Android

Posted

技术标签:

【中文标题】如何从应用程序后台录制视频:Android【英文标题】:How to record video from background of application : Android 【发布时间】:2012-04-24 16:27:54 【问题描述】:

我正在开发一个应用程序,它可以使用Service从应用程序后台录制视频。

问题描述:

将在我的应用程序中安排录制。如果用户想从下午 1 点到下午 3 点录制视频,他将安排任务并可以退出应用程序。应用程序将在下午 1 点至下午 3 点自动开始录制。

我做了什么:

我用谷歌搜索了我的查询,但没有得到解决方案。很多文章都说不可能。但是在Google Play 中有一些应用程序(例如MyCar Recorder)可以从应用程序的背景录制视频。

我得到了一个大致相同的article,但它不起作用。

实现这个功能的方法是什么?

【问题讨论】:

我也有兴趣知道这一点。显然这是可能的:play.google.com/store/apps/… 您尝试过文章站点上的示例项目吗? github.com/pickerweng/CameraRecorder 以前没试过。但似乎用户每次应用程序时都必须启动,然后从后台开始录制。我对吗?我会尽快尝试这段代码。谢谢。 您能否更具体地说明一下在尝试这篇文章时究竟是什么不起作用? 在实践中,您在应用程序中移动活动时遇到问题,因为 Surface 在活动暂停时被破坏。在这一刻,您的视频记录上的图像停止了。我在这个主题中要求它:***.com/questions/15049041/… 【参考方案1】:

1- 我创建了一个活动来启动这样的服务:

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 - 现在我创建了在后台录制视频的服务,如下所示:

    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;
        
    

它将在您的 SD 卡中创建一个文件 video.mp4。您可以更改代码以添加更多功能,但基本功能是通过此代码实现的,即在后台录制视频。

注意:我已经通过按钮单击活动启动了服务,但您可以通过任何其他方式启动它,例如广播接收器等。

希望对你有帮助!!干杯。

【讨论】:

那么,当我最小化应用程序时,它会继续写视频,对吧? 但魔法在哪里?您只需在服务中使用摄像机。我认为应该有更神秘的东西。 ;) 是的,我很快就会给你 +50。 我想在服务中播放我的媒体播放器并将表面视图置于背景.. 有可能吗?你能给我一些例子吗 @DhwanikGandhi 这不是一个愚蠢的问题,杀死它后怎么能运行?它不是僵尸.. LOL 您正在尝试访问将在 Activity 变为 onPause 状态时销毁的 Surface 实例!我没有尝试过这段代码,但只要你的代码使用 SurfaceView,我就永远不会在后台工作。起初,因为这是公认的答案,所以我以为您做了一些技巧,但是在看到代码之后.. NAW。我真的希望有一些解决方法。【参考方案2】:

是的,您可以像这样录制背景视频:

首先,使用服务创建一个视频应用。不要将其视图设置为不可见。 如果您在服务中这样做,那就更好了,因为...

其次,您可以使用 AlarmManager 设置特定时间的闹钟,然后在那个时候,通过使用意图,再次启动您的服务。要停止您的应用,您也可以使用 AlarmManager。

【讨论】:

cool... 然后使用广播接收器启动您的视频应用程序。完成后让我知道我会告诉你下一步。 :) 你熟悉广播接收器仪式吗? 你能告诉我如何从Service制作SurfaceView实例的过程吗? 用于创建surfaceview对象只需在activity中创建surface view对象并将其放入intent.putExtra("string", object);然后启动服务(意图);从该活动和服务中创建意图 object=getIntent();在那里你可以收到你的surfaceview对象:) 你能给出可以接受对象的putextra方法的链接吗?我在developer.android.com/reference/android/content/Intent.html 没有找到。并且在不启动我的应用程序的情况下从服务中传递我所说的这个对象。【参考方案3】:

这里有一些很酷的 android 项目关于相同的一些变化:

https://github.com/zeitgeist87/SpartanTimeLapseRecorder/blob/master/src/at/andreasrohner/spartantimelapserec/recorder/VideoRecorder.java - 控制相机的FPS

https://www.sisik.eu/blog/android/media/camera2-from-service - 来自后台摄像头的图像

https://github.com/kevalpatel2106/android-hidden-camera/blob/master/hiddencamera/src/main/java/com/androidhiddencamera/HiddenCameraService.java

https://github.com/botyourbusiness/android-camera2-secret-picture-taker - 官方

https://gist.github.com/joseph-zhong/c2a52a5507d6588bec2db9869c860114

https://github.com/ulysses4ever/Background-VideoRecorder

【讨论】:

以上是关于如何从应用程序后台录制视频:Android的主要内容,如果未能解决你的问题,请参考以下文章

如何从我的 Android 设备直接在 Helix 服务器上录制视频?

如何录制视频并保持音乐在后台播放?

Android 自定义视频录制

如何在我的 Android 应用中录制视频?

在android中录制视频时如何在视频上绘图,并保存视频和绘图?

如何防止在 Android 应用程序中录制屏幕视频?