Monday, November 9, 2015

Zxing 给二维码添加闪光灯遇到的各种问题



使用Zxing 的插件 实现了二维码的扫买,但是现在我想在二维码的基础之上,添加闪光灯。但是,我遇到了各种的问题,在这里总结一下。

先说一下我的思考:
如果我要做一个 闪光灯的话,为了以后的方便,我要提取一个工具类,所以我自定义了一个 FlashLightUtils, 在里面进行处理 闪光灯的而所有处理。 包括Camera 的初始化,但是这个时候我遇到了:
无法链接 camera 服务,这让我蛋疼,我想了半天也没有想到为什么?

出现这样的问题的原因是:系统只有一个Camera对象,我再重新声明一个Camera对象的话,当然会报错,这是我犯错误比较严重的地方,果然还是应该先细读一下Zxing的源码啊!
 you will see thsi line code:
theCamera = new OpenCameraManager().build().open();

public synchronized void openDriver(SurfaceHolder holder)
      throws IOException {
   Camera theCamera = camera;   if (theCamera == null) {
      theCamera = new OpenCameraManager().build().open();      if (theCamera == null) {
         throw new IOException();      }
      camera = theCamera;   }
   theCamera.setPreviewDisplay(holder);
   if (!initialized) {
      initialized = true;      configManager.initFromCameraParameters(theCamera);      if (requestedFramingRectWidth > 0 && requestedFramingRectHeight > 0) {
         setManualFramingRect(requestedFramingRectWidth,               requestedFramingRectHeight);         requestedFramingRectWidth = 0;         requestedFramingRectHeight = 0;      }
   }

   Camera.Parameters parameters = theCamera.getParameters();   String parametersFlattened = parameters == null ? null : parameters
         .flatten(); // Save these, temporarily   try {
      configManager.setDesiredCameraParameters(theCamera, false);   } catch (RuntimeException re) {
      // Driver failed      Log.w(TAG,                   "Camera rejected parameters. Setting only minimal safe-mode parameters");      Log.i(TAG, "Resetting to saved camera params: "                   + parametersFlattened);      // Reset:      if (parametersFlattened != null) {
         parameters = theCamera.getParameters();         parameters.unflatten(parametersFlattened);         try {
            theCamera.setParameters(parameters);            configManager.setDesiredCameraParameters(theCamera, true);         } catch (RuntimeException re2) {
            // Well, darn. Give up            Log.w(TAG,                           "Camera rejected even safe-mode parameters! No configuration");         }
      }
   }

}


我在自己的Activity中又初始化了一次 Camera
Camara mCamera = Camera.open();
所以导致了,

ailed to connect to camera service


解决方法:因为Zxing扫描启动的时候已经初始化了一个Camera对象了,所以没有必要再重新声明一个对象。




注意:
这里很蛋疼的,以为一开的时候调用的时候,CameraManager 里面的Camera 老师为null,我找了好长时间也没有找到,后来不知怎么的就好了。我也是醉了,只是现在还没找到原因!



权限的问题: 我就不说了,你们搜一下就好了:
<uses-permission android:name="android.permission.CAMERA"/><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-feature android:name="android.hardware.camera" /><uses-feature android:name="android.hardware.camera.autofocus" /><uses-feature android:name="android.hardware.camera.flash" />


在就是当你阅读官网的文档的时候:
public static Camera open (int cameraId)

Caution: On some devices, this method may take a long time to complete. It is best to call this method from a worker thread (possibly using AsyncTask) to avoid blocking the main application UI thread.

建议用异步任务来实现,但是我个人比较喜欢Handler.下面是我的实现方式:

1 第一步 在Camera 里面方法抽取:
/////////////////////////// flashLight///////////////////////////////////////

public void startLight(boolean flag){
if(flag){
openLight();
}else{
offLight();
}
}

public void openLight(){
if (camera != null) {
parameter = camera.getParameters();
parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameter);
camera.startPreview();
}
}

public void offLight(){
if (camera != null) {
parameter = camera.getParameters();
parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(parameter);
}
}

public void closeCarema(){
if(camera != null){
camera.release();
camera = null;
}
}

2 第二部:你可以参考:
private Boolean FLASH_LIGHT_FLAG = false;
private static final int CAMERA_FLAG_CLOSE = 0;private static final int CAMERA_FLAG_OPEN = 1;private static final int CAMERA_FLAG_INIT_CAMERA = 2;

protected Handler mHandler = new Handler(){
    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @Override    public void handleMessage(Message msg) {
        super.handleMessage(msg);        if(msg.what == CAMERA_FLAG_OPEN){
            initCamareView();        }else if(msg.what == CAMERA_FLAG_CLOSE){
            mCameraManager.closeCarema();        }
    }
};

private void initCamareView() {
    FLASH_LIGHT_FLAG = !FLASH_LIGHT_FLAG;    mCameraManager.startLight(FLASH_LIGHT_FLAG);    if(FLASH_LIGHT_FLAG){
        mTitleBar.setRightFirstIcon(R.drawable.flash_light_press);    }else{
        mTitleBar.setRightFirstIcon(R.drawable.flash_light);    }
}



onClicklistenr

 send message:
@Overridepublic void onClickRightOne(View view) {
    super.onClickRightOne(view);    mHandler.sendEmptyMessage(CAMERA_FLAG_OPEN);}



我的建议:
既然自己的花费了好长的时间整理这个东西,那就不应该让自己未来在花费这么长的时间来整理,所以应该把自己今天的收获记录下来,这样不要在同一个坑里面 跌倒两次。 
显然,我们添加的这个东西不是只是使用一次。所以,我们应该抽取一个抽象类
顶层: CaptureActivity
二级: BaseQRCodeActivity
三级: BaseQRCodeWithFlashLightActivity
四级: 你自定的实现的类

当你需要 待FlashLight 的时候,你就extends   BaseQRCodeWithFlashLightActivity
随心所欲

这就是面向对象的好处。很多时候,我们用着面向对象的语言,写着面向过程的程序,我也是醉了!





附录:

No comments:

Post a Comment