From 8f3501101b24c1dc30424b74f218299e0607a0ac Mon Sep 17 00:00:00 2001 From: Niko Strijbol Date: Wed, 25 May 2022 19:01:35 +0000 Subject: [PATCH] Add ZXing barcode library for open variant --- app/build.gradle | 1 + .../hydra/common/scanner/BarcodeScanner.java | 27 +++++--- .../be/ugent/zeus/hydra/wpi/WpiActivity.java | 8 ++- .../zeus/hydra/wpi/tap/cart/CartActivity.java | 58 +++++++++++----- app/src/main/res/layout/activity_wpi.xml | 4 +- app/src/open/AndroidManifest.xml | 12 +++- .../zeus/hydra/common/barcode/Manager.java | 37 ++++++++++ .../common/barcode/OpenBarcodeScanner.java | 68 +++++++++++++++++++ .../common/barcode/GoogleBarcodeScanner.java | 12 ++++ 9 files changed, 194 insertions(+), 33 deletions(-) create mode 100644 app/src/open/java/be/ugent/zeus/hydra/common/barcode/Manager.java create mode 100644 app/src/open/java/be/ugent/zeus/hydra/common/barcode/OpenBarcodeScanner.java diff --git a/app/build.gradle b/app/build.gradle index b0497a7f9..3606adc7a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -203,6 +203,7 @@ dependencies { // Dependencies for open version. openImplementation 'org.osmdroid:osmdroid-android:6.1.11' + openImplementation 'com.journeyapps:zxing-android-embedded:4.3.0' if (props.getProperty("hydra.debug.leaks").toBoolean()) { logger.info("Leak tracking enabled...") diff --git a/app/src/main/java/be/ugent/zeus/hydra/common/scanner/BarcodeScanner.java b/app/src/main/java/be/ugent/zeus/hydra/common/scanner/BarcodeScanner.java index f2452451e..eb276f373 100644 --- a/app/src/main/java/be/ugent/zeus/hydra/common/scanner/BarcodeScanner.java +++ b/app/src/main/java/be/ugent/zeus/hydra/common/scanner/BarcodeScanner.java @@ -25,14 +25,10 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import androidx.annotation.Nullable; -import androidx.activity.result.ActivityResultLauncher; - -import java.util.List; import java.util.function.Consumer; -import be.ugent.zeus.hydra.common.request.Result; - /** * Ask some service to scan for barcodes. * @@ -41,22 +37,33 @@ * @author Niko Strijbol */ public interface BarcodeScanner { - - String RESULT_BARCODE = "activity_result_barcode"; - String RESULT_ERROR_MESSAGE = "activity_result_error_message"; - /** * If this barcode scanner needs to launch an activity or not. */ boolean needsActivity(); - /** * Get an activity to launch, which will give the barcode * as a result. */ Intent getActivityIntent(Activity activity); + /** + * @return Get the request code to use when launching an activity. + */ + int getRequestCode(); + + /** + * Get the barcode from the activity launch from the intent from + * {@link #getActivityIntent(Activity)}. + * + * @param data The result data. + * + * @return The barcode, or null. + */ + @Nullable + String interpretActivityResult(Intent data, int resultCode); + /** * Get a barcode without activity. * diff --git a/app/src/main/java/be/ugent/zeus/hydra/wpi/WpiActivity.java b/app/src/main/java/be/ugent/zeus/hydra/wpi/WpiActivity.java index 764393373..4634de6b7 100644 --- a/app/src/main/java/be/ugent/zeus/hydra/wpi/WpiActivity.java +++ b/app/src/main/java/be/ugent/zeus/hydra/wpi/WpiActivity.java @@ -88,7 +88,7 @@ public void onPageSelected(int position) { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(ActivityWpiBinding::inflate); - setTitle(AccountManager.getUsername(this)); + setTitle(); pageAdapter = new WpiPagerAdapter(this); ViewPager2 viewPager = binding.viewPager; @@ -119,8 +119,13 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { String balance = currencyFormatter.format(user.getBalanceDecimal()); String orders = decimalFormatter.format(user.getOrders()); binding.profileDescription.setText(getString(R.string.wpi_user_description, balance, orders)); + setTitle(); })); } + + private void setTitle() { + setTitle(AccountManager.getUsername(this)); + } @Override protected void onStart() { @@ -168,6 +173,7 @@ protected void onActivityResult(int requestCode, int resultCode, @Nullable Inten if (requestCode == ACTIVITY_DO_REFRESH && resultCode == Activity.RESULT_OK) { Log.i(TAG, "onActivityResult: refreshing for result..."); combinedUserViewModel.onRefresh(); + if (pageAdapter != null) { pageAdapter.notifyDataSetChanged(); } diff --git a/app/src/main/java/be/ugent/zeus/hydra/wpi/tap/cart/CartActivity.java b/app/src/main/java/be/ugent/zeus/hydra/wpi/tap/cart/CartActivity.java index 5a99dd51c..94996246a 100644 --- a/app/src/main/java/be/ugent/zeus/hydra/wpi/tap/cart/CartActivity.java +++ b/app/src/main/java/be/ugent/zeus/hydra/wpi/tap/cart/CartActivity.java @@ -22,6 +22,7 @@ package be.ugent.zeus.hydra.wpi.tap.cart; +import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.*; @@ -79,24 +80,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { binding.scanAdd.setOnClickListener(v -> { BarcodeScanner scanner = Manager.getScanner(); - scanner.getBarcode(CartActivity.this, s -> { - if (viewModel.getLastCart() == null) { - // There is no cart yet. - Log.w(TAG, "onCreate: cart not ready yet..."); - Snackbar.make(binding.getRoot(), "Product niet gevonden.", Snackbar.LENGTH_LONG) - .show(); - return; - } - Product foundProduct = viewModel.getLastCart().getProductFor(s); - if (foundProduct == null) { - Log.w(TAG, "onCreate: barcode niet gevonden in map " + s); - Snackbar.make(binding.getRoot(), "Product niet gevonden.", Snackbar.LENGTH_LONG) - .show(); - return; - } - Cart newCart = viewModel.getLastCart().addProduct(foundProduct); - saveCart(newCart, false); - }, this::onError); + if (scanner.needsActivity()) { + Intent intent = scanner.getActivityIntent(CartActivity.this); + startActivityForResult(intent, scanner.getRequestCode()); + } else { + scanner.getBarcode(CartActivity.this, this::onBarcodeScan, this::onError); + } }); binding.manualAdd.setOnClickListener(v -> { ProductPickerDialogFragment productPicker = new ProductPickerDialogFragment(); @@ -202,6 +191,39 @@ private void onError(Throwable throwable) { .setAction(getString(R.string.action_again), v -> viewModel.onRefresh()) .show(); } + + private void onBarcodeScan(String barcode) { + if (barcode == null) { + return; + } + if (viewModel.getLastCart() == null) { + // There is no cart yet. + Log.w(TAG, "onCreate: cart not ready yet..."); + Snackbar.make(binding.getRoot(), "Product niet gevonden.", Snackbar.LENGTH_LONG) + .show(); + return; + } + Product foundProduct = viewModel.getLastCart().getProductFor(barcode); + if (foundProduct == null) { + Log.w(TAG, "onCreate: barcode niet gevonden in map " + barcode); + Snackbar.make(binding.getRoot(), "Product niet gevonden.", Snackbar.LENGTH_LONG) + .show(); + return; + } + Cart newCart = viewModel.getLastCart().addProduct(foundProduct); + saveCart(newCart, false); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (requestCode == Manager.getScanner().getRequestCode()) { + // Handle it. + String barcode = Manager.getScanner().interpretActivityResult(data, resultCode); + onBarcodeScan(barcode); + return; + } + super.onActivityResult(requestCode, resultCode, data); + } private void updateCartSummary(Cart cart) { BigDecimal totalAmount = BigDecimal.ZERO; diff --git a/app/src/main/res/layout/activity_wpi.xml b/app/src/main/res/layout/activity_wpi.xml index b5abe20ba..0d7c0f9bc 100644 --- a/app/src/main/res/layout/activity_wpi.xml +++ b/app/src/main/res/layout/activity_wpi.xml @@ -106,7 +106,7 @@ android:layout_margin="16dp" app:icon="@drawable/ic_bank_transfer" android:text="@string/wpi_start_transfer" - app:layout_behavior=".common.ui.ShrinkExtendedFabBehavior" + app:layout_behavior="be.ugent.zeus.hydra.common.ui.ShrinkExtendedFabBehavior" tools:ignore="ContentDescription" /> diff --git a/app/src/open/AndroidManifest.xml b/app/src/open/AndroidManifest.xml index 50fa40369..1e591ca25 100644 --- a/app/src/open/AndroidManifest.xml +++ b/app/src/open/AndroidManifest.xml @@ -22,9 +22,17 @@ --> - - + + + + + diff --git a/app/src/open/java/be/ugent/zeus/hydra/common/barcode/Manager.java b/app/src/open/java/be/ugent/zeus/hydra/common/barcode/Manager.java new file mode 100644 index 000000000..554cc333b --- /dev/null +++ b/app/src/open/java/be/ugent/zeus/hydra/common/barcode/Manager.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Niko Strijbol + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package be.ugent.zeus.hydra.common.barcode; + +import be.ugent.zeus.hydra.common.scanner.BarcodeScanner; + +/** + * Get a barcode scanner. + * + * @author Niko Strijbol + */ +public class Manager { + + public static BarcodeScanner getScanner() { + return new OpenBarcodeScanner(); + } +} diff --git a/app/src/open/java/be/ugent/zeus/hydra/common/barcode/OpenBarcodeScanner.java b/app/src/open/java/be/ugent/zeus/hydra/common/barcode/OpenBarcodeScanner.java new file mode 100644 index 000000000..ce9132682 --- /dev/null +++ b/app/src/open/java/be/ugent/zeus/hydra/common/barcode/OpenBarcodeScanner.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Niko Strijbol + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package be.ugent.zeus.hydra.common.barcode; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import androidx.annotation.Nullable; + +import java.util.function.Consumer; + +import be.ugent.zeus.hydra.common.scanner.BarcodeScanner; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; + +/** + * @author Niko Strijbol + */ +class OpenBarcodeScanner implements BarcodeScanner { + + @Override + public boolean needsActivity() { + return true; + } + + @Override + public Intent getActivityIntent(Activity activity) { + IntentIntegrator integrator = new IntentIntegrator(activity); + integrator.setDesiredBarcodeFormats(IntentIntegrator.PRODUCT_CODE_TYPES); + return integrator.createScanIntent(); + } + + public int getRequestCode() { + return IntentIntegrator.REQUEST_CODE; + } + + @Override + @Nullable + public String interpretActivityResult(Intent data, int resultCode) { + IntentResult result = IntentIntegrator.parseActivityResult(resultCode, data); + return result.getContents(); + } + + @Override + public void getBarcode(Context context, Consumer onSuccess, Consumer onError) { + throw new UnsupportedOperationException("This Barcode Scanner requires an activity."); + } +} diff --git a/app/src/store/java/be/ugent/zeus/hydra/common/barcode/GoogleBarcodeScanner.java b/app/src/store/java/be/ugent/zeus/hydra/common/barcode/GoogleBarcodeScanner.java index 065c75631..94a9c12de 100644 --- a/app/src/store/java/be/ugent/zeus/hydra/common/barcode/GoogleBarcodeScanner.java +++ b/app/src/store/java/be/ugent/zeus/hydra/common/barcode/GoogleBarcodeScanner.java @@ -27,6 +27,7 @@ import android.content.Intent; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -58,6 +59,17 @@ public Intent getActivityIntent(Activity activity) { throw new UnsupportedOperationException("This Barcode Scanner does not use an activity."); } + @Override + public int getRequestCode() { + throw new UnsupportedOperationException("This Barcode Scanner does not use an activity."); + } + + @Nullable + @Override + public String interpretActivityResult(Intent data, int resultCode) { + throw new UnsupportedOperationException("This Barcode Scanner does not use an activity."); + } + @Override public void getBarcode(Context context, Consumer onSuccess, Consumer onError) { GmsBarcodeScannerOptions options = new GmsBarcodeScannerOptions.Builder()