Last active
January 11, 2018 09:45
-
-
Save oakkub/986029531b7c2934b5c5f76258beba5b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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