相机无法在 Android 设备上使用

发布于 2024-12-16 18:44:34 字数 5671 浏览 1 评论 0原文

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

我正在测试的设备是 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();  
    }  
}  

}

和清单

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

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

泪痕残 2024-12-23 18:44:34

相机预览在不同设备上的工作方式非常不同。我们在 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);

华泰
丹尼尔

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文