PolyBooks/sdp_polyBooks

View on GitHub
app/src/main/java/com/github/polybooks/activities/TakeBookPictureActivity.kt

Summary

Maintainability
A
1 hr
Test Coverage
F
38%
package com.github.polybooks.activities

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.ImageProxy
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.github.polybooks.R
import com.github.polybooks.utils.CameraManip.REQUEST_CODE_PERMISSIONS
import com.github.polybooks.utils.CameraManip.REQUIRED_PERMISSIONS
import com.github.polybooks.utils.CameraManip.TAG
import com.github.polybooks.utils.CameraManip.allPermissionsGranted
import com.github.polybooks.utils.CameraManip.startCamera
import com.github.polybooks.utils.GlobalVariables.EXTRA_ISBN
import com.github.polybooks.utils.GlobalVariables.EXTRA_PICTURE_FILE
import com.github.polybooks.utils.GlobalVariables.EXTRA_SALE_PRICE
import kotlinx.android.synthetic.main.activity_take_book_picture.*
import java.io.ByteArrayOutputStream
import java.io.FileOutputStream
import java.nio.ByteBuffer
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class TakeBookPictureActivity : AppCompatActivity() {
    private var imageCapture: ImageCapture? = null

    // I think (hope) that using a single fileName is fine as here we are fine with overwriting it everytime a new picture is taken
    private val pictureFileName = "bookPictureFile"

    private lateinit var cameraExecutor: ExecutorService
    private var stringISBN: String? = null
    private var salePrice: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_take_book_picture)


        val intent = intent
        val extras = intent.extras
        if (extras != null) {
            stringISBN = extras.getString(EXTRA_ISBN)
            salePrice = extras.getString(EXTRA_SALE_PRICE)
        }

        // Request camera permissions
        if (allPermissionsGranted(baseContext)) {
            startTakeBookPictureCamera()
        } else {
            ActivityCompat.requestPermissions(
                this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }

        cameraExecutor = Executors.newSingleThreadExecutor()
    }

    private fun startTakeBookPictureCamera() {
        imageCapture = ImageCapture.Builder().build()
        startCamera(this, viewFinder, imageCapture!!)
    }

    fun takePhoto(view: View) {
        // TODO offer flash option and other quality of life upgrades

        // Get a stable reference of the modifiable image capture use case
        val imageCapture = imageCapture ?: return


        // Set up image capture listener, which is triggered after photo has
        // been taken
        imageCapture.takePicture(
            ContextCompat.getMainExecutor(this),
            object : ImageCapture.OnImageCapturedCallback() {
                override fun onError(exc: ImageCaptureException) {
                    Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
                }

                override fun onCaptureSuccess(image: ImageProxy) {
                    super.onCaptureSuccess(image)
                    val msg = "Photo capture succeeded"
                    Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                    Log.d(TAG, msg)

                    val buffer: ByteBuffer = image.planes[0].buffer
                    val bytes = ByteArray(buffer.remaining())
                    buffer.get(bytes)
                    val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size, null)
                    saveBitmap(bitmap)

                    image.close()

                    val intent = Intent(baseContext, FillSaleActivity::class.java).apply {
                        val extras = Bundle()
                        extras.putString(EXTRA_ISBN, stringISBN)
                        extras.putString(EXTRA_PICTURE_FILE, pictureFileName)
                        extras.putString(EXTRA_SALE_PRICE, salePrice)
                        putExtras(extras)
                    }
                    startActivity(intent)
                }
            })
    }

    fun saveBitmap(bitmap: Bitmap): String {
        try {
            val bytes = ByteArrayOutputStream()
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes)
            val fo: FileOutputStream = baseContext.openFileOutput(
                pictureFileName,
                Context.MODE_PRIVATE
            )
            fo.write(bytes.toByteArray())
            // remember close file output
            fo.close()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        return pictureFileName
    }


    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<String>, grantResults:
        IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted(baseContext)) {
                startTakeBookPictureCamera()
            } else {
                Toast.makeText(this,
                    "You must grant camera permissions to take a picture.",
                    Toast.LENGTH_SHORT).show()
                finish()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        cameraExecutor.shutdown()
    }


}