diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 764c87e..4e8ec5c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -34,7 +34,6 @@ android { viewBinding = true } } -var cameraxVersion = "1.0.1" dependencies { implementation(libs.androidx.core.ktx) @@ -49,7 +48,9 @@ dependencies { implementation(libs.androidx.legacy.support.v4) implementation(libs.androidx.fragment) testImplementation(libs.junit) + implementation(libs.volley) androidTestImplementation(libs.androidx.junit) + implementation (libs.play.services.code.scanner) androidTestImplementation(libs.androidx.espresso.core) // implementation("com.google.android.material:1.2.0") @@ -58,8 +59,8 @@ dependencies { implementation (libs.barcode.scanning) // CameraX library - implementation ("androidx.camera:camera-camera2:$cameraxVersion") - implementation ("androidx.camera:camera-lifecycle:$cameraxVersion") + implementation (libs.androidx.camera.camera2) + implementation (libs.androidx.camera.lifecycle) implementation (libs.androidx.camera.view) - implementation ("com.google.android.gms:play-services-code-scanner:16.1.0") + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1dc263f..d0e1812 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ + () val projection = arrayOf( BaseColumns._ID, + AbstractProductContract.AbstractProductEntry.BARCODE, AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, @@ -114,11 +117,12 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE with(cursor) { while (moveToNext()) { val abstractProductId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) + val abstractProductBarcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) val abstractProductName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) val abstractProductNetWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) val abstractProductImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) - val abstractProduct = AbstractProduct(abstractProductId, abstractProductName, abstractProductNetWeight, abstractProductImageHash, category = id) + val abstractProduct = AbstractProduct(abstractProductId, abstractProductBarcode, abstractProductName, abstractProductNetWeight, abstractProductImageHash, category = id) result.add(abstractProduct) } diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Parser.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Parser.kt index 741d48c..50492f9 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Parser.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Parser.kt @@ -2,46 +2,57 @@ package org.foxarmy.barcodescannerforemployees import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct -class Parser constructor(payloadStartRegex: String, payloadEndRegex: String, payloadRegex: String){ - val payloadStartRegex: String = payloadStartRegex - val payloadEndRegex: String = payloadEndRegex - val payloadRegex: String = payloadRegex +class Parser constructor() { + fun parse(text: String): AbstractProduct { + var text = text - fun parse(text: String): MutableList { + var name = "" + var netWeight = 0.0 - val payloadStart = Regex(payloadStartRegex) - val payloadEnd = Regex(payloadEndRegex) - val payload = Regex(payloadRegex) - - val startFound = payloadStart.find(text)?.value.toString() - val payloadStartIndex = text.indexOf(startFound) - var clearText = text.removeRange( - 0, - if (payloadStartIndex < 0) 0 else payloadStartIndex - ) - - val endFound = payloadEnd.find(clearText)?.value.toString() - val payloadEndIndex = clearText.indexOf(endFound) - clearText = clearText.removeRange( - if (payloadEndIndex < 0) 0 else payloadEndIndex - 1, - clearText.length - ) - - println(clearText) - - var products = payload.findAll(clearText).toMutableList() - - for (product in products) { - println(product.value) + //Find volume in liters + val litersRegex = Regex("[0-9+],[0-9*]\\s*[лЛ]") + val foundLiters = litersRegex.find(text) + if (foundLiters != null) { + text = text.replace(foundLiters.groupValues[0], "") + netWeight = stripNetWeight(foundLiters.groupValues[0]) + } else { // not found liters. Maybe milliliters? + val millilitersRegex = Regex("[0-9+],[0-9*]\\s*((мл)|(МЛ)|(Мл))") + val foundMilliliters = millilitersRegex.find(text) + netWeight = if (foundMilliliters != null) { + text = text.replace(foundMilliliters.groupValues[0], "") + stripNetWeight(foundMilliliters.groupValues[0]) / 1000 // Found milliliters, convert to liters + } else { + 0.0 // Nothing found + } } - return mutableListOf() + val kilogramRegex = Regex("[0-9+],[0-9*]\\s*((кг)|(Кг))") + val foundKilograms = kilogramRegex.find(text) + if (foundKilograms != null) { + text = text.replace(foundKilograms.groupValues[0], "") + netWeight = stripNetWeight(foundKilograms.groupValues[0]) * 1000 + } else { // Not found kilograms, maybe we could find grams? + val gramsRegex = Regex("[0-9+],[0-9*]\\s*[гГ]") + val foundGrams = gramsRegex.find(text) + netWeight = if (foundGrams != null) { + text = text.replace(foundGrams.groupValues[0], "") + stripNetWeight(foundGrams.groupValues[0]) + } else { + 0.0 // Nothing found + } + } + + val piecesRegex = Regex("[0-9+],*[0-9*]\\s*((шт)|(Шт))") + val foundPieces = piecesRegex.find(text) + if (foundPieces != null) { + text = text.replace(foundPieces.groupValues[0], "") + netWeight = stripNetWeight(foundPieces.groupValues[0]) + } else { + netWeight = 0.0 + } + + name = text + + return AbstractProduct(0, "", name, netWeight, "", 0) } -} - -fun main () { - val p = Parser("""\""", """\<\/table\>""", """[ёЁ\u0401\u0451\u0410-\u044f\d\w\s]{16,}""") - p.parse(Requester("https://barcode-list.ru", "barcode/RU/Поиск.htm?barcode=4680036915828", ).request("4680036915828")) -// println(Requester("https://barcode-list.ru", "barcode/RU/Поиск.htm?barcode=4680036915828", ).request("4680036915828")) - } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Requester.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Requester.kt index 1693e59..b207fa5 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Requester.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Requester.kt @@ -1,28 +1,35 @@ package org.foxarmy.barcodescannerforemployees -import java.net.HttpURLConnection -import java.net.URL +import android.content.Context +import android.widget.Toast +import com.android.volley.toolbox.StringRequest +import com.android.volley.toolbox.Volley -class Requester constructor(siteName:String, endpoint: String) { - var siteName: String = siteName - var endpoint: String = endpoint +class Requester constructor(var siteName: String, var endpoint: String) { + var response = "" - fun request (productId: String): String { - val url = URL("${siteName}/$endpoint") + fun request(context: Context, barcode: String) { + val url = "${siteName}/${endpoint}" - var response: String = "" + val volleyQueue = Volley.newRequestQueue(context) + val stringRequest = object: StringRequest( + Method.POST, url, { resp -> + run { + response = resp + } + }, + { + Toast.makeText(context, "Cannot make request", Toast.LENGTH_LONG).show() + } + ) { + override fun getHeaders(): Map { + return mapOf("referer" to "$siteName/") + } - with(url.openConnection() as HttpURLConnection) { - requestMethod = "GET" // optional default is GET - - println("\nSent 'GET' request to URL : $url; Response Code : $responseCode") - - inputStream.bufferedReader().use { - it.lines().forEach { line -> - response += line //+ '\n' - } + public override fun getParams(): MutableMap { + return mutableMapOf("barcode" to barcode) } } - return response + volleyQueue.add(stringRequest) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Utils.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Utils.kt index 28bc288..e1dbee8 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Utils.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Utils.kt @@ -6,12 +6,14 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri import android.os.Build +import android.util.Log import androidx.annotation.RequiresApi import androidx.core.content.FileProvider import androidx.core.graphics.scale import com.google.firebase.components.BuildConfig import java.io.File import java.io.FileOutputStream +import java.net.URLEncoder import java.security.MessageDigest fun getImageUri(activity: Activity, imageFile: File): Uri? { @@ -39,4 +41,19 @@ fun String.md5(): String { val md = MessageDigest.getInstance("MD5") val digest = md.digest(this.toByteArray()) return digest.toHexString() -} \ No newline at end of file +} + +fun stripNetWeight (netWeight: String): Double { + return removeSubstringsFromString(netWeight, arrayOf("Л", "л", "мл", "Мл", "г", "Г", "кг", "Кг", "шт", "Шт", ",", " ", ".")).toDouble() +} + +fun removeSubstringsFromString(text: String, toRemove: Array): String { + var result = text + for (candidate in toRemove.iterator()) { + result = result.replace(candidate, "") + } + Log.d("QWERTYUIOP", result) + return result +} + +fun String.utf8(): String = URLEncoder.encode(this, "UTF-8") \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt index 9b2dacb..fee5ecc 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt @@ -18,6 +18,7 @@ import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import java.io.File import java.nio.file.Files import java.nio.file.StandardCopyOption +import kotlin.concurrent.thread class AddAbstractProductActivity : AppCompatActivity() { private lateinit var imageView: ImageView @@ -34,6 +35,7 @@ class AddAbstractProductActivity : AppCompatActivity() { private var abstractProduct: AbstractProduct? = null private lateinit var pictureFile: File private lateinit var picturesPath: File + private lateinit var barcode: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -73,7 +75,7 @@ class AddAbstractProductActivity : AppCompatActivity() { saveButton.setOnClickListener { val productName = productNameText.text.toString() val netWeight = netWeightText.text - if (!this::pictureFile.isInitialized && !pictureFile.exists()) { + if (!this::pictureFile.isInitialized || !pictureFile.exists()) { Toast.makeText(this, "Please, make a picture of a product!", Toast.LENGTH_SHORT).show() return@setOnClickListener @@ -89,6 +91,7 @@ class AddAbstractProductActivity : AppCompatActivity() { val db = DBStorageController(this).writableDatabase val values = ContentValues().apply { + put(AbstractProductContract.AbstractProductEntry.BARCODE, barcode) put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, productName) put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, netWeight.toString()) put(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, pictureFile.nameWithoutExtension) @@ -117,7 +120,21 @@ class AddAbstractProductActivity : AppCompatActivity() { val scanner = GmsBarcodeScanning.getClient(this) scanner.startScan() .addOnSuccessListener { barcode -> - productNameText.setText(barcode.rawValue) + this.barcode = barcode.rawValue.toString() + val requester = Requester("https://ean-online.ru", "match.php") + requester.request(this, barcode.rawValue!!.toString()) + var abstractProduct: AbstractProduct + + thread { + // Я сам в ахуях какой это костыль, пока хз как фиксить, потом придумаю :)) + while (requester.response == "") { } + abstractProduct = Parser().parse(requester.response) + requester.response = "" + runOnUiThread { + productNameText.text = abstractProduct.name + netWeightText.text = abstractProduct.netWeight.toString() + } + } } .addOnFailureListener { e -> Toast.makeText( diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/dataclasses/AbstractProduct.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/dataclasses/AbstractProduct.kt index 579bc89..8089189 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/dataclasses/AbstractProduct.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/dataclasses/AbstractProduct.kt @@ -5,13 +5,15 @@ import android.os.Parcelable class AbstractProduct() : Parcelable { var id: Int = 0 + var barcode: String = "" var name: String = "" var netWeight: Double = 0.0 var imageHash: String = "" var category: Int = 0 - constructor(id: Int, name: String ,netWeight: Double, imageHash: String, category: Int) : this() { + constructor(id: Int, barcode: String, name: String ,netWeight: Double, imageHash: String, category: Int) : this() { this.id = id + this.barcode = barcode this.name = name this.netWeight = netWeight this.imageHash = imageHash @@ -20,6 +22,7 @@ class AbstractProduct() : Parcelable { constructor(parcel: Parcel) : this() { id = parcel.readInt() + barcode = parcel.readString()!! name = parcel.readString()!! netWeight = parcel.readDouble() imageHash = parcel.readString()!! @@ -28,6 +31,7 @@ class AbstractProduct() : Parcelable { override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(id) + parcel.writeString(barcode) parcel.writeString(name) parcel.writeDouble(netWeight) parcel.writeString(imageHash) @@ -47,5 +51,4 @@ class AbstractProduct() : Parcelable { return arrayOfNulls(size) } } - } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt index 6b41691..16b054d 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/fragments/StorageFragment.kt @@ -76,6 +76,7 @@ class StorageFragment : Fragment() { val db = DBStorageController(requireContext()).readableDatabase val projection = arrayOf(BaseColumns._ID, + AbstractProductContract.AbstractProductEntry.BARCODE, AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, @@ -87,12 +88,13 @@ class StorageFragment : Fragment() { with (cursor) { while(moveToNext()) { val productId = getInt(getColumnIndexOrThrow(BaseColumns._ID)) + val barcode = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.BARCODE)) val productName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME)) val netWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT)) val productImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME)) val category = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.CATEGORY)) - val product = AbstractProduct(productId, productName, netWeight, productImageHash, category) + val product = AbstractProduct(productId, barcode, productName, netWeight, productImageHash, category) generateThumbnailForImage(context!!, productImageHash) diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt index 55c8cf2..435cbc2 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/views/AbstractProductView.kt @@ -11,10 +11,10 @@ import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat.startActivity -import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import org.foxarmy.barcodescannerforemployees.DBStorageController import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity +import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import org.foxarmy.barcodescannerforemployees.getImageUri import java.io.File @@ -59,8 +59,6 @@ class AbstractProductView: LinearLayout { } - - productNameField.text = abstractProduct.name netWeightField.text = abstractProduct.netWeight.toString() categoryField.text = DBStorageController(context).getCategoryNameById(DBStorageController(context).readableDatabase, abstractProduct.category) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cfe8758..6f07d12 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,8 +17,12 @@ gridlayout = "1.0.0" activity = "1.9.2" legacySupportV4 = "1.0.0" fragment = "1.8.4" +playServicesCodeScanner = "16.1.0" +volley = "1.2.1" [libraries] +androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraView" } +androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraView" } androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraView" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } barcode-scanning = { module = "com.google.mlkit:barcode-scanning", version.ref = "barcodeScanning" } @@ -35,6 +39,8 @@ androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", vers androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } androidx-legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" } androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "fragment" } +play-services-code-scanner = { module = "com.google.android.gms:play-services-code-scanner", version.ref = "playServicesCodeScanner" } +volley = { module = "com.android.volley:volley", version.ref = "volley" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }