问题背景:要让Camera循环聚焦,聚焦完成后进行拍照,在拍照的数据里截取出一定区域的数据。在initCamera里设置聚焦模式:

List<String> allFocus = myParam.getSupportedFocusModes();for(String ff:allFocus){Log.i(tag, ff + "...FOCUS...");}if(allFocus.contains(Camera.Parameters.FLASH_MODE_AUTO)){myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);  Focus_Mode = 1;}else if(allFocus.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)){myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);  // FOCUS_MODE_CONTINUOUS_PICTURE FOCUS_MODE_AUTOFocus_Mode = 2;}myCamera.setParameters(myParam);

然后有个GetPictureThread进行每隔一段时间聚焦并且拍照:

class GetPictureThread implements Runnable{public void run() {// TODO Auto-generated method stubwhile(!Thread.currentThread().isInterrupted()){if(myCamera != null && isPreview){if(Focus_Mode == 1 && (!isFocusing)){myCamera.autoFocus(mAutoFocusCallback);}else if(Focus_Mode == 2){myCamera.takePicture(myShutterCallback, null, myJpegCallback);}try {Thread.sleep(3000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();Thread.currentThread().interrupt();}}}}}

原来设的GetPictureThread是每隔1200毫秒触发一次,在中兴的Geek手机上一切良好。在华为G700上,总是拍一张就挂,挂的log如下:

12-07 18:05:33.227: D/dalvikvm(13589): threadid=11: exiting12-07 18:05:33.227: W/dalvikvm(13589): threadid=11: thread exiting with uncaught exception (group=0x417669a8)12-07 18:05:33.230: E/AndroidRuntime(13589): FATAL EXCEPTION: Thread-117712-07 18:05:33.230: E/AndroidRuntime(13589): java.lang.RuntimeException: autoFocus failed12-07 18:05:33.230: E/AndroidRuntime(13589): at android.hardware.Camera.native_autoFocus(Native Method)12-07 18:05:33.230: E/AndroidRuntime(13589): at android.hardware.Camera.autoFocus(Camera.java:1120)12-07 18:05:33.230: E/AndroidRuntime(13589): at org.yanzi.rectphoto_wuzhou.RectPhoto$GetPictureThread.run(RectPhoto.java:428)12-07 18:05:33.230: E/AndroidRuntime(13589): at java.lang.Thread.run(Thread.java:838)12-07 18:05:33.240: I/Camera(13589): handleMessage: 2

反正就是auto focus出问题了,单看这里的log看不出所以然来。话说2000元买的G'700还是支持自动聚焦的吧。截取所有的log又看了次,搜索关键字:autofocus,得到以下信息:

  F:\1.log (12 hits)Line 12829: 12-08 10:14:19.477 D/CameraClient(  142): autoFocus (pid 10314)Line 12831: 12-08 10:14:19.477 D/MtkCam/CamDevice(  142): (599)(Default:0)[CamDevice::autoFocus] +Line 12834: 12-08 10:14:19.477 D/MtkCam/CamAdapter(  142): (599)(Default)[autoFocus] +Line 12861: 12-08 10:14:19.477 D/aaa_hal (  142): [autoFocus()]Line 12877: 12-08 10:14:19.477 D/MtkCam/CamAdapter(  142): (599)(Default)[autoFocus] -Line 20489: 12-08 10:14:20.677 D/CameraClient(  142): autoFocus (pid 10314)Line 20491: 12-08 10:14:20.677 D/MtkCam/CamDevice(  142): (142)(Default:0)[CamDevice::autoFocus] +Line 20503: 12-08 10:14:20.678 E/MtkCam/CamDevice(  142): (142)(Default:0)[CamDevice::autoFocus] preview is not enabled (autoFocus){#552:mediatek/hardware/camera/device/CamDevice/CamDevice.cpp}Line 20503: 12-08 10:14:20.678 E/MtkCam/CamDevice(  142): (142)(Default:0)[CamDevice::autoFocus] preview is not enabled (autoFocus){#552:mediatek/hardware/camera/device/CamDevice/CamDevice.cpp}Line 20512: 12-08 10:14:20.679 E/AndroidRuntime(10314): java.lang.RuntimeException: autoFocus failedLine 20514: 12-08 10:14:20.679 E/AndroidRuntime(10314): at android.hardware.Camera.native_autoFocus(Native Method)Line 20516: 12-08 10:14:20.679 E/AndroidRuntime(10314): at android.hardware.Camera.autoFocus(Camera.java:1120)
可以看到,上面提到preview is not enabled,竟然说preview没有开启。可我明明preview已经开启了,而且我在扫描线程里设置了判断if(myCamera != null && isPreview)。参考国外这位大大的帖子http://www.hitziger.net/blog/android-camera-autofocus-failed/上面提到auto focus失败原因是surfaceholder还没有被创建,换句话camera还没有开启预览就进行自动聚焦了。但其实我的扫描线程启动已经加了延迟,确保camera预览已经开启,姑且信了吧。把线程开启的地方加到了surfacechanged,因为我的initcamera是在surfacechanged里面,initcamera的最后就是startPreview。但依然出错。我加了个延迟在surfacechanged依旧报错。后来参考又一个人的帖子,在activity的onResume方法里进行mySurfaceHolder.addCallback(this);确保surfaceview已经创建了再添加回调。这样干确实严谨一点,但依旧报错。事实上这样做不是必须的,因为我把GetPictureThread去掉之后,一切ok。我加个button,拍照的时候自动聚焦,如果聚焦成功再触发takePicture也是ok的。

问题出在哪呢?最后才恍然大悟,问题在拍照的jpegCallback上,代码如下:

PictureCallback myJpegCallback = new PictureCallback() {public void onPictureTaken(byte[] data, Camera camera) {// TODO Auto-generated method stubLog.i(tag, "myJpegCallback:onPictureTaken...");long t1 = System.currentTimeMillis();if(null != data){mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);myCamera.stopPreview();isPreview = false;}Matrix matrix = new Matrix();matrix.postRotate((float)90.0);Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);//Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);Bitmap rectBitmap = Bitmap.createBitmap(rotaBitmap, square.left, square.top, square.width(), square.height());if(null != rectBitmap){saveThread.setSaveBitmap(rectBitmap);}//ImageUtil.saveJpeg(rotaBitmap);myCamera.startPreview();isPreview = true;long t2 = System.currentTimeMillis();Log.i(tag, "本次保存耗时:" + (t2 - t1) + "毫秒");}};
注意在拍照时,camera首先停止预览保存完照片后再次开启预览。尽管我加了isPreview这个标志,但这个标志位是不起啥作用的。推测,stoppreviw和startpreview的时候,camera在底层是异步处理的。也就是说程序执行到startpreview,isPreview为真了,但这时camera还没有完全开启预览,而扫描线程再次触发auto focus就会报上面的错误。后来我对这个myJpegCallback测了下时间,完全同样的代码,在geek手机上是900多毫秒左右,在G700上是1800毫秒左右,将近2秒了,所以扫描周期一定得大于这个时间。后来将扫描周期设为3秒,两个手机都ok了。但G700上偶发的也还是会报错,这是因为内存占用太多,手机速度变慢,myJpegCallback回调的周期超过了3秒,重启下手机就好了。在AutoFocusCallback里设置标志isFocusing也是必须的。

final AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback() {public void onAutoFocus(boolean success, Camera camera) {// TODO Auto-generated method stubisFocusing = true;if(success){Log.i(tag, "聚焦成功...");myCamera.takePicture(myShutterCallback, null, myJpegCallback);}else{Log.i(tag, "聚焦失败...");}isFocusing = false;}};

看来,要玩Camera还是得整个高端点的手机啊!!!

参考http://stackoverflow.com/questions/5878042/android-camera-autofocus-on-demand自从API9,就有了连续聚焦。参考官方对聚焦模式的说明,http://developer.android.com/reference/android/hardware/Camera.Parameters.html#FOCUS_MODE_CONTINUOUS_VIDEO聚焦最强的是FOCUS_MODE_CONTINUOUS_PICTURE它是和AutoFocus兼容的,其次是

FOCUS_MODE_CONTINUOUS_VIDEO,聚焦强度弱于CONTINUOUS_PICTURE. 所以如果能满足需要的话,FOCUS_MODE_CONTINUOUS_VIDEO 就ok了!有些资料不建议周期性auto focus,但看今天的扫描二维码貌似都是用的auto focus模式,而不是连续聚焦,所以可以肯定,在这种模式下,获得数据是从预览帧里截取的,而不是拍照。因为拍照在普通手机上一定得停预览然后开预览,这个花费时间太大了!如果是为了高更分辨率,只能拍照的话一定要控制好扫描周期。

更多相关文章

  1. MVP模式的Android(安卓)调用系统拍照,相册,剪裁,适配到7.0,修复拍照
  2. android调用系统相机拍照保存照片并显示在当前界面
  3. PhotoDraweeView+Fresco模式 预览图像 修改缩放比例方法
  4. Java乔晓松-android中调用系统拍照功能并显示拍照的图片
  5. android 部分手机Camera 拍照 图片被旋转90度的解决方法
  6. Android更新到API26之后,targetVersion26,调用系统相机拍照遇到的
  7. android --拍照相册选取图片[兼容小米等其他手机]
  8. Android(安卓)调用系统相机拍照并获取图片
  9. android 拍照获得的照片太小太娇气 的 解决方法

随机推荐

  1. Android(安卓)的EditText实现不可编辑
  2. 打开Android(安卓)Studio报错"required p
  3. android获取屏幕分辨率大小(DisplayMetri
  4. 转贴:Icon Design Guidelines, Android(安
  5. Android-- Intent.Action(1)
  6. Android学习札记22:ThumbnailUtils
  7. Android(安卓)Studio 快捷键
  8. android studio 3.1 Android(安卓)Device
  9. 关于listView设置背景引起StackOverflowE
  10. android 中常用的权限