简体   繁体   中英

Camera doesn't work on Android device

I found some tutorials to use the camera. There are no errors on the emulator, but it crashes on the device, why? I'm just creating simple code to preview the picture.

The device I'm testing is the HTC Wildfire Android 2.2

Mainclass

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();  
}  

}

ImageCaptureCallBack

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();  
    }  
}  

}

and the manifest

<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>

camera preview is working very differently on different devices. We had a lot of issues in mixare augmented reality engine.

First, it's better to use a compatibility class to let your code work on older devices. You can see the code here:

https://github.com/mixare/mixare/blob/master/src/org/mixare/Compatibility.java

Then, as you can see here, it's your responsibility to choose the correct one among the list of the previews provided by the system: https://github.com/mixare/mixare/blob/master/src/org/mixare/MixView.java at line 871 and ongoing.

            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);

HTH Daniele

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM