Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Barcode #85

Merged
merged 2 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ dependencies {
implementation("androidx.navigation:navigation-fragment:2.7.5")
implementation("androidx.core:core:1.12.0")
testImplementation("junit:junit:4.13.2")
implementation("com.google.mlkit:barcode-scanning:17.2.0")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.example.househomey.Item;
import com.example.househomey.MainActivity;
import com.example.househomey.R;
import com.example.househomey.scanner.BarcodeImageScanner;
import com.example.househomey.scanner.SNImageScanner;
import com.example.househomey.scanner.ScannerPickerDialog;
import com.google.android.material.datepicker.MaterialDatePicker;
Expand All @@ -43,13 +44,16 @@
*
* @author Owen Cooke
*/
public abstract class ItemFormFragment extends Fragment implements ImagePickerDialog.OnImagePickedListener, PhotoAdapter.OnButtonClickListener, SNImageScanner.OnImageScannedListener {
public abstract class ItemFormFragment extends Fragment implements ImagePickerDialog.OnImagePickedListener,
PhotoAdapter.OnButtonClickListener, SNImageScanner.OnImageScannedListener,
BarcodeImageScanner.OnBarcodeScannedListener {
protected Date dateAcquired;
private TextInputEditText dateTextView;
protected CollectionReference itemRef;
protected ArrayList<String> photoUris = new ArrayList<>();
protected PhotoAdapter photoAdapter;
private TextInputEditText sNTextView;
private TextInputEditText descriptionTextView;
private final ArrayList<String> photosToDelete = new ArrayList<>();
private ImagePickerDialog imagePickerDialog;

Expand All @@ -72,6 +76,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
// Get item collection reference from main activity
itemRef = ((MainActivity) requireActivity()).getItemRef();
sNTextView = rootView.findViewById(R.id.add_item_serial_number);
descriptionTextView = rootView.findViewById(R.id.add_item_description);
View scanButton = rootView.findViewById(R.id.add_item_scan_button);
scanButton.setOnClickListener(v -> launchScannerPicker());
return rootView;
Expand Down Expand Up @@ -265,6 +270,22 @@ public void onSNScanningComplete(String serialNumber) {
sNTextView.setText(serialNumber);
}

/**
* Sets the item description field to the decoded barcode value after scanning image
* @param description the decoded barcode value to set as description
*/
@Override
public void onBarcodeOKPressed(String description) {
descriptionTextView.setText(description);
}

/**
* Sets the item serial number field to the decoded barcode value after scanning image
* @param serialNumber the decoded barcode value to set as serial number
*/
@Override
public void onSerialNumberOKPressed(String serialNumber) {sNTextView.setText(serialNumber);}

/**
* Uploads a local image to Firebase Cloud Storage and returns its UUID.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.example.househomey.scanner;

import android.app.AlertDialog;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.mlkit.vision.barcode.BarcodeScanner;
import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
import com.google.mlkit.vision.barcode.BarcodeScanning;
import com.google.mlkit.vision.barcode.common.Barcode;
import com.google.mlkit.vision.common.InputImage;

import java.io.IOException;
import java.util.List;

/**
* A class for handling the scanning and decoding of barcodes
* and updating item information accordingly
* @author Sami
*/
public class BarcodeImageScanner extends ImageScanner{

private InputImage image;
private BarcodeScanner scanner;
private Context context;
private final OnBarcodeScannedListener listener;

/**
* Constructs a new BarcodeImageScanner
* @param context context of this scanner
* @param listener listener that handles the action when barcode is scanned
*/
public BarcodeImageScanner(Context context, OnBarcodeScannedListener listener) {
this.context = context;
this.listener = listener;

}

/**
* Scans image for barcodes using Google's MLKit API and handles information extraction
* @param imageUri Image to scan
*/
@Override
public void scanImage(String imageUri) {
try {
image = InputImage.fromFilePath(context, Uri.parse(imageUri));
} catch (IOException e) {
e.printStackTrace();
}
scanner = BarcodeScanning.getClient();
Task<List<Barcode>> result = scanner.process(image)
.addOnSuccessListener(new OnSuccessListener<List<Barcode>>() {
@Override
public void onSuccess(List<Barcode> barcodes) {
selectProductInfoFromBarcode(barcodes,context);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(context.getApplicationContext(),
("Failure in scanning barcode!"),
Toast.LENGTH_SHORT).show();
Log.e("Scanner","faied to scan");
}
});

}

/**
* Ensures that only 1 barcode was scanned and extracts the value encoded into the barcode
* Depending on the value type, lets user set it as either item description or Serial Number
* @param barcodes List of barcodes detected and scanned by the scanner
* @param context context in which the scanner is being used in the app
*/
private void selectProductInfoFromBarcode(List<Barcode> barcodes, Context context) {
if (barcodes.size() == 0) {
Toast.makeText(context.getApplicationContext(),
("No barcodes were detected. Please use a different image."),
Toast.LENGTH_LONG).show();
}
else if (barcodes.size()==1){
String productInfo = barcodes.get(0).getDisplayValue();

if (barcodes.get(0).getValueType() == 7 || barcodes.get(0).getValueType() == 5) {
new AlertDialog.Builder(context)
.setTitle("Item info from decoded barcode: ")
.setMessage(productInfo +
"\n \nDecoded value may be a serial number. Set as:")
.setPositiveButton("Description",(dialog,which)->{
listener.onBarcodeOKPressed(productInfo);
})
.setNegativeButton("Serial Number",(dialog,which)->{
listener.onSerialNumberOKPressed(productInfo);
})
.setNeutralButton("Cancel", null)
.show();
}
else {
new AlertDialog.Builder(context)
.setTitle("Item info from decoded barcode: ")
.setMessage(productInfo +
"\n \nSet info as item description?")
.setPositiveButton("YES",(dialog,which)->{
listener.onBarcodeOKPressed(productInfo);
})
.setNegativeButton("NO", null)
.show();
}

}
else {
Toast.makeText(context.getApplicationContext(),
("Multiple barcodes detected. Please choose an image with one barcode."),
Toast.LENGTH_LONG).show();
}
}

/**
* Interface to handle how the decoded value of the barcode is used after scanning
*/
public interface OnBarcodeScannedListener {
void onBarcodeOKPressed(String description);
void onSerialNumberOKPressed(String serialNumber);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

import java.io.IOException;

/**
* A class for handling the scanning of serial numbers and updating item information accordingly
* @author Lukas
*/
public class SNImageScanner extends ImageScanner {
private Context context;
private OnImageScannedListener listener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
// Set up listeners to open the camera/gallery
Button barcodeButton = rootView.findViewById(R.id.barcode_button);
Button serialNumButton = rootView.findViewById(R.id.serialNum_button);
//barcodeButton.setOnClickListener(v -> launchImageIntent(true));
barcodeButton.setOnClickListener(v -> launchBarcodeScanner());
serialNumButton.setOnClickListener(v -> launchSerialNumScanner());
imagePickerDialog = new ImagePickerDialog();
return rootView;
}

/**
* Launches a new serial num scanner and brings up image picker dialog
* to choose the image to scan
*/
private void launchSerialNumScanner() {
SNImageScanner.OnImageScannedListener listener;
Expand All @@ -56,6 +57,22 @@ private void launchSerialNumScanner() {
imagePickerDialog.show(getChildFragmentManager(), imagePickerDialog.getTag());
}

/**
* Launches a new Barcode scanner and brings up the image picker dialog
* to choose the image to scan
*/
private void launchBarcodeScanner() {
BarcodeImageScanner.OnBarcodeScannedListener listener;
Fragment parent = requireParentFragment();
if (parent instanceof BarcodeImageScanner.OnBarcodeScannedListener) {
listener = (BarcodeImageScanner.OnBarcodeScannedListener) parent;
} else {
throw new ClassCastException(parent + " must implement OnImagePickedListener");
}
scanner = new BarcodeImageScanner(getContext(), listener);
imagePickerDialog.show(getChildFragmentManager(), imagePickerDialog.getTag());
}

/**
* Scans a given image using the appropriate scanner
* @param imageUri uri of the image to scan
Expand Down
6 changes: 4 additions & 2 deletions app/src/main/res/layout/dialog_photo_choices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:text="Take photo"
android:textSize="24sp"
android:textAlignment="textStart"
android:textColor="@color/white"
app:icon="@drawable/baseline_camera_alt_24"
app:iconGravity="textStart"
app:iconSize="24dp"
app:iconSize="32dp"
app:iconTint="@color/white" />

<com.google.android.material.divider.MaterialDivider
Expand All @@ -30,12 +31,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:textSize="24sp"
android:text="Select from gallery"
android:textAlignment="textStart"
android:textColor="@color/white"
app:icon="@drawable/baseline_insert_photo_24"
app:iconGravity="textStart"
app:iconSize="24dp"
app:iconSize="32dp"
app:iconTint="@color/white" />

</LinearLayout>
8 changes: 5 additions & 3 deletions app/src/main/res/layout/dialog_scanning_choices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
android:textAlignment="textStart"
android:textColor="@color/white"
app:icon="@drawable/number_sign_icon"
android:textSize="24sp"
app:iconGravity="textStart"
app:iconSize="24dp"
app:iconSize="32dp"
app:iconTint="@color/white" />

<com.google.android.material.divider.MaterialDivider
Expand All @@ -30,12 +31,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:text="Select from gallery"
android:text="Scan Barcode"
android:textAlignment="textStart"
android:textColor="@color/white"
app:icon="@drawable/baseline_barcode_scanner_24"
app:iconGravity="textStart"
app:iconSize="24dp"
android:textSize="24sp"
app:iconSize="32dp"
app:iconTint="@color/white" />

</LinearLayout>
Loading