Note that there are some explanatory texts on larger screens.

plurals
  1. POStrange behaviour with Camera and SurfaceView
    primarykey
    data
    text
    <p>I'm going crazy with the use of SurfaceView.</p> <p>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:</p> <pre><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></pre> <p>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:</p> <pre><code>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); } } </code></pre> <p>where CameraPreview is:</p> <pre><code>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()); } } } </code></pre> <p>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:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"&gt; &lt;FrameLayout android:id="@+id/camera_preview" android:layout_width="100dp" android:layout_height="100dp" /&gt; &lt;Button android:id="@+id/button_capture" android:text="Capture" android:layout_width="wrap_content" android:layout_height="wrap_content" /&gt; &lt;/LinearLayout&gt; </code></pre> <p>What's wrong?</p> <p>Please note that if I do:</p> <pre><code>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); } } ); } </code></pre> <p>of course removing the mCamera.release() from the PictureCallback, it works perfectly on a device with Android 4.1. Any comment? </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload