ela*_*dex 5 android android-camera
我有一项服务,我尝试将服务记录视频发送到文件.
启动服务的活动:
public static SurfaceView mSurfaceView;
public static SurfaceHolder mSurfaceHolder;
public static Camera mCamera;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.addCallback(this);
Intent intent = new Intent(MainActivity.this, RecordService.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
finish();
}
Run Code Online (Sandbox Code Playgroud)
服务:
private MediaRecorder mMediaRecorder;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private boolean mRecordingStatus;
private Camera mServiceCamera;
private Size mPreviewSize;
@Override
public void onCreate()
{
mRecordingStatus = false;
mSurfaceView = MainActivity.mSurfaceView;
mSurfaceHolder = MainActivity.mSurfaceHolder;
mServiceCamera=MainActivity.mCamera;
InitCamera();
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
if (!mRecordingStatus)
StartRecord();
else
StopRecord();
return START_STICKY;
}
private void InitCamera()
{
mServiceCamera = Camera.open();
Camera.Parameters p = mServiceCamera.getParameters();
final List<Size> listSize = p.getSupportedPreviewSizes();
mPreviewSize = listSize.get(2);
p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
mServiceCamera.setParameters(p);
try
{
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
}
catch (IOException e)
{
e.printStackTrace();
}
mServiceCamera.unlock();
}
private void StartRecord()
{
try
{
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(Environment.getExternalStorageDirectory().getPath()+File.separator+ "video.mp4");
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecordingStatus = true;
Toast toast = Toast.makeText(getBaseContext(), "Recording",1000);
toast.show();
}
catch (IOException e)
{
Toast toast = Toast.makeText(getBaseContext(), e.getMessage(),2000);
toast.show();
}
}
Run Code Online (Sandbox Code Playgroud)
当我调试我的Galaxy上的代码时,我得到了吐司(在StartRecord()方法中)"无效的预览表面"
怎么修好?
San*_*awy 18
您看到的原因是因为您mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
在创建曲面之前执行了.添加延迟恰好可行,但不是处理此问题的正确方法.
该线 mSurfaceHolder = mSurfaceView.getHolder();
不会立即创建曲面.实际上,SurfaceHolder提供了一个回调接口,可以让您知道何时创建了曲面.
该行mSurfaceHolder.addCallback(this);
应该在您创建的类的构造函数中,该类扩展了SurfaceView并实现了SurfaceHolder.Callback.然后,您可以覆盖SurfaceHolder.Callback接口的回调方法,以便在创建表面后执行代码.这是一个例子:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder surfaceHolder;
public CameraPreview(Context context, VideoHandler vh) {
super(context);
videoHandler = vh;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// Perform actions that require Surface to have been created here e.g.
// mMediaRecorder.setPreviewDisplay(holder.getSurface()); etc.
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Take care of releasing camera preview etc.
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Handle changes
}
}
Run Code Online (Sandbox Code Playgroud)
我必须让 MediaRecorder 启动延迟一些。这意味着在 中onResume
,我创建了一个处理程序并postDelayed
对其进行调用。我知道,它仍然是同一个线程,但它对我有用。