Skip to content

Instantly share code, notes, and snippets.

@oakkub
Last active January 11, 2018 09:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oakkub/986029531b7c2934b5c5f76258beba5b to your computer and use it in GitHub Desktop.
Save oakkub/986029531b7c2934b5c5f76258beba5b to your computer and use it in GitHub Desktop.
interface BarcodeManager {
fun startDetecting()
fun stopDetecting()
fun release()
}
sealed class ScannedResult {
data class Success(val barcode: String) : ScannedResult()
object PermissionDenied : ScannedResult()
object NotOperational : ScannedResult()
data class Error(val exception: Exception) : ScannedResult()
}
class VisionBarcodeManager(private val surfaceView: SurfaceView,
private val barcodeDetector: BarcodeDetector,
private val camera: CameraSource,
private val lifecycle: Lifecycle,
private val scannedResult: (ScannedResult) -> Unit) : LifecycleObserver, BarcodeManager {
init {
lifecycle.addObserver(this)
/**
* Stupid workaround to force surfaceView to redraw itself
* With this workaround surfaceCreated(surfaceHolder: SurfaceHolder) function will be called again
* after runtime permission is allowed
* by setting visibility to "gone" first and then after permission is allowed set it back to "visible"
*/
surfaceView.visibility = View.GONE
}
@OnLifecycleEvent(value = Lifecycle.Event.ON_START)
override fun startDetecting() {
if (!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
return
}
if (ContextCompat.checkSelfPermission(surfaceView.context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
scannedResult(ScannedResult.PermissionDenied)
return
}
if (!barcodeDetector.isOperational) {
scannedResult(ScannedResult.NotOperational)
return
}
// Workaround to force SurfaceView to redraw itself
surfaceView.visibility = View.VISIBLE
surfaceView.holder.addCallback(surfaceViewCallback)
barcodeDetector.setProcessor(barcodeDetectorProcessor)
}
@OnLifecycleEvent(value = Lifecycle.Event.ON_STOP)
override fun stopDetecting() {
surfaceView.holder.removeCallback(surfaceViewCallback)
barcodeDetector.setProcessor(null)
camera.stop()
}
@OnLifecycleEvent(value = Lifecycle.Event.ON_DESTROY)
override fun release() {
camera.release()
}
private val surfaceViewCallback = object : SurfaceHolder.Callback {
@SuppressLint("MissingPermission")
override fun surfaceCreated(surfaceHolder: SurfaceHolder) {
try {
camera.start(surfaceHolder)
} catch (e: IOException) {
scannedResult(ScannedResult.Error(e))
}
}
override fun surfaceChanged(surfaceHolder: SurfaceHolder, format: Int, width: Int, height: Int) {}
override fun surfaceDestroyed(surfaceHolder: SurfaceHolder) {}
}
private val barcodeDetectorProcessor = object : Detector.Processor<Barcode> {
override fun release() {}
override fun receiveDetections(detections: Detector.Detections<Barcode>) {
if (detections.detectedItems.size() == 0) return
surfaceView.post {
// Run on main thread
detections.detectedItems.valueAt(0).displayValue.let {
scannedResult(ScannedResult.Success(it))
}
}
}
}
}
object VisionBarcodeConstants {
fun createDefaultBarcodeDetector(context: Context): BarcodeDetector = BarcodeDetector.Builder(context)
.build()
fun createDefaultCameraSource(context: Context, barcodeDetector: BarcodeDetector): CameraSource = CameraSource.Builder(context, barcodeDetector)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setAutoFocusEnabled(true)
.setRequestedFps(15f)
.build()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment