各位 Android 开发者大家好。我正在开发一个应用程序,它使用相机来显示连续预览,并且当用户愿意时,从该源录制视频并保存。
我已经设置了第一部分,但我在录音工作时遇到问题。我遵循了各种指南和答案来解决我遇到的问题,但我似乎总是遇到“无效状态”问题(当前 setCamera 在无效状态下调用(4))。
这是我的完整代码。感谢您的浏览!
Camera camera;
SurfaceView preview;
SurfaceHolder previewHolder;
MediaRecorder recorder;
boolean recording = false;
boolean cameraConfigured = false;
private Button camera_button;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//Remove title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//Remove notification bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//Keep screen awake
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_fullscreen);
preview = (SurfaceView)findViewById(R.id.camerapreview);
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
camera_button = (Button) findViewById(R.id.camera_button);
camera_button.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
if (recording)
{
recorder.stop();
recording = false;
initRecorder();
prepareRecorder();
camera_button.setText("Record");
}
else
{
recording = true;
recorder.start();
camera_button.setText("Stop");
}
}
});
// Wake screen
WakeLock screenLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
screenLock.acquire();
screenLock.release();
}
@Override
public void onResume()
{
super.onResume();
if (camera == null)
{
camera = Camera.open();
}
preview.setVisibility(View.VISIBLE);
startPreview();
}
@Override
public void onPause()
{
if(camera != null)
{
camera.stopPreview();
camera.release();
camera = null;
cameraConfigured = false;
}
preview.setVisibility(View.INVISIBLE);
super.onPause();
}
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback()
{
public void surfaceCreated(SurfaceHolder holder)
{
initRecorder();
prepareRecorder();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height)
{
initPreview(width, height);
startPreview();
}
public void surfaceDestroyed(SurfaceHolder holder)
{
if (recording)
{
recorder.stop();
recording = false;
}
recorder.release();
}
};
private void initRecorder()
{
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile cpHigh = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
recorder.setOutputFile("/sdcard" + File.separator + "testVideo_" + timeStamp + ".mp4");
camera.unlock();
recorder.setCamera(camera);
}
private void prepareRecorder()
{
recorder.setPreviewDisplay(previewHolder.getSurface());
try
{
recorder.prepare();
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
private void initPreview(int width, int height)
{
if (camera != null && previewHolder.getSurface() != null)
{
try
{
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable t)
{
Log.e("CameraTest","");
}
if (!cameraConfigured)
{
Camera.Parameters parameters=camera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);
Camera.Size pictureSize = getSmallestPictureSize(parameters);
if (size != null && pictureSize != null)
{
parameters.setPreviewSize(size.width, size.height);
parameters.setPictureSize(pictureSize.width,
pictureSize.height);
parameters.set("cam_mode", 1 );
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
parameters.setPictureFormat(ImageFormat.JPEG);
camera.setParameters(parameters);
cameraConfigured=true;
}
}
}
}
private void startPreview()
{
if (cameraConfigured && camera != null)
{
camera.startPreview();
}
}
public Camera.Size getBestPreviewSize(int width, int height,
Camera.Parameters parameters)
{
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPreviewSizes())
{
if ((size.width <= width && size.height <= height) || (size.height <= width && size.width <= height))
{
if (result == null)
{
result=size;
}
else
{
int resultArea=result.width * result.height;
int newArea=size.width * size.height;
if (newArea > resultArea)
{
result=size;
}
}
}
}
return(result);
}
public Camera.Size getSmallestPictureSize(Camera.Parameters parameters)
{
Camera.Size result=null;
for (Camera.Size size : parameters.getSupportedPictureSizes())
{
if (result == null)
{
result=size;
}
else
{
int resultArea=result.width * result.height;
int newArea=size.width * size.height;
if (newArea < resultArea)
{
result=size;
}
}
}
return(result);
}
最佳答案
查看 android video recording sample code ,android需要一个非常特定的顺序来配置mediaRecorder。在我看来,你应该按如下方式安排你的 initRecorder()
:
private void initRecorder()
{
recorder = new MediaRecorder();
// The following two lines should precede setAudioSource line
camera.unlock();
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile cpHigh = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
recorder.setOutputFile("/sdcard" + File.separator + "testVideo_" + timeStamp + ".mp4");
}
关于android - 从已经运行的预览中录制视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22055450/