ver 2.0
This commit is contained in:
1 parent
e9dcb2b394
commit
e39e393b8b
11 files changed
+503
No files matched your search
@@ -34,6 +34,13 @@ dependencies {
|
|||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
|
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
|
||||||
implementation 'com.google.zxing:core:3.5.3'
|
implementation 'com.google.zxing:core:3.5.3'
|
||||||
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
|
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||||
|
implementation 'com.github.bumptech.glide:glide:4.16.0'
|
||||||
|
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||||
|
implementation 'org.tensorflow:tensorflow-lite:2.14.0'
|
||||||
|
implementation 'org.tensorflow:tensorflow-lite-gpu:2.14.0'
|
||||||
|
implementation 'org.tensorflow:tensorflow-lite-support:0.4.7'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
package com.example.upcreader;
|
package com.example.upcreader;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.content.ClipData;
|
||||||
|
import android.content.ClipboardManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -12,6 +19,7 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
import com.google.zxing.ResultPoint;
|
import com.google.zxing.ResultPoint;
|
||||||
import com.journeyapps.barcodescanner.BarcodeCallback;
|
import com.journeyapps.barcodescanner.BarcodeCallback;
|
||||||
import com.journeyapps.barcodescanner.BarcodeResult;
|
import com.journeyapps.barcodescanner.BarcodeResult;
|
||||||
@@ -24,10 +32,22 @@ public class CameraActivity extends AppCompatActivity implements BarcodeCallback
|
|||||||
|
|
||||||
private DecoratedBarcodeView barcodeView;
|
private DecoratedBarcodeView barcodeView;
|
||||||
private Button scanButton;
|
private Button scanButton;
|
||||||
|
private Button copyShareButton;
|
||||||
private TextView resultTextView;
|
private TextView resultTextView;
|
||||||
private boolean isScanning = false;
|
private boolean isScanning = false;
|
||||||
private List<String> scannedCodes = new ArrayList<>();
|
private List<String> scannedCodes = new ArrayList<>();
|
||||||
|
|
||||||
|
// For product image display
|
||||||
|
private View productImageView;
|
||||||
|
private ImageView imageViewProduct;
|
||||||
|
private TextView textViewProductName;
|
||||||
|
|
||||||
|
// For object recognition
|
||||||
|
private ObjectRecognizer objectRecognizer;
|
||||||
|
private View recognitionResultView;
|
||||||
|
private ImageView imageViewRecognitionResult;
|
||||||
|
private TextView textViewRecognitionResult;
|
||||||
|
|
||||||
private static final int PERMISSION_REQUEST_CAMERA = 1;
|
private static final int PERMISSION_REQUEST_CAMERA = 1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -37,8 +57,12 @@ public class CameraActivity extends AppCompatActivity implements BarcodeCallback
|
|||||||
|
|
||||||
barcodeView = findViewById(R.id.barcode_scanner_view);
|
barcodeView = findViewById(R.id.barcode_scanner_view);
|
||||||
scanButton = findViewById(R.id.button_scan);
|
scanButton = findViewById(R.id.button_scan);
|
||||||
|
copyShareButton = findViewById(R.id.button_copy_share);
|
||||||
resultTextView = findViewById(R.id.text_view_results);
|
resultTextView = findViewById(R.id.text_view_results);
|
||||||
|
|
||||||
|
// Initialize object recognizer
|
||||||
|
objectRecognizer = new ObjectRecognizer(this);
|
||||||
|
|
||||||
// Check for camera permission
|
// Check for camera permission
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA);
|
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CAMERA);
|
||||||
@@ -56,6 +80,78 @@ public class CameraActivity extends AppCompatActivity implements BarcodeCallback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
copyShareButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (scannedCodes.isEmpty()) {
|
||||||
|
Toast.makeText(CameraActivity.this, "No codes to copy or share", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the text to copy/share
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String code : scannedCodes) {
|
||||||
|
sb.append(code).append("\n");
|
||||||
|
}
|
||||||
|
String textToCopy = sb.toString().trim();
|
||||||
|
|
||||||
|
// Copy to clipboard
|
||||||
|
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
|
ClipData clip = ClipData.newPlainText("UPC Codes", textToCopy);
|
||||||
|
clipboard.setPrimaryClip(clip);
|
||||||
|
|
||||||
|
// Show toast notification
|
||||||
|
Toast.makeText(CameraActivity.this, "Copied to clipboard", Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
// Share via intent
|
||||||
|
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||||
|
shareIntent.setType("text/plain");
|
||||||
|
shareIntent.putExtra(Intent.EXTRA_TEXT, textToCopy);
|
||||||
|
startActivity(Intent.createChooser(shareIntent, "Share UPC Codes"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add touch listener to barcode view for object recognition
|
||||||
|
barcodeView.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
|
// Get the touch coordinates
|
||||||
|
float x = event.getX();
|
||||||
|
float y = event.getY();
|
||||||
|
|
||||||
|
// Get the bitmap from the barcode view
|
||||||
|
Bitmap bitmap = barcodeView.getBitmap();
|
||||||
|
if (bitmap != null) {
|
||||||
|
// Calculate the crop region around the touch point
|
||||||
|
int cropSize = 224; // Size expected by the model
|
||||||
|
int centerX = (int) x;
|
||||||
|
int centerY = (int) y;
|
||||||
|
|
||||||
|
// Ensure the crop region stays within bounds
|
||||||
|
int left = Math.max(0, centerX - cropSize / 2);
|
||||||
|
int top = Math.max(0, centerY - cropSize / 2);
|
||||||
|
int right = Math.min(bitmap.getWidth(), left + cropSize);
|
||||||
|
int bottom = Math.min(bitmap.getHeight(), top + cropSize);
|
||||||
|
|
||||||
|
// Create a cropped bitmap
|
||||||
|
Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, left, top, right - left, bottom - top);
|
||||||
|
|
||||||
|
// Recognize the object
|
||||||
|
String recognitionResult = objectRecognizer.recognize(croppedBitmap);
|
||||||
|
|
||||||
|
// Display the result
|
||||||
|
showRecognitionResult(croppedBitmap, recognitionResult);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
croppedBitmap.recycle();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupScanner() {
|
private void setupScanner() {
|
||||||
@@ -96,6 +192,53 @@ public class CameraActivity extends AppCompatActivity implements BarcodeCallback
|
|||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
resultTextView.setText("Found: " + code + "\nTotal: " + scannedCodes.size());
|
resultTextView.setText("Found: " + code + "\nTotal: " + scannedCodes.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Look up product information via API
|
||||||
|
UpcApiManager.getInstance().getProductByUpc(code, new UpcApiManager.UpcApiCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(UpcProduct product) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// Create and show product image view
|
||||||
|
if (productImageView == null) {
|
||||||
|
productImageView = getLayoutInflater().inflate(R.layout.layout_product_image, null);
|
||||||
|
imageViewProduct = productImageView.findViewById(R.id.image_view_product);
|
||||||
|
textViewProductName = productImageView.findViewById(R.id.text_view_product_name);
|
||||||
|
|
||||||
|
// Add to activity layout
|
||||||
|
((ViewGroup) findViewById(android.R.id.content)).addView(productImageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display product image and name
|
||||||
|
if (product.getImageUrl() != null && !product.getImageUrl().isEmpty()) {
|
||||||
|
Glide.with(CameraActivity.this)
|
||||||
|
.load(product.getImageUrl())
|
||||||
|
.placeholder(R.drawable.ic_product_placeholder)
|
||||||
|
.error(R.drawable.ic_product_error)
|
||||||
|
.into(imageViewProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (product.getName() != null && !product.getName().isEmpty()) {
|
||||||
|
textViewProductName.setText(product.getName());
|
||||||
|
} else {
|
||||||
|
textViewProductName.setText("Product Information");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide product image after 3 seconds
|
||||||
|
productImageView.postDelayed(() -> {
|
||||||
|
if (productImageView != null && productImageView.getParent() != null) {
|
||||||
|
((ViewGroup) productImageView.getParent()).removeView(productImageView);
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(String error) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
Toast.makeText(CameraActivity.this, "Could not lookup product: " + error, Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,4 +274,27 @@ public class CameraActivity extends AppCompatActivity implements BarcodeCallback
|
|||||||
super.onPause();
|
super.onPause();
|
||||||
barcodeView.pause();
|
barcodeView.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showRecognitionResult(Bitmap bitmap, String result) {
|
||||||
|
// Create and show recognition result view
|
||||||
|
if (recognitionResultView == null) {
|
||||||
|
recognitionResultView = getLayoutInflater().inflate(R.layout.layout_object_recognition_result, null);
|
||||||
|
imageViewRecognitionResult = recognitionResultView.findViewById(R.id.image_view_recognition_result);
|
||||||
|
textViewRecognitionResult = recognitionResultView.findViewById(R.id.text_view_recognition_result);
|
||||||
|
|
||||||
|
// Add to activity layout
|
||||||
|
((ViewGroup) findViewById(android.R.id.content)).addView(recognitionResultView);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the cropped bitmap and recognition result
|
||||||
|
imageViewRecognitionResult.setImageBitmap(bitmap);
|
||||||
|
textViewRecognitionResult.setText(result);
|
||||||
|
|
||||||
|
// Hide result after 3 seconds
|
||||||
|
recognitionResultView.postDelayed(() -> {
|
||||||
|
if (recognitionResultView != null && recognitionResultView.getParent() != null) {
|
||||||
|
((ViewGroup) recognitionResultView.getParent()).removeView(recognitionResultView);
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package com.example.upcreader;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.tensorflow.lite.Interpreter;
|
||||||
|
import org.tensorflow.lite.support.image.ImageProcessor;
|
||||||
|
import org.tensorflow.lite.support.image.TensorImage;
|
||||||
|
import org.tensorflow.lite.support.image.ops.ResizeOp;
|
||||||
|
import org.tensorflow.lite.support.image.ops.ResizeOp.ResizeMethod;
|
||||||
|
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer;
|
||||||
|
import org.tensorflow.lite.support.common.FileUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.MappedByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ObjectRecognizer {
|
||||||
|
private static final String MODEL_PATH = "detect.tflite";
|
||||||
|
private static final String LABELS_PATH = "labelmap.txt";
|
||||||
|
private static final int INPUT_SIZE = 224;
|
||||||
|
private static final int NUM_CLASSES = 1000; // Default for MobileNet
|
||||||
|
|
||||||
|
private Interpreter interpreter;
|
||||||
|
private List<String> labels;
|
||||||
|
|
||||||
|
public ObjectRecognizer(Context context) {
|
||||||
|
try {
|
||||||
|
// Load the model file
|
||||||
|
MappedByteBuffer model = FileUtil.loadMappedFile(context, MODEL_PATH);
|
||||||
|
interpreter = new Interpreter(model);
|
||||||
|
|
||||||
|
// Load the labels
|
||||||
|
labels = FileUtil.loadLabels(context, LABELS_PATH);
|
||||||
|
|
||||||
|
// Validate model
|
||||||
|
if (labels.size() != NUM_CLASSES) {
|
||||||
|
Log.w("ObjectRecognizer", "Label count mismatch: " + labels.size() + " vs " + NUM_CLASSES);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("ObjectRecognizer", "Error loading model or labels", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String recognize(Bitmap bitmap) {
|
||||||
|
if (interpreter == null || labels.isEmpty()) {
|
||||||
|
return "Model not loaded";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Preprocess the image
|
||||||
|
TensorImage inputImage = preprocessImage(bitmap);
|
||||||
|
|
||||||
|
// Create output buffer
|
||||||
|
float[][] output = new float[1][NUM_CLASSES];
|
||||||
|
|
||||||
|
// Run inference
|
||||||
|
interpreter.run(inputImage.getBuffer(), output);
|
||||||
|
|
||||||
|
// Get the best prediction
|
||||||
|
int bestIndex = 0;
|
||||||
|
float bestConfidence = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_CLASSES; i++) {
|
||||||
|
if (output[0][i] > bestConfidence) {
|
||||||
|
bestConfidence = output[0][i];
|
||||||
|
bestIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the label with highest confidence
|
||||||
|
if (bestConfidence > 0.1f) { // Minimum confidence threshold
|
||||||
|
return labels.get(bestIndex);
|
||||||
|
} else {
|
||||||
|
return "Unknown object";
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("ObjectRecognizer", "Error during inference", e);
|
||||||
|
return "Error recognizing object";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TensorImage preprocessImage(Bitmap bitmap) {
|
||||||
|
// Convert bitmap to TensorImage
|
||||||
|
TensorImage tensorImage = TensorImage.fromBitmap(bitmap);
|
||||||
|
|
||||||
|
// Resize image to model input size
|
||||||
|
ImageProcessor imageProcessor = new ImageProcessor.Builder()
|
||||||
|
.add(new ResizeOp(INPUT_SIZE, INPUT_SIZE, ResizeMethod.BILINEAR))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return imageProcessor.process(tensorImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if (interpreter != null) {
|
||||||
|
interpreter.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.example.upcreader;
|
||||||
|
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class UpcApiManager {
|
||||||
|
private static final String BASE_URL = "https://api.upcitemdb.com/";
|
||||||
|
private static UpcApiManager instance;
|
||||||
|
private UpcApiService apiService;
|
||||||
|
|
||||||
|
private UpcApiManager() {
|
||||||
|
Retrofit retrofit = new Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
apiService = retrofit.create(UpcApiService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized UpcApiManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new UpcApiManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getProductByUpc(String upc, UpcApiCallback callback) {
|
||||||
|
Call<UpcProduct> call = apiService.getProductByUpc(upc);
|
||||||
|
call.enqueue(new retrofit2.Callback<UpcProduct>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<UpcProduct> call, retrofit2.Response<UpcProduct> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
callback.onSuccess(response.body());
|
||||||
|
} else {
|
||||||
|
callback.onError("Failed to get product information");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<UpcProduct> call, Throwable t) {
|
||||||
|
Log.e("UpcApiManager", "API call failed", t);
|
||||||
|
callback.onError("Network error: " + t.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface UpcApiCallback {
|
||||||
|
void onSuccess(UpcProduct product);
|
||||||
|
void onError(String error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.example.upcreader;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.Path;
|
||||||
|
|
||||||
|
public interface UpcApiService {
|
||||||
|
@GET("/api/product/{upc}")
|
||||||
|
Call<UpcProduct> getProductByUpc(@Path("upc") String upc);
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.example.upcreader;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class UpcProduct {
|
||||||
|
@SerializedName("upc")
|
||||||
|
private String upc;
|
||||||
|
|
||||||
|
@SerializedName("name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@SerializedName("description")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@SerializedName("image_url")
|
||||||
|
private String imageUrl;
|
||||||
|
|
||||||
|
@SerializedName("brand")
|
||||||
|
private String brand;
|
||||||
|
|
||||||
|
@SerializedName("category")
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
// Default constructor required for Gson
|
||||||
|
public UpcProduct() {}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
public String getUpc() {
|
||||||
|
return upc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImageUrl() {
|
||||||
|
return imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrand() {
|
||||||
|
return brand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setters
|
||||||
|
public void setUpc(String upc) {
|
||||||
|
this.upc = upc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImageUrl(String imageUrl) {
|
||||||
|
this.imageUrl = imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrand(String brand) {
|
||||||
|
this.brand = brand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(String category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#333333" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:gravity="center">
|
||||||
|
<vector android:width="48dp" android:height="48dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#FF0000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5 5,-2.24 5,-5 -2.24,-5 -5,-5z"/>
|
||||||
|
<path android:fillColor="#FF0000" android:pathData="M15.5,15.5L8.5,8.5M8.5,15.5L15.5,8.5" android:strokeWidth="2" android:strokeColor="#FF0000" android:strokeLineCap="round"/>
|
||||||
|
</vector>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#333333" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:gravity="center">
|
||||||
|
<vector android:width="48dp" android:height="48dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#FFFFFF" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5 5,-2.24 5,-5 -2.24,-5 -5,-5z"/>
|
||||||
|
</vector>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
||||||
@@ -31,4 +31,13 @@
|
|||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:background="#333333" />
|
android:background="#333333" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_copy_share"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Copy/Share Scanned Codes"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:backgroundTint="#2196F3" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="#000000"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_view_recognition_result"
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:background="#333333" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_view_recognition_result"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:padding="16dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="#000000"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_view_product"
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="200dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:background="#333333" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_view_product_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:padding="16dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
Reference in new issue
Block a user