From daed52e0046e5170fd097a4c8047489efc77878f Mon Sep 17 00:00:00 2001 From: leca Date: Fri, 27 Sep 2024 15:58:34 +0300 Subject: [PATCH] camera --- .idea/deploymentTargetSelector.xml | 8 + app/build.gradle.kts | 1 + app/src/main/AndroidManifest.xml | 17 +- .../AbstractProductView.kt | 22 ++- .../AddProductFragment.kt | 157 ++++++++++++------ .../DBStorageController.kt | 38 ++++- .../MainActivity.kt | 35 ---- .../ProductContract.kt | 12 -- .../StorageFragment.kt | 37 ++++- .../shelfContract.kt | 7 - .../main/res/layout/add_product_fragment.xml | 10 +- app/src/main/res/values/strings.xml | 4 +- app/src/main/res/xml/file_path.xml | 18 ++ gradle/libs.versions.toml | 2 + 14 files changed, 233 insertions(+), 135 deletions(-) delete mode 100644 app/src/main/java/org/foxarmy/barcodescannerforemployees/ProductContract.kt create mode 100644 app/src/main/res/xml/file_path.xml diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef3..41aa2e6 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9fb7385..1f5c261 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { implementation(libs.androidx.constraintlayout) implementation(libs.androidx.navigation.fragment.ktx) implementation(libs.androidx.navigation.ui.ktx) + implementation(libs.firebase.crashlytics.buildtools) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 243c2f8..2ac5f2d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,11 @@ xmlns:tools="http://schemas.android.com/tools"> + + + + + + + + @@ -23,10 +38,8 @@ android:theme="@style/Theme.BarcodeScannerForEmployees"> - - \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/AbstractProductView.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/AbstractProductView.kt index db8f058..4961472 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/AbstractProductView.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/AbstractProductView.kt @@ -1,9 +1,14 @@ package org.foxarmy.barcodescannerforemployees import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.util.Log import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView +import android.widget.Toast +import java.io.File /** * TODO: document your custom view class. @@ -16,10 +21,21 @@ class AbstractProductView: LinearLayout { constructor(context: Context, productImageFile: String, productName: String, netWeight: Double, category: Int) : super(context) { -// this.layerType = -// setLayerType() this.orientation = LinearLayout.VERTICAL -// productImage.set + + val imageFile = File(File(context.filesDir, "pictures"), productImageFile) + val image: ByteArray = imageFile.readBytes() + + if (image.isEmpty()) { + Toast.makeText(context, image.size.toString(), Toast.LENGTH_LONG).show() + } + try { + Log.d("org.foxarmy.barcodescannerforemployees", "[ХУЙ]" + imageFile.absolutePath) + val bitmap: Bitmap = BitmapFactory.decodeFile(imageFile.absolutePath) + } catch (e:Exception) { + Log.d("org.foxarmy.barcodescannerforemployees", "[ХУЙ] " + e) + } +// productImage.setImageBitmap(bitmap) productNameField.setText(productName) netWeightField.setText(netWeight.toString()) diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/AddProductFragment.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/AddProductFragment.kt index cec75ec..b91c33e 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/AddProductFragment.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/AddProductFragment.kt @@ -1,24 +1,20 @@ package org.foxarmy.barcodescannerforemployees //import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions -import android.app.Activity -import android.content.Intent -import android.graphics.Bitmap +import android.os.Build import android.os.Bundle -import android.provider.MediaStore +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts +import androidx.annotation.RequiresApi +import androidx.core.content.FileProvider import androidx.fragment.app.Fragment -import com.google.mlkit.vision.barcode.common.Barcode -import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions -import com.google.mlkit.vision.codescanner.GmsBarcodeScanning +import com.google.firebase.components.BuildConfig import org.foxarmy.barcodescannerforemployees.databinding.AddProductFragmentBinding import java.io.File -import java.io.FileOutputStream -import java.nio.ByteBuffer import java.security.MessageDigest @@ -29,74 +25,126 @@ fun String.md5(): String { return digest.toHexString() } -/** - * A simple [Fragment] subclass as the default destination in the navigation. - */ - class AddProductFragment : Fragment() { private var _binding: AddProductFragmentBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - _binding = AddProductFragmentBinding.inflate(inflater, container, false) return binding.root - } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - when (requestCode) { - 200 -> { - if (resultCode == Activity.RESULT_OK && data != null) { - val picture = (data.extras?.get("data") as Bitmap) - binding.imageView.setImageBitmap(picture) - val picturesPath = context?.filesDir - val dir = File(picturesPath, "pictures") - dir.mkdirs() - val filename = picture.toString().md5() - val file = File(dir, filename) - FileOutputStream(file).use { - val b = ByteBuffer.allocate(picture.byteCount) - picture.copyPixelsToBuffer(b) - it.write(b.array()) - } - } + val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean -> + if (success) { + Log.i("QWERTYUIOP", "Done") + } else { + Log.e("QWERTYUIOP", "Xuinya") + } + } + + fun getPicture () { + val imageFile = File(requireContext().filesDir, "image.png") + val imageUri = FileProvider.getUriForFile(requireActivity(), BuildConfig.APPLICATION_ID + "." + requireActivity().localClassName + ".provider", imageFile) + takePicture.launch(imageUri) + } + + val requestPermissionLauncher = + registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted: Boolean -> + if (isGranted) { + Toast.makeText(requireContext(), "Granted", Toast.LENGTH_LONG).show() +// getFuckingPicture() + } else { + Toast.makeText(requireContext(), "I need permission in order to take a picture", Toast.LENGTH_LONG).show() } } - } - - val requestPermissionLauncher = registerForActivityResult( - ActivityResultContracts.RequestPermission() - ) { isGranted -> - if (isGranted) { - val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) - startActivityForResult(cameraIntent, 200) - } else { - Toast.makeText( - requireContext(), - "I need permission for camera in order to take a picture!", - Toast.LENGTH_LONG - ).show() - } - } + @RequiresApi(Build.VERSION_CODES.R) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.saveButton.setOnClickListener { + binding.takePictureButton.setOnClickListener { +// requestPermissionLauncher.launch(android.Manifest.permission.CAMERA) + try { + getPicture() + } catch (e:Exception) { + Log.e("QWERTYUIOP", e.message.toString()) + } + +// try { +// when{ +// ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED -> { +// getFuckingPicture() +// } else -> { +//// requestPermissionLauncher.launch(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) +//// ActivityCompat.requestPermissions(requireActivity(), arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE), 200) +// +// Log.e("QWERTYUIOP", "хуй соси губой тряси") +// } +// } +// +// } catch (e:Exception) { +// Log.e("QWERTYUIOP", e.message.toString()) +// } + } +/* + binding.saveButton.setOnClickListener { + val productName = binding.productName.text.toString() + val netWeight = binding.netWeight.text + if (picture == null) { + Toast.makeText(context, "Please, make a picture of a product!", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + if (productName == "") { + Toast.makeText(context, "Please, write a name of a product!", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + if (netWeight.toString() == "" || netWeight.toString().toDoubleOrNull() == null) { + Toast.makeText(context, "Please, write a valid net weight of a product!", Toast.LENGTH_SHORT).show() + } + + val appFiles = context?.filesDir + val picturesDir = File(appFiles, "pictures") + picturesDir.mkdirs() + val imageFilename = picture.toString().md5() + ".png" + val imageFile = File(picturesDir, imageFilename) + val stream = FileOutputStream(imageFile) + picture!!.compress(Bitmap.CompressFormat.PNG, 100, stream) + + stream.use { + val buffer = ByteBuffer.allocate(picture!!.byteCount) + picture!!.copyPixelsToBuffer(buffer) + it.write(buffer.array()) + } + + val db = DBStorageController(requireContext()).writableDatabase + + val values = ContentValues().apply { + put(ProductContract.ProductEntry.PRODUCT_NAME, productName) + put(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT, netWeight.toString()) + put(ProductContract.ProductEntry.IMAGE_FILENAME, imageFilename) + } + + db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values) } binding.takePictureButton.setOnClickListener { + requestPermissionLauncher.launch(android.Manifest.permission.CAMERA) + +// val imageUri: Uri = Uri.fromFile(File(File(context?.filesDir, "pictures"), "test.jpg")) +// val imageUri = Uri.parse("pictures/test.jpg") +// val picturesDir = File(context?.filesDir, "pictures") +// picturesDir.mkdirs() +// val uri = Uri.fromFile(File(picturesDir, "test.jpg")) +// Log.d("", uri.toString()) +// takePicture.launch(uri) } binding.scanButton.setOnClickListener { @@ -109,6 +157,8 @@ class AddProductFragment : Fragment() { scanner.startScan() .addOnSuccessListener { barcode -> binding.productName.setText(barcode.rawValue) + +// val url = URL() } .addOnFailureListener { e -> Toast.makeText( @@ -118,6 +168,7 @@ class AddProductFragment : Fragment() { ).show() } } + */ } override fun onDestroyView() { diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt index 45ca8ad..d502d02 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/DBStorageController.kt @@ -6,7 +6,7 @@ import android.database.sqlite.SQLiteOpenHelper import android.provider.BaseColumns object ProductContract { - object ProductEntry :BaseColumns { + object ProductEntry : BaseColumns { const val TABLE_NAME = "products" const val PRODUCT_NAME = "name" const val PRODUCT_NET_WEIGHT = "net_weight" @@ -14,17 +14,43 @@ object ProductContract { } } -const val SQL_CREATE_ENTRIES = +object ShelfContract { + object ShelfEntry : BaseColumns { + const val TABLE_NAME = "shelf" + const val PRODUCT_ID = "product_id" + const val EXPIRE_DATE = "expire_date" + } +} + +object CategoriesContract { + object CategoryEntry : BaseColumns { + const val TABLE_NAME = "categories" + const val CATEGORY_NAME = "category_name" + } +} + +const val SQL_CREATE_PRODUCT_TABLE = "CREATE TABLE ${ProductContract.ProductEntry.TABLE_NAME} (" + "${BaseColumns._ID} INTEGER PRIMARY KEY," + "${ProductContract.ProductEntry.PRODUCT_NAME} TEXT," + - "${ProductContract.ProductEntry.PRODUCT_NET_WEIGHT} TEXT" + + "${ProductContract.ProductEntry.PRODUCT_NET_WEIGHT} REAL," + "${ProductContract.ProductEntry.IMAGE_FILENAME} TEXT)" -class DBStorageController(context: Context) : SQLiteOpenHelper (context, DATABASE_NAME, null, DATABASE_VERSION) { +const val SQL_CREATE_SHELF_TABLE = + "CREATE TABLE ${ShelfContract.ShelfEntry.TABLE_NAME} (" + + "${ShelfContract.ShelfEntry.PRODUCT_ID} INTEGER," + + "${ShelfContract.ShelfEntry.EXPIRE_DATE} DATE)" + +const val SQL_CREATE_CATEGORIES_TABLE = + "CREATE TABLE ${CategoriesContract.CategoryEntry.TABLE_NAME} (" + + "${CategoriesContract.CategoryEntry.CATEGORY_NAME} TEXT)" + +class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { override fun onCreate(db: SQLiteDatabase) { - db.execSQL(SQL_CREATE_ENTRIES) + db.execSQL(SQL_CREATE_PRODUCT_TABLE) + db.execSQL(SQL_CREATE_SHELF_TABLE) + db.execSQL(SQL_CREATE_CATEGORIES_TABLE) } override fun onUpgrade(p0: SQLiteDatabase?, p1: Int, p2: Int) { @@ -34,6 +60,6 @@ class DBStorageController(context: Context) : SQLiteOpenHelper (context, DATABAS companion object { // If you change the database schema, you must increment the database version. const val DATABASE_VERSION = 1 - const val DATABASE_NAME = "FeedReader.db" + const val DATABASE_NAME = "database.db" } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/MainActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/MainActivity.kt index 529d6dd..ed73c27 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/MainActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/MainActivity.kt @@ -19,33 +19,6 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) val dbHelper = DBStorageController(applicationContext) -// val db = dbHelper.writableDatabase -// -// val values = ContentValues().apply { -// put(ProductContract.ProductEntry.PRODUCT_NAME, "Имя продукта") -// put(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT, "0г") -// put(ProductContract.ProductEntry.IMAGE_FILENAME, "image.png") -// } -// -// val netRowId = db?.insert(ProductContract.ProductEntry.TABLE_NAME, null, values) - -// val db2 = dbHelper.readableDatabase -// -// val projection = arrayOf(BaseColumns._ID, ProductContract.ProductEntry.PRODUCT_NAME, ProductContract.ProductEntry.PRODUCT_NET_WEIGHT, ProductContract.ProductEntry.IMAGE_FILENAME) -// -// val selection = "${ProductContract.ProductEntry.PRODUCT_NAME} = ?" -// val selectionArgs = arrayOf("Имя продукта") -// -// val cursor = db2.query( -// ProductContract.ProductEntry.TABLE_NAME, -// null, -// selection, -// selectionArgs, -// null, -// null, -// null -// ) - binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) @@ -56,24 +29,16 @@ class MainActivity : AppCompatActivity() { setupActionBarWithNavController(navController, appBarConfiguration) binding.addProductFab.setOnClickListener { view -> -// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) -// .setAction("Action", null) -// .setAnchorView(R.id.add_product_fab).show() -// Toast.makeText(applicationContext, "Test", Toast.LENGTH_SHORT).show() navController.navigate(R.id.AddProductFragment) } } override fun onCreateOptionsMenu(menu: Menu): Boolean { - // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.menu_main, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. return when (item.itemId) { R.id.action_settings -> true else -> super.onOptionsItemSelected(item) diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/ProductContract.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/ProductContract.kt deleted file mode 100644 index e840d00..0000000 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/ProductContract.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.foxarmy.barcodescannerforemployees - -import android.provider.BaseColumns - -//object ProductContract { -// object ProductEntry :BaseColumns { -// const val TABLE_NAME = "products" -// const val PRODUCT_NAME = "name" -// const val PRODUCT_NET_WEIGHT = "net_weight" -// const val IMAGE_FILENAME = "image_filename" -// } -//} \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/StorageFragment.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/StorageFragment.kt index c8f6efd..c4d33d2 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/StorageFragment.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/StorageFragment.kt @@ -1,6 +1,7 @@ package org.foxarmy.barcodescannerforemployees import android.os.Bundle +import android.provider.BaseColumns import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -29,14 +30,32 @@ class StorageFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - getView()?.findViewById(R.id.storageLayout)?.addView( - AbstractProductView( - requireContext(), - productImageFile = "test1", - productName = "test2", - netWeight = 1.1, - category = 1 - ) - ) + val db = DBStorageController(requireContext()).readableDatabase + val projection = arrayOf(BaseColumns._ID, ProductContract.ProductEntry.PRODUCT_NAME, ProductContract.ProductEntry.PRODUCT_NET_WEIGHT, ProductContract.ProductEntry.IMAGE_FILENAME) + + val selection = "${ProductContract.ProductEntry.PRODUCT_NAME} = ?" + val selectionArgs = arrayOf("test") + + val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null) + + with (cursor) { + while(moveToNext()) { + val productName = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NAME)) + val netWeight = getDouble(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT)) + val pictureFilename = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.IMAGE_FILENAME)) + + getView()?.findViewById(R.id.storageLayout)?.addView( + AbstractProductView( + requireContext(), + productImageFile = pictureFilename, + productName = productName, + netWeight = netWeight, + category = 1 + ) + ) + } + } + + } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/shelfContract.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/shelfContract.kt index dd6c0e7..307afc7 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/shelfContract.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/shelfContract.kt @@ -2,10 +2,3 @@ package org.foxarmy.barcodescannerforemployees import android.provider.BaseColumns -object ShelfContract { - object ShelfEntry : BaseColumns { - const val TABLE_NAME = "shelf" - const val PRODUCT_ID = "product_id" - const val EXPIRE_DATE = "expire_date" - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/add_product_fragment.xml b/app/src/main/res/layout/add_product_fragment.xml index 7744486..70e4c9f 100644 --- a/app/src/main/res/layout/add_product_fragment.xml +++ b/app/src/main/res/layout/add_product_fragment.xml @@ -16,7 +16,7 @@ android:layout_height="50dp" android:text="@string/scan_label" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/editTextText" + app:layout_constraintTop_toBottomOf="@+id/netWeight" android:layout_marginTop="25dp"/> @@ -44,7 +44,7 @@ android:layout_height="50dp" android:inputType="text" android:ems="10" - android:id="@+id/editTextText" + android:id="@+id/netWeight" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" @@ -55,13 +55,13 @@ android:text="@string/saveButton" android:layout_width="100dp" android:layout_height="50dp" android:id="@+id/saveButton" - app:layout_constraintTop_toBottomOf="@+id/editTextText" + app:layout_constraintTop_toBottomOf="@+id/netWeight" android:layout_marginTop="25dp" app:layout_constraintEnd_toEndOf="parent"/>