摄像头和SurfaceView奇怪的行为 [英] Strange behaviour with Camera and SurfaceView
问题描述
我要疯了与使用SurfaceView的。
I'm going crazy with the use of SurfaceView.
我已经开发了一个应用程序,它在固定的时间间隔拍摄照片。它与我的设备与Androd 2.3效果很好。下面是一个示例code:
I've developed an app which takes pictures at fixed time intervals. It works well with my device with Androd 2.3. Here is a sample code:
public class MainActivity extends Activity
{
private Camera mCamera;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
takeAPicture();
}
}
);
}
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera)
{
// ... save image ...
camera.release();
camera = null;
}
};
private void takeAPicture()
{
mCamera = getCameraInstance();
mCamera.takePicture(null, null, mPicture);
}
}
在同一code不与Android 4.1的工作。谷歌上搜索了一下,我发现,大多数现代的Android设备,现在检查一个SurfaceView存在并具有非零的宽度和高度。所以,我修改了上面的code如下:
The same code does not work with Android 4.1. Googling a bit I've found that "most of the modern Android devices now check that a SurfaceView exists and has a non-zero width and height". So I've modified the above code as follows:
public class MainActivity extends Activity
{
private Camera mCamera;
private CameraPreview mPreview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
takeAPicture();
}
}
);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera)
{
// ... save image ...
camera.release();
camera = null;
}
};
private void takeAPicture()
{
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
mCamera.takePicture(null, null, mPicture);
}
}
在那里摄像头preVIEW是:
where CameraPreview is:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera)
{
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder)
{
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(MainActivity.TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(MainActivity.TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
但PictureCallback不调用和应用程序的用户界面消失。用户界面是一个简单的的FrameLayout和一个按钮如下:
But the PictureCallback is not invoked and the user interface of the app disappear. The user interface is simply a FrameLayout and a button as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="100dp"
android:layout_height="100dp" />
<Button
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
怎么了?
请注意,如果我做的:
public class MainActivity extends Activity
{
private Camera mCamera;
private CameraPreview mPreview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.takePicture(null, null, mPicture);
}
}
);
}
当然,从本PictureCallback的mCamera.release()的,它完美的作品与Android 4.1的设备上。任何意见?
of course removing the mCamera.release() from the PictureCallback, it works perfectly on a device with Android 4.1. Any comment?
推荐答案
在点击,您可以创建相机preVIEW
的一个实例 - 这是好的,但需要时间和一些回调。你不能叫 mCamera.takePicture()
直到 SurfaceView 准备 - 这不会需要很长时间,但你仍然需要在这里的延迟。最简单的变化将是调用 mCamera.takePicture()从相机preview.surfaceCreated()
。
On click, you create an instance of CameraPreview
- which is fine, but takes time and some callbacks. You cannot call mCamera.takePicture()
until the SurfaceView is ready - this won't take long, but still you need a delay here. The easiest change would be to call mCamera.takePicture() from your CameraPreview.surfaceCreated()
.
这篇关于摄像头和SurfaceView奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!