Android应用屏幕关闭时的视频录制

23
我想要做的是制作一个应用程序,在屏幕关闭的情况下可以录制视频或音频。我们可以先开始录制然后关闭屏幕,或者录制器应该通过声音或任何其他外部命令触发。在任何情况下,应用程序都应该持续记录。
如果可以,请提供代码。

6
你到目前为止尝试了什么?请展示你遇到问题的代码。 - dave
1个回答

18
大多数情况下,当需要离线完成某些任务时,会使用一个 服务

enter image description here (www.slideshare.net)

假设您不知道服务是什么,从文档中可以看到:

服务是一种应用组件,表示应用程序希望执行较长时间的操作而不与用户交互或为其他应用程序提供功能。每个服务类都必须在其包的AndroidManifest.xml文件中有相应的声明。服务可以使用Context.startService()和Context.bindService()来启动。

因此,基本上,它只是在后台运行的东西,即使屏幕关闭也会继续运行。现在,您所要做的就是将您的录制代码放入一个服务中。 您可能会遇到一个问题,即系统会杀死您的服务,正如Android文档所指定的那样:

请注意,这意味着大多数情况下,如果您的服务承受着重的内存压力,系统可能会将其杀死。如果发生这种情况,系统稍后会尝试重新启动服务。这个重要的结果是,如果您实现了onStartCommand()以异步或在另一个线程中安排工作,则您可能需要使用START_FLAG_REDELIVERY来让系统重新发送一个Intent,以便在服务在处理它时被杀死时不会丢失。

在这种情况下,您需要添加一些代码以将服务保持在前台并确保它不会被终止:
startForeground();//keeps service from getting destroyed.

这可能会带来的唯一问题是服务存活时间的持续通知。
您还可以使用 startSticky()
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    
       // We want this service to continue running until it is explicitly
       // stopped, so return sticky.
       return START_STICKY;
}

现在,假设你已经完成录制。你可以使用:

stopSelf();

停止服务,或者:
Context.stopService();

这个通知并不是什么大问题,因为服务运行时屏幕很可能是关闭的。您还可以自定义通知,让用户了解后台正在发生什么更好。

以下是一些示例录制代码,来自vanevery在这里的回答

public class VideoCapture extends Activity implements OnClickListener, SurfaceHolder.Callback {
    MediaRecorder recorder;
    SurfaceHolder holder;
    boolean recording = false;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        recorder = new MediaRecorder();
        initRecorder();
        setContentView(R.layout.main);

        SurfaceView cameraView = (SurfaceView) findViewById(R.id.CameraView);
        holder = cameraView.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        cameraView.setClickable(true);
        cameraView.setOnClickListener(this);
    }

    private void initRecorder() {
        recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

        CamcorderProfile cpHigh = CamcorderProfile
                .get(CamcorderProfile.QUALITY_HIGH);
        recorder.setProfile(cpHigh);
        recorder.setOutputFile("/sdcard/videocapture_example.mp4");
        recorder.setMaxDuration(50000); // 50 seconds
        recorder.setMaxFileSize(5000000); // Approximately 5 megabytes
    }

    private void prepareRecorder() {
        recorder.setPreviewDisplay(holder.getSurface());

        try {
            recorder.prepare();
        } catch (IllegalStateException e) {
            e.printStackTrace();
            finish();
        } catch (IOException e) {
            e.printStackTrace();
            finish();
        }
    }

    public void onClick(View v) {
        if (recording) {
            recorder.stop();
            recording = false;

            // Let's initRecorder so we can record again
            initRecorder();
            prepareRecorder();
        } else {
            recording = true;
            recorder.start();
        }
    }

    public void surfaceCreated(SurfaceHolder holder) {
        prepareRecorder();
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        if (recording) {
            recorder.stop();
            recording = false;
        }
        recorder.release();
        finish();
    }
}

再次将那段代码放入一个长时间运行的前台服务中,就像我之前所解释的那样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接