diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/WebSocketClient.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/WebSocketClient.kt index 74ca600..8a7c42a 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/WebSocketClient.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/WebSocketClient.kt @@ -2,8 +2,10 @@ package org.foxarmy.barcodescannerforemployees import android.content.Context import android.os.Build +import android.util.Log import androidx.annotation.RequiresApi import okhttp3.* +import org.foxarmy.barcodescannerforemployees.activities.MainActivity import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO import org.foxarmy.barcodescannerforemployees.database.CategoryDAO import org.foxarmy.barcodescannerforemployees.database.DBStorageController @@ -12,18 +14,30 @@ import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import org.foxarmy.barcodescannerforemployees.dataclasses.Category import org.foxarmy.barcodescannerforemployees.dataclasses.Product import org.json.JSONObject +import java.io.File +import java.util.concurrent.TimeUnit class WebSocketClient(private val context: Context, private val server: String) { private lateinit var webSocket: WebSocket fun connect(token: String, currentGroup: String) { - val client = OkHttpClient() - val request = Request.Builder().url("ws://$server:8282").build() + val client = OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .readTimeout(1, TimeUnit.MINUTES) + .writeTimeout(10, TimeUnit.SECONDS) + .callTimeout(1, TimeUnit.MINUTES) + .build() + + val request = Request.Builder() + .url("wss://$server") + .build() + client.newWebSocket(request, object : WebSocketListener() { override fun onOpen(webSocket: WebSocket, response: Response) { this@WebSocketClient.webSocket = webSocket - sendMessage("\"token\":\"$token\",\"currentGroup\":\"$currentGroup\"") + sendMessage("{\"token\":\"$token\",\"currentGroup\":\"$currentGroup\"}") + keepAlive() } @RequiresApi(Build.VERSION_CODES.O) @@ -45,6 +59,19 @@ class WebSocketClient(private val context: Context, private val server: String) when (item) { "abstractproduct" -> { val newAbstractProduct = AbstractProduct.createFromJSON(data) + + val net = Net() + net.server = server + net.token = token + + val picturesDir = File(context.filesDir, "pictures") + picturesDir.mkdirs() + + val pictureFile = + File(picturesDir, "${data["image_filename"]}.png") + val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${data["local_id"]}" + net.downloadImage(url, pictureFile) + abstractProductDAO.addAbstractProduct(newAbstractProduct) } @@ -64,6 +91,19 @@ class WebSocketClient(private val context: Context, private val server: String) when (item) { "abstractproduct" -> { val updatedAbstractProduct = AbstractProduct.createFromJSON(data) + + val net = Net() + net.server = server + net.token = token + + val picturesDir = File(context.filesDir, "pictures") + picturesDir.mkdirs() + + val pictureFile = + File(picturesDir, "${data["image_filename"]}.png") + val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${data["local_id"]}" + net.downloadImage(url, pictureFile) + abstractProductDAO.updateAbstractProduct(updatedAbstractProduct) } "product" -> { @@ -78,31 +118,44 @@ class WebSocketClient(private val context: Context, private val server: String) } "delete" -> { - val id = data["local_id"] as Int + val id = data["local_id"] as String when(item) { "abstractproduct" -> { - abstractProductDAO.eraseAbstractProduct(id, context) + abstractProductDAO.eraseAbstractProduct(id.toInt(), context) } "product" -> { - productDAO.eraseProduct(id) + productDAO.eraseProduct(id.toInt()) } "category" -> { - categoryDAO.eraseCategory(id, context) + categoryDAO.eraseCategory(id.toInt(), context) } } } } + + (context as MainActivity).updateAll() } override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { + Log.d("QWERTYUIOP", "Closing ws. Reason: $reason") } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + Log.d("QWERTYUIOP","Connection failed: ${t.message}") } }) } + private fun keepAlive() { + Thread { + while (true) { + Thread.sleep(30000) + webSocket.send("keepalive") + } + }.start() + } + fun sendMessage(message: String) { webSocket.send(message) } 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 8c6d1dd..17d6ee0 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt @@ -73,7 +73,7 @@ class AddAbstractProductActivity : AppCompatActivity() { EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) - val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!) + val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!) DAO = AbstractProductDAO(dbHelper) picturesPath = File(filesDir, "pictures") @@ -109,24 +109,24 @@ class AddAbstractProductActivity : AppCompatActivity() { action = extras!!.get("action") as String when (action) { "update" -> { - abstractProduct = extras.get("abstractProduct") as AbstractProduct? + abstractProduct = extras.get("abstractProduct") as AbstractProduct } "new_from_barcode" -> { - abstractProduct = extras.get("abstractProduct") as AbstractProduct? + abstractProduct = extras.get("abstractProduct") as AbstractProduct barcode = abstractProduct!!.barcode performRequest(abstractProduct!!.barcode) } } - if (abstractProduct != null) { + if (abstractProduct != null && action == "update") { val imageThumbnailUri = getImageUri(this, File(thumbnailsDir, "${abstractProduct!!.imageHash}.webp")) - pictureFile = File(picturesPath, "${abstractProduct!!.imageHash}.png]") + pictureFile = File(picturesPath, "${abstractProduct!!.imageHash}.png") imageView.setImageURI(imageThumbnailUri) barcodeText.setText(abstractProduct!!.barcode) productNameText.text = abstractProduct!!.name netWeightText.text = abstractProduct!!.netWeight.toString() - categorySpinner.setSelection(abstractProduct!!.category) + categorySpinner.setSelection(abstractProduct!!.category - 1) unitTypeSpinner.setSelection(abstractProduct!!.unit) } @@ -149,6 +149,7 @@ class AddAbstractProductActivity : AppCompatActivity() { } if (netWeight.toString() == "" || netWeight.toString().toDoubleOrNull() == null) { Toast.makeText(this, getString(R.string.product_net_weight_request), Toast.LENGTH_SHORT).show() + return@setOnClickListener } val net = Net() @@ -157,7 +158,7 @@ class AddAbstractProductActivity : AppCompatActivity() { net.server = sharedPreferences.getString("server", "")!! net.language = sharedPreferences.getString("language", "en-US")!! - val currentGroup = sharedPreferences.getString("currentGroup", "offline")!! + val currentGroup: Int = if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") 0 else sharedPreferences.getString("currentGroup", "")!!.toInt() lateinit var response: Response @@ -174,10 +175,10 @@ class AddAbstractProductActivity : AppCompatActivity() { if (action == "update") { DAO.updateAbstractProduct(abstractProduct!!) - response = net.updateAbstractProduct(currentGroup.toInt(), abstractProduct!!, pictureFile) + response = net.updateAbstractProduct(currentGroup, abstractProduct!!, pictureFile) } else if (action == "new" || action == "new_from_barcode") { abstractProduct!!.id = DAO.addAbstractProduct(abstractProduct!!).toInt() - response = net.uploadAbstractProduct(currentGroup.toInt(), abstractProduct!!, pictureFile); + response = net.uploadAbstractProduct(currentGroup, abstractProduct!!, pictureFile); } Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show() @@ -198,7 +199,6 @@ class AddAbstractProductActivity : AppCompatActivity() { barcodeText.setText(this.barcode) val net = Net(); val result = net.requestProductFromOnlineDB(barcode) - Log.d("QWERTYUIOP", "Result of request: $result") var abstractProduct: AbstractProduct @@ -272,18 +272,11 @@ class AddAbstractProductActivity : AppCompatActivity() { if (success) { //Move picture to a proper directory according to its calculated hash val tempfile = File(filesDir, "image.png") - val imageHash = calculateMd5Hash(tempfile) -// val imageContent = tempfile.inputStream().readBytes() -// val imageHash = imageContent.toString(Charsets.UTF_8).md5() - pictureFile = File(picturesPath, "$imageHash.png") - Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING) - tempfile.delete() - - val imageContent = pictureFile.inputStream().readBytes() + val imageContent = tempfile.inputStream().readBytes() var img = BitmapFactory.decodeByteArray(imageContent, 0, imageContent.size) - val exif = ExifInterface(pictureFile.absoluteFile.toString()) + val exif = ExifInterface(tempfile.absoluteFile.toString()) val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) val matrix = Matrix() @@ -298,9 +291,15 @@ class AddAbstractProductActivity : AppCompatActivity() { rotated.compress( Bitmap.CompressFormat.WEBP_LOSSY, 100 * (15 / (16 - compressionFactor)), - FileOutputStream(pictureFile) + FileOutputStream(tempfile) ) + val imageHash = calculateMd5Hash(tempfile) + + pictureFile = File(picturesPath, "$imageHash.png") + Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING) + tempfile.delete() + generateThumbnailForImage(this, imageHash) imageView.setImageURI(getImageUri(this, pictureFile)) diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt index 185c69c..9642a48 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddCategoryActivity.kt @@ -48,7 +48,7 @@ class AddCategoryActivity : Activity() { net.server = sharedPreferences.getString("server", "")!! net.language = sharedPreferences.getString("language", "")!! - val currentGroup = sharedPreferences.getString("currentGroup", "offline")!!.toInt() + val currentGroup: Int = if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") 0 else sharedPreferences.getString("currentGroup", "")!!.toInt() findViewById