1
1
package nl.storegear.android.mlbarcodescanner
2
2
3
3
import android.Manifest
4
- import android.content.Context
5
- import android.content.pm.PackageManager
6
4
import android.os.Bundle
7
- import android.util.Log
8
- import android.util.Size
9
5
import androidx.appcompat.app.AppCompatActivity
10
- import androidx.camera.core.CameraSelector
11
- import androidx.camera.core.ImageAnalysis
12
- import androidx.camera.core.ImageProxy
13
- import androidx.camera.core.Preview
14
- import androidx.camera.lifecycle.ProcessCameraProvider
15
- import androidx.core.app.ActivityCompat
16
- import androidx.core.content.ContextCompat
17
- import androidx.lifecycle.ViewModelProvider
18
- import com.google.mlkit.common.MlKitException
6
+ import com.buildtoapp.mlbarcodescanner.MLBarcodeCallback
7
+ import com.buildtoapp.mlbarcodescanner.MLBarcodeScanner
19
8
import nl.storegear.android.mlbarcodescanner.databinding.ActivityMainBinding
20
- import nl.storegear.android.mlbarcodescanner.mlkit.BarcodeScannerProcessor
21
- import nl.storegear.android.mlbarcodescanner.mlkit.CameraXBarcodeCallback
22
- import nl.storegear.android.mlbarcodescanner.mlkit.CameraXViewModel
23
- import nl.storegear.android.mlbarcodescanner.mlkit.VisionImageProcessor
24
- import nl.storegear.android.mlbarcodescanner.util.MetricUtils.dpToPx
9
+ import nl.storegear.android.mlbarcodescanner.util.MetricUtils
10
+ import nl.storegear.android.mlbarcodescanner.util.PermissionUtils
25
11
26
- class MainActivity : AppCompatActivity (), CameraXBarcodeCallback {
27
- lateinit var binding: ActivityMainBinding
28
-
29
- private lateinit var cameraXViewModel: CameraXViewModel
30
- private var cameraProvider: ProcessCameraProvider ? = null
31
- private var previewUseCase: Preview ? = null
32
- private var analysisUseCase: ImageAnalysis ? = null
33
- private var imageProcessor: VisionImageProcessor ? = null
34
- private var needUpdateGraphicOverlayImageSourceInfo = false
35
- private var lensFacing = CameraSelector .LENS_FACING_BACK
36
- private lateinit var cameraSelector: CameraSelector
12
+ class MainActivity : AppCompatActivity (), MLBarcodeCallback {
13
+ private lateinit var binding: ActivityMainBinding
14
+ private lateinit var barcodeScanner: MLBarcodeScanner
37
15
38
16
override fun onCreate (savedInstanceState : Bundle ? ) {
39
17
super .onCreate(savedInstanceState)
40
18
binding = ActivityMainBinding .inflate(layoutInflater)
41
19
setContentView(binding.root)
42
20
43
- if (! allRuntimePermissionsGranted()) {
44
- getRuntimePermissions()
45
- }
46
- cameraXViewModel = ViewModelProvider (this ).get(CameraXViewModel ::class .java)
47
-
48
- cameraSelector = CameraSelector .Builder ().requireLensFacing(lensFacing).build()
49
- cameraXViewModel.processCameraProvider.observe(this ) { provider: ProcessCameraProvider ? ->
50
- cameraProvider = provider
51
- bindAllCameraUseCases()
21
+ if (! PermissionUtils .allRuntimePermissionsGranted(this , REQUIRED_RUNTIME_PERMISSIONS )) {
22
+ PermissionUtils .getRuntimePermissions(this , REQUIRED_RUNTIME_PERMISSIONS )
52
23
}
24
+ initBarcodeScanner()
53
25
}
54
26
55
- override fun onPause () {
56
- super .onPause()
57
- imageProcessor?.stop()
58
- }
59
-
60
- override fun onResume () {
61
- super .onResume()
62
- bindAllCameraUseCases()
63
- }
64
-
65
- override fun onDestroy () {
66
- imageProcessor?.stop()
67
- super .onDestroy()
27
+ private fun initBarcodeScanner () {
28
+ barcodeScanner = MLBarcodeScanner (
29
+ callback = this ,
30
+ focusBoxSize = MetricUtils .dpToPx(264 ),
31
+ graphicOverlay = binding.graphicOverlay,
32
+ previewView = binding.previewViewCameraScanning,
33
+ lifecycleOwner = this ,
34
+ context = this ,
35
+ drawOverlay = true , // show rectangle around detected barcode
36
+ drawBanner = true // show detected barcode value on top of it
37
+ )
68
38
}
69
39
70
40
override fun onNewBarcodeScanned (displayValue : String , rawValue : String ) {
71
41
// todo: you can process your barcode here
72
42
}
73
43
74
- private fun bindAllCameraUseCases () {
75
- // As required by CameraX API, unbinds all use cases before trying to re-bind any of them.
76
- cameraProvider?.unbindAll()
77
- bindPreviewUseCase()
78
- bindAnalysisUseCase()
79
- }
80
-
81
- private fun bindPreviewUseCase () {
82
- if (cameraProvider == null ) {
83
- return
84
- }
85
- cameraProvider?.unbind(previewUseCase)
86
- val builder = Preview .Builder ()
87
- previewUseCase = builder.build()
88
- previewUseCase?.setSurfaceProvider(binding.previewViewCameraScanning.surfaceProvider)
89
- cameraProvider?.bindToLifecycle(this , cameraSelector, previewUseCase)
90
- }
91
-
92
- private fun bindAnalysisUseCase () {
93
- if (cameraProvider == null ) {
94
- return
95
- }
96
- cameraProvider?.unbind(analysisUseCase)
97
- imageProcessor?.stop()
98
- imageProcessor = BarcodeScannerProcessor (this , focusBoxSize = dpToPx(264 ))
99
-
100
- val builder = ImageAnalysis .Builder ()
101
- builder.setTargetResolution(Size (768 , 1024 ))
102
- analysisUseCase = builder.build()
103
-
104
- needUpdateGraphicOverlayImageSourceInfo = true
105
-
106
- analysisUseCase?.setAnalyzer(
107
- // imageProcessor.processImageProxy will use another thread to run the detection underneath,
108
- // thus we can just runs the analyzer itself on main thread.
109
- ContextCompat .getMainExecutor(this )
110
- ) { imageProxy: ImageProxy ->
111
- if (needUpdateGraphicOverlayImageSourceInfo) {
112
- val rotationDegrees = imageProxy.imageInfo.rotationDegrees
113
- if (rotationDegrees == 0 || rotationDegrees == 180 ) {
114
- binding.graphicOverlay.setImageSourceInfo(imageProxy.width, imageProxy.height, false )
115
- } else {
116
- binding.graphicOverlay.setImageSourceInfo(imageProxy.height, imageProxy.width, false )
117
- }
118
- needUpdateGraphicOverlayImageSourceInfo = false
119
- }
120
-
121
- try {
122
- imageProcessor?.processImageProxy(imageProxy, binding.graphicOverlay)
123
- } catch (e: MlKitException ) {
124
- Log .e(" TAG" , " Failed to process image. Error: " + e.localizedMessage)
125
- }
126
- }
127
- cameraProvider?.bindToLifecycle(this , cameraSelector, analysisUseCase)
128
- }
129
-
130
-
131
- // GET PERMISSIONS //
132
- private fun allRuntimePermissionsGranted (): Boolean {
133
- for (permission in REQUIRED_RUNTIME_PERMISSIONS ) {
134
- permission.let {
135
- if (! isPermissionGranted(this , it)) {
136
- return false
137
- }
138
- }
139
- }
140
- return true
141
- }
142
-
143
- private fun getRuntimePermissions () {
144
- val permissionsToRequest = ArrayList <String >()
145
- for (permission in REQUIRED_RUNTIME_PERMISSIONS ) {
146
- permission.let {
147
- if (! isPermissionGranted(this , it)) {
148
- permissionsToRequest.add(permission)
149
- }
150
- }
151
- }
152
-
153
- if (permissionsToRequest.isNotEmpty()) {
154
- ActivityCompat .requestPermissions(this , permissionsToRequest.toTypedArray(), PERMISSION_REQUESTS )
155
- }
156
- }
157
-
158
- private fun isPermissionGranted (context : Context , permission : String ): Boolean {
159
- if (ContextCompat .checkSelfPermission(context, permission) == PackageManager .PERMISSION_GRANTED ) {
160
- Log .i(TAG , " Permission granted: $permission " )
161
- return true
162
- }
163
- Log .i(TAG , " Permission NOT granted: $permission " )
164
- return false
165
- }
166
-
167
44
companion object {
168
- private const val TAG = " MLBarcodeScanner"
169
- private const val PERMISSION_REQUESTS = 1
170
-
171
- private val REQUIRED_RUNTIME_PERMISSIONS = arrayOf(
172
- Manifest .permission.CAMERA ,
173
- Manifest .permission.WRITE_EXTERNAL_STORAGE ,
174
- Manifest .permission.READ_EXTERNAL_STORAGE
175
- )
45
+ private val REQUIRED_RUNTIME_PERMISSIONS = arrayOf(Manifest .permission.CAMERA )
176
46
}
177
47
}
0 commit comments