Skip to content

Commit 929160c

Browse files
committed
Integrate google ml kit barcode scanner
1 parent f0fa9c7 commit 929160c

File tree

12 files changed

+116
-11
lines changed

12 files changed

+116
-11
lines changed

pretixscan/app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ dependencies {
174174
}
175175
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
176176
implementation 'com.github.apg-mobile:android-round-textview:v1.0.0'
177+
178+
implementation "com.google.android.gms:play-services-base:18.7.2"
179+
implementation "com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1"
177180
}
178181

179182
sqldelight {

pretixscan/app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@
112112
android:resource="@xml/filepaths" />
113113
</provider>
114114

115+
<meta-data
116+
android:name="com.google.mlkit.vision.DEPENDENCIES"
117+
android:value="barcode" />
118+
115119
<meta-data android:name="io.sentry.dsn" android:value="${SENTRY_DSN}" />
116120
<meta-data android:name="io.sentry.attach-screenshot" android:value="false" />
117121
<meta-data android:name="io.sentry.attach-view-hierarchy" android:value="false" />

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/AppConfig.kt

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ class AppConfig(ctx: Context) : ConfigStore {
6666
.putString(PREFS_KEY_AUTOPRINTBADGES, "once")
6767
.commit()
6868
}
69+
if (prefs.contains(LEGACY_PREFS_KEY_USE_CAMERA)) {
70+
prefs.edit()
71+
.putString(PREFS_KEY_SCAN_ENGINE, if (prefs.getBoolean(LEGACY_PREFS_KEY_USE_CAMERA, true)) "zxing" else "hardware")
72+
.remove(LEGACY_PREFS_KEY_USE_CAMERA)
73+
.commit()
74+
}
6975
}
7076

7177
override fun isDebug(): Boolean {
@@ -339,9 +345,9 @@ class AppConfig(ctx: Context) : ConfigStore {
339345
}
340346
}
341347

342-
var useCamera: Boolean
343-
get() = default_prefs.getBoolean(PREFS_KEY_USE_CAMERA, true)
344-
set(value) = default_prefs.edit().putBoolean(PREFS_KEY_USE_CAMERA, value).apply()
348+
@Deprecated("use scanEngine instead")
349+
val useCamera: Boolean
350+
get() = default_prefs.getString(PREFS_KEY_SCAN_ENGINE, "zxing") != "hardware"
345351

346352
val hideNames: Boolean
347353
get() = default_prefs.getBoolean(PREFS_KEY_HIDE_NAMES, false)
@@ -397,6 +403,10 @@ class AppConfig(ctx: Context) : ConfigStore {
397403
get() = default_prefs.getBoolean(PREFS_KEY_SYNC_ORDERS, true)
398404
set(value) = default_prefs.edit().putBoolean(PREFS_KEY_SYNC_ORDERS, value).apply()
399405

406+
var scanEngine: String
407+
get() = default_prefs.getString(PREFS_KEY_SCAN_ENGINE, "zxing") ?: "zxing"
408+
set(value) = default_prefs.edit().putString(PREFS_KEY_SCAN_ENGINE, value).apply()
409+
400410
override fun getKnownLiveEventSlugs(): Set<String> {
401411
return default_prefs.getStringSet(PREFS_KEY_KNOWN_LIVE_EVENT_SLUGS, emptySet()) as Set<String>
402412
}
@@ -435,7 +445,7 @@ class AppConfig(ctx: Context) : ConfigStore {
435445
val PREFS_KEY_SCAN_FLASH = "scan_flash"
436446
val PREFS_KEY_SYNC_ORDERS = "pref_sync_orders"
437447
val PREFS_KEY_AUTO_SWITCH = "pref_auto_switch"
438-
val PREFS_KEY_USE_CAMERA = "pref_use_camera"
448+
val LEGACY_PREFS_KEY_USE_CAMERA = "pref_use_camera"
439449
val PREFS_KEY_SCAN_OFFLINE = "pref_scan_offline"
440450
val PREFS_KEY_SCAN_OFFLINE_AUTO = "pref_auto_offline"
441451
val PREFS_KEY_SCAN_PROXY = "pref_scan_proxy"
@@ -451,6 +461,7 @@ class AppConfig(ctx: Context) : ConfigStore {
451461
val PREFS_KEY_SEARCH_DISABLE = "pref_search_disable"
452462
val PREFS_KEY_KIOSK_MODE = "pref_kiosk_mode"
453463
val PREFS_KEY_MULTI_EVENT_MODE = "multi_event_mode"
464+
val PREFS_KEY_SCAN_ENGINE = "pref_scan_engine"
454465
private const val PREFS_KEY_KNOWN_LIVE_EVENT_SLUGS = "cache_known_live_event_slugs"
455466
}
456467
}

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/ui/MainActivity.kt

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,16 @@ import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
5656
import com.fasterxml.jackson.databind.DeserializationFeature
5757
import com.fasterxml.jackson.databind.ObjectMapper
5858
import com.fasterxml.jackson.databind.module.SimpleModule
59+
import com.google.android.gms.common.moduleinstall.InstallStatusListener
60+
import com.google.android.gms.common.moduleinstall.ModuleInstall
61+
import com.google.android.gms.common.moduleinstall.ModuleInstallRequest
62+
import com.google.android.gms.common.moduleinstall.ModuleInstallStatusUpdate
63+
import com.google.android.gms.common.moduleinstall.ModuleInstallStatusUpdate.InstallState.STATE_CANCELED
64+
import com.google.android.gms.common.moduleinstall.ModuleInstallStatusUpdate.InstallState.STATE_COMPLETED
65+
import com.google.android.gms.common.moduleinstall.ModuleInstallStatusUpdate.InstallState.STATE_FAILED
5966
import com.google.android.material.dialog.MaterialAlertDialogBuilder
6067
import com.google.android.material.snackbar.Snackbar
68+
import com.google.mlkit.vision.barcode.BarcodeScanning
6169
import eu.pretix.libpretixsync.api.PretixApi
6270
import eu.pretix.libpretixsync.check.CheckException
6371
import eu.pretix.libpretixsync.check.OnlineCheckProvider
@@ -528,6 +536,66 @@ class MainActivity : AppCompatActivity(), ReloadableActivity, ScannerView.Result
528536
pendingPinAction?.let { it(pin) }
529537
}
530538
}
539+
540+
if (conf.scanEngine == "mlkit") {
541+
val moduleInstallClient = ModuleInstall.getClient(this)
542+
val barcodeModule = BarcodeScanning.getClient()
543+
moduleInstallClient.areModulesAvailable(
544+
barcodeModule
545+
)
546+
class ModuleInstallProgressListener : InstallStatusListener {
547+
override fun onInstallStatusUpdated(update: ModuleInstallStatusUpdate) {
548+
// Progress info is only set when modules are in the progress of downloading.
549+
update.progressInfo?.let {
550+
val progress = (it.bytesDownloaded * 100 / it.totalBytesToDownload).toInt()
551+
// Set the progress for the progress bar.
552+
//progressBar.setProgress(progress)
553+
}
554+
555+
if (isTerminateState(update.installState)) {
556+
moduleInstallClient.unregisterListener(this)
557+
}
558+
if (update.installState == STATE_COMPLETED) {
559+
// -> switch engine
560+
switchScanEngine()
561+
}
562+
}
563+
564+
fun isTerminateState(@ModuleInstallStatusUpdate.InstallState state: Int): Boolean {
565+
return state == STATE_CANCELED || state == STATE_COMPLETED || state == STATE_FAILED
566+
}
567+
}
568+
569+
val listener = ModuleInstallProgressListener()
570+
val moduleInstallRequest = ModuleInstallRequest.newBuilder()
571+
.addApi(barcodeModule)
572+
.setListener(listener)
573+
.build()
574+
575+
moduleInstallClient
576+
.installModules(moduleInstallRequest)
577+
.addOnSuccessListener {
578+
if (it.areModulesAlreadyInstalled()) {
579+
// Modules are already installed when the request is sent.
580+
// -> switch engine
581+
switchScanEngine()
582+
}
583+
// The install request has been sent successfully. This does not mean
584+
// the installation is completed. To monitor the install status, set an
585+
// InstallStatusListener to the ModuleInstallRequest.
586+
}
587+
.addOnFailureListener {
588+
// Handle failure…
589+
}
590+
}
591+
}
592+
593+
private fun switchScanEngine() {
594+
when(conf.scanEngine) {
595+
"zxing" -> binding.scannerView.setAnalyzer(ScannerView.Companion.ANALYZER.ZXING)
596+
"mlkit" -> binding.scannerView.setAnalyzer(ScannerView.Companion.ANALYZER.MLKIT)
597+
else -> {}
598+
}
531599
}
532600

533601
private fun eventButtonText(): String {

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/ui/Settings.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
175175
true
176176
}
177177
}
178+
179+
// FIXME: pref_scan_engine. if BuildConfig.FLAVOR_edition == "foss", don't offer mlkit (disable?)
180+
// FIXME: pref_scan_engine. check installation status of mlkit and warn for potential large download
181+
// FIXME: pref_scan_engine. if changed to mlkit, check installation status
178182
}
179183

180184
private fun asset_dialog(@RawRes htmlRes: Int, @StringRes title: Int) {

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/ui/SetupActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class SetupActivity : AppCompatActivity(), SetupCallable {
8383

8484
override fun config(useCamera: Boolean) {
8585
val conf = AppConfig(this)
86-
conf.useCamera = useCamera
86+
conf.scanEngine = if (useCamera) "zxing" else "hardware"
8787
}
8888

8989
override fun setup(url: String, token: String) {

pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/ui/WelcomeActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class WelcomeActivity : AppCompatActivity() {
5959

6060
if (defaultToScanner()) {
6161
val conf = AppConfig(this)
62-
conf.useCamera = false
62+
conf.scanEngine = "hardware"
6363
}
6464
}
6565

pretixscan/app/src/main/res/values/arrays.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@
1616
<item>once</item>
1717
<item>true</item>
1818
</string-array>
19+
<string-array name="settings_values_scan_engine">
20+
<item>zxing</item>
21+
<item>mlkit</item>
22+
<item>hardware</item>
23+
</string-array>
1924
</resources>

pretixscan/app/src/main/res/values/strings.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
<string name="preference_badgeprint_enable">Enable badge printing</string>
136136
<string name="preference_autobadgeprint_enable">Print badges automatically</string>
137137
<string name="preference_badgeprint_install_pretixprint">Printing badges requires the separate pretixPRINT app. Do you want to install it?</string>
138+
<string name="preference_scan_engine">Barcode scanner to use</string>
138139
<string name="already_scanned">already scanned</string>
139140
<string name="total_tickets_sold">total tickets sold</string>
140141
<string name="ticket_attention">Attention, special ticket!</string>
@@ -169,6 +170,11 @@
169170
<item>Once, if not yet printed</item>
170171
<item>Always</item>
171172
</string-array>
173+
<string-array name="settings_valuelabels_scan_engine">
174+
<item>Zebra Crossing (ZXing)</item>
175+
<item>Google ML Kit</item>
176+
<item>Hardware scanner of this device</item>
177+
</string-array>
172178
<string name="headline_please_reinstall">Please reinstall pretixSCAN</string>
173179
<string name="reinstall_text">Your previous pretixSCAN version was too old and your local data cannot be used for the current version.\n\nPlease clear the storage for the pretixSCAN app or delete and reinstall the app.</string>
174180
<string name="reinstall_open_app_settings">Open Android App Settings</string>

pretixscan/app/src/main/res/xml/app_restrictions.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
android:key="pref_sync_auto"
66
android:restrictionType="bool"
77
android:title="@string/settings_label_auto_sync" />
8+
<!-- FIXME, remove/migrate? -->
89
<restriction
910
android:defaultValue="true"
1011
android:key="pref_use_camera"

0 commit comments

Comments
 (0)