我找到了一些使用相机的教程。模拟器上没有错误,但它在设备上崩溃了,为什么?我只是创建简单的代码来预览图片。
我正在测试的设备是HTC Wildfire Android 2.2
主类

private Camera camera;
private boolean isPreviewRunning = false;
private SimpleDateFormat timeStampFormat = new SimpleDateFormat("yyyyMMddHHmmssSS");

private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;

public void onCreate(Bundle icicle)
{
    super.onCreate(icicle);
    Log.e(getClass().getSimpleName(), "onCreate");
    getWindow().setFormat(PixelFormat.TRANSLUCENT);
    setContentView(R.layout.main);
    surfaceView = (SurfaceView)findViewById(R.id.surface);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}


@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
}

Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback()
{
    public void onPictureTaken(byte[] data, Camera c)
    {
         Log.e(getClass().getSimpleName(), "PICTURE CALLBACK RAW: " + data);
         camera.startPreview();
    }
};

Camera.PictureCallback mPictureCallbackJpeg= new Camera.PictureCallback()
{
    public void onPictureTaken(byte[] data, Camera c)
    {
         Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
    }
};

Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback()
{
    public void onShutter()
    {
        Log.e(getClass().getSimpleName(), "SHUTTER CALLBACK");
    }
};


public boolean onKeyDown(int keyCode, KeyEvent event)
{
    ImageCaptureCallback iccb = null;
    if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
    {
        try
        {
            String filename = timeStampFormat.format(new Date());
            ContentValues values = new ContentValues();
            values.put(Media.TITLE, filename);
            values.put(Media.DESCRIPTION, "Image capture by camera");
            Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
            //String filename = timeStampFormat.format(new Date());
            iccb = new ImageCaptureCallback( getContentResolver().openOutputStream(uri));
        }
        catch(Exception ex )
        {
            ex.printStackTrace();
            Log.e(getClass().getSimpleName(), ex.getMessage(), ex);
        }
    }

    if (keyCode == KeyEvent.KEYCODE_BACK)
    {
        return super.onKeyDown(keyCode, event);
    }

    if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
    {
        camera.takePicture(mShutterCallback, mPictureCallbackRaw, iccb);
        return true;
    }

    return false;
}

protected void onResume()
{
    Log.e(getClass().getSimpleName(), "onResume");
    super.onResume();
}

protected void onSaveInstanceState(Bundle outState)
{
    super.onSaveInstanceState(outState);
}

protected void onStop()
{
    Log.e(getClass().getSimpleName(), "onStop");
    super.onStop();
}

public void surfaceCreated(SurfaceHolder holder)
{
    Log.e(getClass().getSimpleName(), "surfaceCreated");
    camera = Camera.open();
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
    Log.e(getClass().getSimpleName(), "surfaceChanged");
    if (isPreviewRunning)
    {
        camera.stopPreview();
    }

    Camera.Parameters p = camera.getParameters();
    p.setPreviewSize(w, h);
    camera.setParameters(p);

    try
    {
        camera.setPreviewDisplay(holder);
    }

    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    camera.startPreview();
    isPreviewRunning = true;
}

public void surfaceDestroyed(SurfaceHolder holder)
{
    Log.e(getClass().getSimpleName(), "surfaceDestroyed");
    camera.stopPreview();
    isPreviewRunning = false;
    camera.release();
}

}
图像捕获回调
private OutputStream filoutputStream;

public ImageCaptureCallback(OutputStream filoutputStream)
{
    this.filoutputStream = filoutputStream;
}

@Override
public void onPictureTaken(byte[] data, Camera camera)
{
    try
    {
        Log.v(getClass().getSimpleName(), "onPictureTaken=" + data + " length = " + data.length);
        filoutputStream.write(data);
        filoutputStream.flush();
        filoutputStream.close();
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}

}
以及清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.photo.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:label="@string/app_name"
        android:name=".Main" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

最佳答案

相机预览在不同设备上的工作方式非常不同。我们在mixare增强现实引擎中遇到了很多问题。
首先,最好使用兼容类让代码在旧设备上工作。你可以在这里看到代码:
https://github.com/mixare/mixare/blob/master/src/org/mixare/Compatibility.java
然后,如您所见,您有责任在系统提供的预览列表中选择正确的预览:
https://github.com/mixare/mixare/blob/master/src/org/mixare/MixView.java在871号线,正在进行中。

            List<Camera.Size> supportedSizes = null;
            //On older devices (<1.6) the following will fail
            //the camera will work nevertheless
            supportedSizes = Compatibility.getSupportedPreviewSizes(parameters);

            //preview form factor
            float ff = (float)w/h;
            Log.d("Mixare", "Screen res: w:"+ w + " h:" + h + " aspect ratio:" + ff);

            //holder for the best form factor and size
            float bff = 0;
            int bestw = 0;
            int besth = 0;
            Iterator<Camera.Size> itr = supportedSizes.iterator();

            //we look for the best preview size, it has to be the closest to the
            //screen form factor, and be less wide than the screen itself
            //the latter requirement is because the HTC Hero with update 2.1 will
            //report camera preview sizes larger than the screen, and it will fail
            //to initialize the camera
            //other devices could work with previews larger than the screen though
            while(itr.hasNext()) {
                Camera.Size element = itr.next();
                //current form factor
                float cff = (float)element.width/element.height;
                //check if the current element is a candidate to replace the best match so far
                //current form factor should be closer to the bff
                //preview width should be less than screen width
                //preview width should be more than current bestw
                //this combination will ensure that the highest resolution will win
                Log.d("Mixare", "Candidate camera element: w:"+ element.width + " h:" + element.height + " aspect ratio:" + cff);
                if ((ff-cff <= ff-bff) && (element.width <= w) && (element.width >= bestw)) {
                    bff=cff;
                    bestw = element.width;
                    besth = element.height;
                }
            }
            Log.d("Mixare", "Chosen camera element: w:"+ bestw + " h:" + besth + " aspect ratio:" + bff);
            //Some Samsung phones will end up with bestw and besth = 0 because their minimum preview size is bigger then the screen size.
            //In this case, we use the default values: 480x320
            if ((bestw == 0) || (besth == 0)){
                Log.d("Mixare", "Using default camera parameters!");
                bestw = 480;
                besth = 320;
            }
            parameters.setPreviewSize(bestw, besth);

高温高压
达妮埃莱

10-08 17:28