自动对焦模式在三星 S8 中不起作用

Auto Focus Modes Not Working In Samsung S8

更新 2:任何对焦模式显然都不起作用

更新 1:问题似乎出在我的三星 S8 设备上。它适用于 Nexus 5X 和小米手机

我一直在努力让 FOCUS_MODE_CONTINUOUS_PICTURE 工作,但无济于事。我已经通过 getSupportedFocusModes() 确认我的设备支持连续自动图片,但不确定为什么它不起作用。

这是我的代码,正在 startCamera() 中设置连续自动对焦:

class CaptureReceiptFragment : Fragment(), CaptureReceiptContract.View {

private val MY_PERMISSIONS_REQUEST_CAMERA = 1

private var camera: Camera? = null
private var hasCameraPermission: Boolean? = null

private lateinit var preview: CameraPreview

override var presenter: CaptureReceiptContract.Presenter? = null

private val picture = Camera.PictureCallback { data, camera ->

    val pictureStorageDir = File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), getAppName())

    presenter?.saveReceipt(pictureStorageDir, data)


}

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    val root = inflater!!.inflate(R.layout.capturereceipt_frag, container, false)

    return root
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    hasCameraPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED

    if (hasCameraPermission!!) {
        showCameraErrorMsg()
    } else {
        capturereceipt_button_capturereceipt.setOnClickListener {
            captureReceipt()
        }
        startCameraOnCreate()
    }
}

override fun onResume() {
    super.onResume()
    presenter?.start()
    if (hasCameraPermission!!) {
        showCameraErrorMsg()
    } else {
        startCamera()
        setCameraRotation()
    }
}

override fun onPause() {
    super.onPause()
    camera?.release()
    camera = null
}

override fun gotoReceiptList() {
    //TODO
}

override fun goBack() {
    //TODO
}

private fun startCameraOnCreate() {
    preview = CameraPreview(context)
    capturereceipt_framelayout_viewfinder.addView(preview)
    startCamera()
}

private fun startCamera() {
    if (camera == null) {
        camera = Camera.open()
        if (camera == null) {
            showCameraErrorMsg()
        } else {
            val params: Camera.Parameters? = camera!!.parameters
            if (params!!.getSupportedFocusModes()
                    .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                params.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
            }
            camera?.parameters = params
            preview.camera = camera
            capturereceipt_textview_cameraerrormsg.visibility = View.GONE
            capturereceipt_framelayout_viewfinder.visibility = View.VISIBLE
        }
    }
}

private fun showCameraErrorMsg() {
    capturereceipt_textview_cameraerrormsg.visibility = View.VISIBLE
    capturereceipt_framelayout_viewfinder.visibility = View.GONE
}

override fun captureReceipt() {
    camera?.takePicture(null, null, picture)
}

private fun getOutputPictureFile(): File? {
    val appName = getAppName()

    val pictureStorageDir = File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), appName)

    if (!pictureStorageDir.exists()) {
        pictureStorageDir.mkdirs()
    }

    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    return File(pictureStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg")
}

private fun getAppName(): String {
    val appInfo = context.getApplicationInfo()
    val stringId = appInfo.labelRes
    if (stringId == 0) {
        return appInfo.nonLocalizedLabel.toString()
    } else {
        return this.getString(stringId)
    }
}

fun setCameraDisplayOrientation() {
    val info = Camera.CameraInfo()
    Camera.getCameraInfo(CAMERA_FACING_BACK, info)
    val rotation = activity.windowManager.defaultDisplay.rotation
    var degrees = 0
    when (rotation) {
        Surface.ROTATION_0 -> degrees = 0
        Surface.ROTATION_90 -> degrees = 90
        Surface.ROTATION_180 -> degrees = 180
        Surface.ROTATION_270 -> degrees = 270
    }
    var result: Int
    if (info.facing == CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360
        result = (360 - result) % 360  // compensate the mirror
    } else {  // back-facing
        result = (info.orientation - degrees + 360) % 360
    }
    camera?.setDisplayOrientation(result);
}

fun setCameraRotation() {
    val info: Camera.CameraInfo = Camera.CameraInfo()
    Camera.getCameraInfo(CAMERA_FACING_BACK, info)
    val rotation = activity.windowManager.defaultDisplay.rotation
    var degrees = 0
    when(rotation) {
        Surface.ROTATION_0 -> degrees = 0
        Surface.ROTATION_90 -> degrees = 90
        Surface.ROTATION_180 -> degrees = 180
        Surface.ROTATION_270 -> degrees = 270
    }
    val rotate = (info.orientation - degrees + 360) % 360
    camera?.setDisplayOrientation(rotate)
    val params: Camera.Parameters = camera!!.parameters
    params.setRotation(rotate)
    camera?.parameters = params
}

companion object {
    @JvmStatic fun newInstance(): CaptureReceiptFragment {
        return CaptureReceiptFragment()
    }
}

}

如有任何帮助,我们将不胜感激。谢谢!

我终于想通了 -- 三星 S8 的自动对焦模式参数似乎应该设置不同。

这是我尝试失败的方法:

  1. 设置任何自动对焦模式(AUTO、CONTINUOUS_PICTURE、INFINITY) 开始预览之前
  2. 计划 camera.autoFocus() 至 运行 每 camera.open
  3. 后立即一秒

以下是我尝试过的方法:

  1. 持续关注或camera.autoFocus()点击按钮
  2. camera.open() 之后将连续焦点设置延迟 1 秒 <-- 这就是解决我的问题的方法

我的 #2 代码:

private val autoFocusExecutor = ScheduledThreadPoolExecutor(1)

fun startCamera() {
    if (camera == null) {
        camera = Camera.open()
        if (camera == null) {
            showCameraErrorMsg()
        } else {
            preview.camera = camera
            capturereceipt_textview_cameraerrormsg.visibility = View.GONE
            capturereceipt_framelayout_viewfinder.visibility = View.VISIBLE

            autoFocusExecutor.schedule(Sc{
                val params: Camera.Parameters = camera!!.parameters
                if (params.getSupportedFocusModes()
                        .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                    //TODO: Auto focus not working
                    params.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE
                }
                camera?.parameters = params
            }, 1000, TimeUnit.MILLISECONDS)
        }
    }
}

我在使用 Samsung J7 Prime 时遇到了同样的问题,代码可以正常工作,但相机焦点是固定的。使用处理程序设置焦点模式为我解决了这个问题:

Handler().post { 
    camera.apply {
        val params = camera.parameters

        if (params.supportedFocusModes?.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) == true) {
            params.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE
            camera.parameters = params
        }
    }
}