setParameters() fails despite setting preview size

2019-06-21 08:22发布

问题:

I'm making a simple demo where I can feed the camera preview to a SurfaceView in my activity. I came to know that setParameters() fails if you don't set a supported size. But even when I did that, I'm getting the same FATAL EXCEPTION. Please help!

Code:

package ank.altcamera;

import java.io.IOException;
import java.util.List;

import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.Toast;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Size;

public class CameraActivity extends Activity implements SurfaceHolder.Callback{

    Switch sw_flash;
    SeekBar sb_zoom;

    Camera cam;
    SurfaceView surf_view;
    SurfaceHolder surf_holder;
    boolean preview;

    final int TAKE_PICTURE = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);

        sw_flash = (Switch) findViewById(R.id.sw_flash);
        sb_zoom = (SeekBar) findViewById(R.id.seekBar1);

        //camera settings
        surf_view = (SurfaceView) findViewById(R.id.surfaceView);
        surf_holder = surf_view.getHolder();
        surf_holder.addCallback(CameraActivity.this);
    }

    /* Must implement Interface methods */

    //onClickListener for the button
    public void takePicture (View v) {

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub
        if (preview) {
            cam.stopPreview();
        }

        Camera.Parameters p = cam.getParameters();

        //check for supported sizes to avoid exceptions
        Size size = getBestPreviewSize(width, height, p);
        p.setPreviewSize(size.width, size.height);
        //move ahead
        p.setPreviewFormat(ImageFormat.JPEG);
        cam.setParameters(p);

        //start the preview
        try {
            cam.setPreviewDisplay(surf_holder);
            cam.startPreview();
            preview = true;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub

        cam = Camera.open();

        if (cam != null){
            Camera.Parameters params = cam.getParameters();
            cam.setParameters(params);
        }
        else {
            Toast.makeText(getApplicationContext(), "Camera error.", Toast.LENGTH_LONG).show();
            finish();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        cam.stopPreview();
        preview = false;
        cam.release();

    }

    private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters){
         Size bestSize = null;
         List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();

         bestSize = sizeList.get(0);

         for(int i = 1; i < sizeList.size(); i++){
          if((sizeList.get(i).width * sizeList.get(i).height) >
            (bestSize.width * bestSize.height)){
           bestSize = sizeList.get(i);
          }
         }

         return bestSize;
        }
}

And here's my layout XML file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background_main"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".CameraActivity" >

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="18dp"
        android:minWidth="100dp"
        android:text="Awesome Camera"
        android:textColor="#fff"
        android:textSize="25sp"
        android:textStyle="bold" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:layout_marginTop="5dp"
            android:text="Zoom"
            android:textColor="#fff"
            android:textStyle="bold" />

        <SeekBar
            android:id="@+id/seekBar1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp" />
    </LinearLayout>

    <Switch
        android:id="@+id/sw_flash"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Flash"
        android:textColor="#fff"
        android:textStyle="bold" />

    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:background="#fff"
        android:onClick="takePicture"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:text="Take Picture" />

</LinearLayout>

And finally, the logcat ouput:

06-22 10:26:50.421: D/TextLayoutCache(12360): Using debug level: 0 - Debug Enabled: 0
06-22 10:26:50.511: D/libEGL(12360): loaded /system/lib/egl/libGLES_android.so
06-22 10:26:50.561: D/libEGL(12360): loaded /system/lib/egl/libEGL_adreno200.so
06-22 10:26:50.601: D/libEGL(12360): loaded /system/lib/egl/libGLESv1_CM_adreno200.so
06-22 10:26:50.601: D/libEGL(12360): loaded /system/lib/egl/libGLESv2_adreno200.so
06-22 10:26:50.701: I/Adreno200-EGLSUB(12360): <ConfigWindowMatch:2218>: Format RGBA_8888.
06-22 10:26:50.711: D/memalloc(12360): /dev/pmem: Mapped buffer base:0x516f6000 size:5775360 offset:4239360 fd:58
06-22 10:26:50.711: D/OpenGLRenderer(12360): Enabling debug mode 0
06-22 10:26:51.491: D/AndroidRuntime(12360): Shutting down VM
06-22 10:26:51.491: W/dalvikvm(12360): threadid=1: thread exiting with uncaught exception (group=0x40c28a68)
06-22 10:26:51.501: E/AndroidRuntime(12360): FATAL EXCEPTION: main
06-22 10:26:51.501: E/AndroidRuntime(12360): java.lang.RuntimeException: setParameters failed
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.hardware.Camera.native_setParameters(Native Method)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.hardware.Camera.setParameters(Camera.java:1476)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at ank.altcamera.CameraActivity.surfaceChanged(CameraActivity.java:71)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.view.SurfaceView.updateWindow(SurfaceView.java:591)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.view.SurfaceView.access$000(SurfaceView.java:81)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:173)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:590)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1799)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2632)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.os.Handler.dispatchMessage(Handler.java:99)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.os.Looper.loop(Looper.java:137)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at android.app.ActivityThread.main(ActivityThread.java:4517)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at java.lang.reflect.Method.invokeNative(Native Method)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at java.lang.reflect.Method.invoke(Method.java:511)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
06-22 10:26:51.501: E/AndroidRuntime(12360):    at dalvik.system.NativeStart.main(Native Method)
06-22 10:27:00.301: I/Process(12360): Sending signal. PID: 12360 SIG: 9

Please help me out!

回答1:

The documentation states that setParameters throws a RuntimeException when any of the parameters are invalid or not supported.

The parameters you are changing are the size and the format; However, your're taking the sizes from getSupportedPreviewSizes so they mustn't be the problem. I guess the problem is with setPreviewFormat(ImageFormat.JPEG).



回答2:

It is always important with this error to make sure you check all of the parameters that the camera is asking to set to make sure that every parameter you are asking the camera to set itself to is possible for the camera.

Camera.Parameters parameters = myCamera.getParameters();

With the preview size:

if (myCamera.getParameters().getSupportedPreviewSizes() != null){
     Camera.Size previewSize = getOptimalPreviewSize(myCamera.getParameters().getSupportedPreviewSizes(), width, height);;
     parameters.setPreviewSize(previewSize.width, previewSize.height);
}

With the flash/focus modes:

if(parameters.getSupportedFocusModes() != null && parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){
     parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}

if (parameters.getSupportedFlashModes() != null && parameters.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_AUTO)){
    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);

}

myCamera.setParameters(parameters);

etc. All of this wrapped in a nice try{}catch(){} works great. Good luck.

Here is the getOptimalPreview Size from this great tutorial:

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height)
    {
        // Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
        Camera.Size optimalSize = null;

        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) height / width;

        // Try to find a size match which suits the whole screen minus the menu on the left.
        for (Camera.Size size : sizes){

            if (size.height != width) continue;
            double ratio = (double) size.width / size.height;
            if (ratio <= targetRatio + ASPECT_TOLERANCE && ratio >= targetRatio - ASPECT_TOLERANCE){
                optimalSize = size;
            }
        }

        // If we cannot find the one that matches the aspect ratio, ignore the requirement.
        if (optimalSize == null) {
            // TODO : Backup in case we don't get a size.
        }

        return optimalSize;
    }


回答3:

You can't tell which parameter cause runtime exception from the message text it shows. You had better check parameters one by one.