为什么带处理器的连续自动对焦相机不允许切换相机闪光灯?

时间:2015-07-31 08:46:40

标签: android android-camera

到目前为止我做了什么:

我已经实现了自定义相机来读取qr代码,需要继续对焦相机以便更好地阅读。

我的问题是当我使用处理程序时,相机闪光灯开关\关闭按钮不起作用或者打开和关闭相机闪光灯需要太多时间。当我每秒移除自动聚焦相机的代码(可运行和处理程序)时,每件事情都能正常工作。

我希望能够在相机移动时自动快速对焦,并且无需使用Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE即可快速按需开启和关闭闪光灯,因为它不适用于{{1 }}

我曾经使用过API<14,但它只启动了一次相机,这就是为什么我每天使用处理程序对焦相机。

Min SDK 项目版本为9。

我的相机活动

Camera.Parameters.FOCUS_MODE_AUTO

Camera Preview类是:

public class CameraActivityNew extends Activity implements OnClickListener,
        Camera.PreviewCallback {

    CameraPreviewNew mPreview;
    FrameLayout flCameraPreview;
    ImageButton ibFlashButton;
    Boolean isFlashOn = false;

    Camera mCamera;

    private Handler mAutoFocusHandler;
    private boolean mPreviewing = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        mAutoFocusHandler = new Handler();
        setContentView(R.layout.activity_camera);
        findSetupViews();
        mPreview = new CameraPreviewNew(getApplicationContext(), this,
                autoFocusCB);
        flCameraPreview.addView(mPreview);
    }

    private Runnable doAutoFocus = new Runnable() {
        public void run() {
            if (mCamera != null && mPreviewing) {
                mCamera.autoFocus(autoFocusCB);
            }
        }
    };
    Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
        public void onAutoFocus(boolean success, Camera camera) {
            mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
        }
    };

    @Override
    protected void onResume() {

        super.onResume();
        try {
            mCamera = Camera.open();
            if (mCamera == null) {
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        mPreview.setCamera(mCamera);
        mPreview.showSurfaceView();
        mPreviewing = true;

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCamera != null) {
            mPreview.setCamera(null);
            mCamera.cancelAutoFocus();
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mPreview.hideSurfaceView();
            mPreviewing = false;
            mCamera = null;
        }
    }

    private void findSetupViews() {

        flCameraPreview = (FrameLayout) findViewById(R.id.flCameraPreview);
        ibFlashButton = (ImageButton) findViewById(R.id.ibFlash);
        ibFlashButton.setOnClickListener(this);

        if (getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA_FLASH)) {
            ibFlashButton.setVisibility(View.VISIBLE);
            ibFlashButton.setOnClickListener(this);
        } else {
            ibFlashButton.setVisibility(View.GONE);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.ibFlash:
            if (isFlashOn) {
                mPreview.setCameraFlashLight(false);
                isFlashOn = false;
                ibFlashButton.setImageResource(R.drawable.flashoff);
            } else {
                mPreview.setCameraFlashLight(true);
                ibFlashButton.setImageResource(R.drawable.flashon);
                isFlashOn = true;
            }
            break;
        }
    }

    @Override
    public void onPreviewFrame(final byte[] data, final Camera camera) {
        // processed here qr code and works fine if camera focus
        //now removed to narrow the code for posting the question
    }

}

3 个答案:

答案 0 :(得分:5)

我发现您的自动对焦处理代码存在一些问题     分析结果

自动对焦中有循环。

<强>解释

  

a)相机预览类 mAutoFocusCallback设置为相机活动autoFocusCb

    public CameraPreviewNew(Context context,...,AutoFocusCallback autoFocusCb) 
    {
        super(context);
        mAutoFocusCallback = autoFocusCb;
        ...
    }
  

b) surfaceChanged 在加载活动时被调用一次。要求相机进行自动对焦。

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
    {
        if (mCamera != null) 
        {
            ...
            mCamera.startPreview();
            /*Auto focus camera and call <code>mAutoFocusCallback</code> after autofocus.*/
            mCamera.autoFocus(mAutoFocusCallback); 
            ...
       }
    }
  

c)完成自动对焦后,将调用mAutoFocusCallback回调。 mAutoFocusCallback->autoFocusCb->onAutoFocus()
      相机活动

    Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback()         {
        public void onAutoFocus(boolean success, Camera camera) {
            mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
        }
};
  

d)onAutoFocus在1000毫秒,1秒后再安排一次自动聚焦       相机活动

    public void onAutoFocus(boolean success, Camera camera) {
        mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
    }  
  

e)一秒钟后,消息将传递给处理程序,该处理程序将可运行的doAutoFocus请求摄像头调用为自动对焦,类似于上面的b。

    private Runnable doAutoFocus = new Runnable() {
        public void run() {
            if (mCamera != null && mPreviewing) {
                mCamera.autoFocus(autoFocusCB);
            }
        }
    };
  

f)完成autoFocus后,再次调用autoFocusCB类似于c)。并继续循环。

    Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
        public void onAutoFocus(boolean success, Camera camera) {
            mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
        }
    };

解决方案

我很困惑为什么会这样实施。循环可能是没有收听闪存启用/禁用呼叫的原因。你需要删除下面的代码并做一些有意义的事情,否则将onAutoFocus()留空。

Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
    public void onAutoFocus(boolean success, Camera camera) {
    /*REMOVE LINE BELOW*/
        mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
    }
};

每次相机移动时进行自动对焦,您需要借助手机附带的运动传感器。你可以谷歌吗

希望有所帮助。
   快乐的编码...

答案 1 :(得分:4)

您似乎不需要为您的应用使用AutoFocusCallBack,因为除了delay 1 second之外您什么也没做。

您可以做的一直关注的是使用FOCUS_MODE_CONTINUOUS_PICTURE(阅读更多here),setFocus方法位于CameraPreview,而不是{{1} }}):

Activity

并在public void setFocus() { Camera.Parameters p = mCamera.getParameters(); p.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); mCamera.setParameters(p); mCamera.startPreview(); } 中调用它:

SurfaceChanged

对于public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = mCamera.getParameters(); List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes(); // You need to choose the most appropriate previewSize for your app Camera.Size previewSize = previewSizes.get(0); parameters.setPreviewSize(previewSize.width, previewSize.height); parameters.setRotation(90); mCamera.setParameters(parameters); mCamera.startPreview(); setFlash(true); setZoomLevel(5); setFocus(); Log.w(TAG, "surfaceChanged()"); } ,您可以使用flash中的此方法:

CameraPreview

希望它对你有所帮助!如果您对我的回答有任何疑问,请随时发表评论。

答案 2 :(得分:0)

虽然这一定要迟到,但如果要切换摄像机参数,最好按以下步骤操作

mCamera.stopPreview();
mCamera.setParameters(params); // set flash on in Camera parameters
mCamera.startPreview();