我知道,这个问题被问过很多次,但我认为没有解决方案。我正在开发应用程序,该应用程序应针对所有具有 android 系统和后置摄像头的设备。问题是我只能在两台设备上测试应用程序,并且必须确保它可以在所有设备上运行。我认为唯一合理的解决方案是找到可以在几乎所有设备上运行的相机 api 代码示例。有没有人可以提供这样的来源......但是来源......真的在maaaaany(ALL)设备上测试过?我的头发都掉光了……而且……我想我正在失去理智……这完全是因为我发布了应用程序(仅用于我公司的测试),该应用程序仅在两个上进行了测试设备,并且以应该可以工作的方式使用相机 api,但似乎有一些手机,例如 HTC 渴望高清或 HTC Evo 3d(带 3d 相机),应用程序只是崩溃(因为 fu..ing 相机)或冻结(也因为 fu..ing 相机)。如果有人有真正测试过的相机 api 源(定期拍摄没有用户 gui 交互的照片),请善待,如果可以,请发布源或将我重定向到适当的位置。
嗯,也许这个问题听起来应该是这样的:“技术上是否可以在所有设备上使用相机 API?”
也许我会描述一下我目前是如何使用 api 的。
1)初始化凸轮:
public void initCam()
{
LoggingFacility.debug("Attempting to initialize camera",this);
LoggingFacility.debug("Preview is enabled:"+isPreview,this);
try {
if (camera==null)
{
camera = Camera.open();
camera.setPreviewDisplay(mHolder);
if (camera!=null)
{
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPictureSizes();
if (sizes!=null)
{
Size min = sizes.get(0);
for (Size size : sizes)
if (size.width<min.width) min = size;
{
parameters.setPictureSize(min.width, min.height);
}
}
camera.setParameters(parameters);
setDisplayOrientation(90);
}
}
startPreview(aps);
} catch (Throwable e){
if (exceptionsCallback!=null)
exceptionsCallback.onException(e);
}
}
2) 开始预览:
private void startPreview(AfterPreviewStarted after)
{
try {
if (!isPreview)
{
LoggingFacility.debug("Starting preview",this);
//camera.stopPreview();
camera.startPreview();
isPreview = true;
LoggingFacility.debug("Preview is enabled:"+isPreview,this);
}
if (after!=null) after.doAfter();
}catch(Throwable e)
{
if (exceptionsCallback!=null)
exceptionsCallback.onException(e);
}
}
3) 拍照:
public void takePicture(final PictureCallback callback)
{
LoggingFacility.debug("Attempting to take a picture",this);
if (camera!=null)
{
if (isPreview)
{
try
{
LoggingFacility.debug("preview is enabled jut before taking picture",this);
//AudioManager mgr = (AudioManager)ctx.getSystemService(Context.AUDIO_SERVICE);
//mgr.setStreamMute(AudioManager.STREAM_SYSTEM, true);
LoggingFacility.debug("Taking picture... preview will be stopped...",this);
isPreview = false;
camera.takePicture(null, new PictureCallback(){
public void onPictureTaken(byte[] arg0, Camera arg1)
{
//LoggingFacility.debug("Picture has been taken - 1t callback",CameraPreview.this);
}
}, callback);
//mgr.setStreamMute(AudioManager.STREAM_SYSTEM, false);
} catch (Throwable e){
if (exceptionsCallback!=null)
exceptionsCallback.onException(e);
}
}
}
4) 完成后或表面处理后释放相机。
public void releaseCam()
{
LoggingFacility.debug("Attempting to release camera",this);
if (camera!=null)
{
isTakingPictures = false;
camera.stopPreview();
isPreview = false;
camera.release();
camera = null;
LoggingFacility.debug("A camera connection has been released...",this);
}
}
在回调方法的第三个代码片段中,我再次调用 startPreview,因为拍照后预览被禁用,并且某些智能手机需要开始预览才能制作图片。以上所有方法都是扩展SurfaceView 并实现SurfaceHolder.Callback的类的一部分,并且是活动的一部分。
SurfaceHolder.Callback 实现如下:
public void surfaceCreated(SurfaceHolder holder) {
initCam();
}
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCam();
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
}
类的构造函数
CameraPreview(Context context) {
super(context);
this.ctx = context;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
我也在考虑另一种方法 - 克服拍照,而不是注册 onPreviewFrame 回调,例如在这个回调中检查标志是否已请求图片,如果是 - 将图像转换为位图并在进一步处理中使用它。我正在尝试这种方法,但后来遇到了另一个问题——即使我注册了空回调,gui 的响应也会慢得多。
对于像我一样在使用 android camera api 时遇到问题的每个人,请参考此链接。此示例中的代码似乎适用于大多数智能手机。