Kotlin - com.miui.gallery.provider.GalleryOpenProvider Error - android

basically i have a fragment and in this fragment user can pick a image or use camera to take photo and i am taking the photo as uri and save to the local DB as string . And show the photo in this fragment.
This code works fine until i destroy my app in my xiaomi device. After i try to reach the uri from db and show in the fragment, app crashes. Btw this is not happening in emulator, everything is fine. I read some blogs and this could be happen in Mi devices but did not find a solution. The code;
class ProfilePageFragment : Fragment() {
private var _binding : FragmentProfilePageBinding? = null
private val binding get() = _binding!!
private lateinit var routineTasksViewModel: RoutineTasksViewModel
private var userName : String? = null
private var userProfilePhotoUri : String? = null
private lateinit var cameraPermissions : Array<String>
private lateinit var storagePermissions : Array<String>
private var imageUri : Uri? = null
private companion object {
private const val CAMERA_REQUEST_CODE = 100
private const val STORAGE_REQUEST_CODE = 101
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentProfilePageBinding.inflate(layoutInflater,container,false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
routineTasksViewModel = (activity as MainActivity).routineTasksViewModel
cameraPermissions = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
storagePermissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
getUserProfileInformations()
binding.apply {
profilePhotoIV.setOnClickListener{
showInputImageDialog()
}
}
}
//popUp menu and item click funcs
private fun showInputImageDialog() {
val popUpMenu = PopupMenu(requireContext(),binding.profilePhotoIV)
popUpMenu.menu.add(Menu.NONE,1,1, R.string.camera)
popUpMenu.menu.add(Menu.NONE,2,2, R.string.gallery)
popUpMenu.show()
popUpMenu.setOnMenuItemClickListener { menuItem ->
val id = menuItem.itemId
if (id ==1){
if (checkCameraPermission()){
pickImageCamera()
}else{
requestCameraPermission()
}
}else if(id == 2){
if (checkStoragePermission()){
pickImageGallery()
}else{
requestStoragePermission()
}
}
return#setOnMenuItemClickListener true
}
}
//two funcs check the permissions
private fun checkStoragePermission() : Boolean { //permissionGranted -> true
return ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
}
private fun checkCameraPermission() : Boolean{ //permissionGranted -> true
val cameraResult = ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
val storageResult = ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
return cameraResult && storageResult
}
//
private fun pickImageGallery(){
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
galleryActivityResultLauncher.launch(intent)
}
private fun pickImageCamera(){
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "Sample Title")
values.put(MediaStore.Images.Media.DESCRIPTION, "Sample Description")
imageUri = activity?.contentResolver?.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
cameraActivityResultLauncher.launch(intent)
}
//launcher to camera
private val cameraActivityResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result ->
if ( result.resultCode == Activity.RESULT_OK){
//image came from camera
binding.profilePhotoIV.setImageURI(imageUri)
updateProfilePhotoToDB(imageUri)
}else{
//Toast.makeText(requireContext(), R.string.permissions_required, Toast.LENGTH_SHORT).show()
}
}
//launcher to gallery
private val galleryActivityResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result ->
if ( result.resultCode == Activity.RESULT_OK){
val data = result.data
imageUri = data!!.data
binding.profilePhotoIV.setImageURI(imageUri)
updateProfilePhotoToDB(imageUri)
}else{
//Toast.makeText(requireContext(), R.string.permissions_required, Toast.LENGTH_SHORT).show()
}
}
private fun requestStoragePermission() {
ActivityCompat.requestPermissions(requireActivity(),storagePermissions, STORAGE_REQUEST_CODE)
}
private fun requestCameraPermission() {
ActivityCompat.requestPermissions(requireActivity(),cameraPermissions, CAMERA_REQUEST_CODE)
}
//when we request to take permission, according to request code pickImageCamera or pickImageGallery will work.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode){
CAMERA_REQUEST_CODE -> {
if (grantResults.isNotEmpty()){
val cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED
val storageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED
if (cameraAccepted && storageAccepted){
pickImageCamera()
}
}
}
STORAGE_REQUEST_CODE -> {
if (grantResults.isNotEmpty()){
val storageAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED
if (storageAccepted){
pickImageGallery()
}
}
}
}
}
}

Related

updating storage with the use of io fotoapparat library | Kotlin

I make a mobile application using the "io fotoapparat" library and I want to create a document with a random id and in the document in the id field, add the document id, the photo we will take was updated in the firebase store and in the previously made about the same id in the receipt collection when taking a photo
link from which I took "io fotoapparat"
EDIT
add to firestore document
binding.button.setOnClickListener {
// Inflate the layout for this fragment
val biedronka = "biedronka"
val price = "20"
val img = " "
val identificator = " "
val from = biedronka
val value = price
val image = img
val idd = identificator
val db = Firebase.firestore
val data = hashMapOf(
"from" to from,
"value" to value,
"image" to image,
"id" to idd
)
db.collection("receipts")
.add(data)
.addOnSuccessListener { documentReference ->
Log.d(SCAN_DEBUG, "DocumentSnapshot written with ID: ${documentReference.id}")
db.collection("receipts")
.document(documentReference.id)
.update("id", documentReference.id)
.addOnSuccessListener {
}
}
.addOnFailureListener { e ->
Log.w(SCAN_DEBUG, "Error adding document", e)
}
}
2 add to storage and to document (doesnt work)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CAPTURE_IMAGE && resultCode == RESULT_OK) {
val uid = profileVm.user.value?.uid!!
val imageBitmap = data?.extras?.get("data") as Bitmap
val userImage = binding.userImg
val stream = ByteArrayOutputStream()
val result = imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
val byteArray = stream.toByteArray()
if (result) profileVm.uploadUserPhoto(byteArray, "$uid.jpg")
}
}
repository to 2
fun uploadReceiptPhoto(bytes: ByteArray) {
storage.getReference("receipts")
.child("${docId}.jpg")
.putBytes(bytes)
.addOnCompleteListener{
Log.d(REPO_DEBUG, "COMPLETE UPLOAD PHOTO")
}
.addOnSuccessListener {
getReceiptPhotoDownloadUrl(it.storage)
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
private fun getReceiptPhotoDownloadUrl(storage: StorageReference) {
storage.downloadUrl
.addOnSuccessListener {
updateReceiptPhoto(it.toString())
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
private fun updateReceiptPhoto(url: String) {
cloud.collection("receipts")
.document(docId)
.update("image", url)
.addOnSuccessListener {
Log.d(REPO_DEBUG, "UPDATE USER PHOTO")
}
.addOnFailureListener {
Log.d(REPO_DEBUG, it.message.toString())
}
}
THE REST OF THE CODE (camera code "io fotoapparat" and take pictures)
class ScanFragment : Fragment(), OnReceiptsItemAdd {
private var _binding: FragmentScanBinding? = null
private val binding get() = _binding!!
private val scanVm by viewModels<ScanViewModel>()
private val SCAN_DEBUG = "SCAN_DEBUG"
private var fotoapparat: Fotoapparat? = null
private var fotoapparatState: FotoapparatState? = null
private var cameraStatus: CameraState? = null
private var flashState: FlashState? = null
private val permissions = arrayOf(Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentScanBinding.inflate(inflater, container, false)
createFotoapparat()
cameraStatus = CameraState.BACK
flashState = FlashState.OFF
fotoapparatState = FotoapparatState.OFF
binding.fabSwitchCamera.setOnClickListener {
switchCamera()
}
binding.fabFlash.setOnClickListener {
changeFlashState()
}
return binding.root
}
private fun createFotoapparat(){
val cameraView = binding.cameraView
fotoapparat = Fotoapparat(
context = requireContext(),
view = cameraView,
scaleType = ScaleType.CenterCrop,
lensPosition = back(),
logger = loggers(
logcat()
),
cameraErrorCallback = { error ->
println("Recorder errors: $error")
}
)
}
private fun changeFlashState() {
fotoapparat?.updateConfiguration(
CameraConfiguration(
flashMode = if(flashState == FlashState.TORCH) off() else torch()
)
)
flashState = if(flashState == FlashState.TORCH) FlashState.OFF
else FlashState.TORCH
}
private fun switchCamera() {
fotoapparat?.switchTo(
lensPosition = if (cameraStatus == CameraState.BACK) front() else back(),
cameraConfiguration = CameraConfiguration()
)
cameraStatus = if(cameraStatus == CameraState.BACK) CameraState.FRONT
else CameraState.BACK
}
private fun takePhoto() {
if (hasNoPermissions()) {
requestPermission()
}else{
fotoapparat
?.takePicture()
?.toBitmap()
}
}
override fun onStart() {
super.onStart()
if (hasNoPermissions()) {
requestPermission()
}else{
fotoapparat?.start()
fotoapparatState = FotoapparatState.ON
}
}
private fun hasNoPermissions(): Boolean{
return ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(requireContext(),
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
}
private fun requestPermission(){
ActivityCompat.requestPermissions(requireActivity(), permissions,0)
}
override fun onStop() {
super.onStop()
fotoapparat?.stop()
FotoapparatState.OFF
}
}
enum class CameraState{
FRONT, BACK
}
enum class FlashState{
TORCH, OFF
}
enum class FotoapparatState{
ON, OFF
}

The size of byte buffer and the shape do not match TFLite Android Kotlin

I'm new to ML, but thanks to the documentation and the community, I'm developing in this direction. Now I have stumbled upon an error and for several days I could not solve it, what is the problem and how to solve it?
I looked at the tutorials, I didn't seem to forget anything. On the XMl layout there is a picture, a text where the data comes from, their ids match
I want to open an object, take a picture of it and say what it is based on my trained model
Problem: the application crashes on line 194:
inputFeature0.loadBuffer(byteBuffer)
class SortingFragment : Fragment(), View.OnClickListener {
//ML
lateinit var bitmap: Bitmap
lateinit var appCtx: Application
lateinit var btnMLrn : Button
#SuppressLint("WrongConstant")
public fun checkandGetpermissions() {
if (PermissionChecker.checkSelfPermission(
requireActivity(),
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_DENIED
) {
requestPermissions(arrayOf(Manifest.permission.CAMERA), 100)
} else {
requireActivity().showToast("Camera permission granted")
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 100) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
requireActivity().showToast("Camera permission granted")
} else {
requireActivity().showToast("Permission Denied")
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.v(LOG_SORTING_FRAGMENT, "onCreate called")
// handling permissions
checkandGetpermissions()
appCtx = requireActivity().application
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Log.v(LOG_SORTING_FRAGMENT, "onCreateView called")
// Inflate the layout for this fragment
val rootView = inflater.inflate(R.layout.fragment_sorting, container, false)
btnMLrn = rootView.findViewById(R.id.btnMLrn)
fltNtf = rootView.findViewById(R.id.fltNtf)
fltNtf.setOnClickListener(this)
btnMLrn.setOnClickListener(View.OnClickListener {
var camera : Intent = Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(camera, 200)
})
return rootView
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == 250){
img_view.setImageURI(data?.data)
var uri : Uri?= data?.data
bitmap = MediaStore.Images.Media.getBitmap(requireActivity().contentResolver, uri)
}
else if(requestCode == 200 && resultCode == Activity.RESULT_OK){
bitmap = data?.extras?.get("data") as Bitmap
img_view.setImageBitmap(bitmap)
var resized = Bitmap.createScaledBitmap(bitmap, 224, 224, true)
val model = ModelUnquant.newInstance(requireActivity())
var tbuffer = TensorImage.fromBitmap(resized)
var byteBuffer = tbuffer.buffer
// Creates inputs for reference.
val inputFeature0 = TensorBuffer.createFixedSize(intArrayOf(1, 224, 224, 3), DataType.FLOAT32)
inputFeature0.loadBuffer(byteBuffer)
// Runs model inference and gets result.
val outputs = model?.process(inputFeature0)
val outputFeature0 = outputs?.outputFeature0AsTensorBuffer
var max = outputFeature0?.let { it1 -> getMax(it1.floatArray) }
val labels = appCtx.assets.open("labels.txt").bufferedReader().use { it.readText() }.split("\n")
sorttext.setText(labels[max!!])
// Releases model resources if no longer used.
if (model != null) {
model.close()
}
}}
fun getMax(arr: FloatArray): Int {
var ind = 0;
var min = 0.0f;
for (i in 0..10) {
if (arr[i] > min) {
min = arr[i]
ind = i;
}
}
return ind
}
} ```

Lateinit property does not initialize

In this Tab (Hence why its a fragment) the user can choose to either upload a picture or take a new one from camera.
Once he clicks the button whether to decide for an option the App closes and the Logcat gives me this error:
2021-06-01 12:49:45.680 16355-16355/com.example.nlp_expense_tracker E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.nlp_expense_tracker, PID: 16355
kotlin.UninitializedPropertyAccessException: lateinit property receiptsViewModel has not been initialized
at com.example.nlp_expense_tracker.fragments.Scanner.getReceiptsViewModel(Scanner.kt:56)
at com.example.nlp_expense_tracker.fragments.Scanner.onCreateView$lambda-2$lambda-0(Scanner.kt:84)
at com.example.nlp_expense_tracker.fragments.Scanner.lambda$swyIeEDCHOralrhRcI5ZMLiEfwM(Unknown Source:0)
at com.example.nlp_expense_tracker.fragments.-$$Lambda$Scanner$swyIeEDCHOralrhRcI5ZMLiEfwM.onClick(Unknown Source:2)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:174)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I am not quite sure where else to initiate the property.
Here is the Fragment code:
class Scanner : Fragment() {
private lateinit var imageView: ImageView
private lateinit var photoImage: Bitmap
private lateinit var mlkitImage: InputImage
private lateinit var editLocation: EditText
private lateinit var editVAT: EditText
private lateinit var editTotal: EditText
private val REQUEST_CODE_KAMERA = 42
private val REQUEST_CODE_GALLERY = 69
private val CAMERA_PERMISSION_CODE = 100
#Inject
lateinit var receiptsViewModel: ReceiptsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?):
View? {val view: View = inflater.inflate(R.layout.fragment_scan, container, false)
val btnTakePicture: Button = view.findViewById(R.id.btnTakePicture)
imageView = view.findViewById(R.id.imageView)
editLocation = view.findViewById(R.id.editLocation)
editTotal =view.findViewById(R.id.editTotal)
editVAT = view.findViewById(R.id.editVAT)
//Button Picture
btnTakePicture.setOnClickListener {
checkPermission(Manifest.permission.CAMERA,
CAMERA_PERMISSION_CODE)
val builder: AlertDialog.Builder = AlertDialog.Builder(requireActivity())
builder.setTitle("Choose a Receipt")
builder.setMessage("Either upload a Receipt or take a picture of one")
// add the buttons
builder.setPositiveButton("Use camera", DialogInterface.OnClickListener { dialog, which ->
startActivityForResult(receiptsViewModel.uploadIntent(), REQUEST_CODE_KAMERA)
})
builder.setNegativeButton("Upload from gallery", DialogInterface.OnClickListener { dialog, which ->
startActivityForResult(receiptsViewModel.cameraIntent(activity!!), REQUEST_CODE_GALLERY)
})
val dialog: AlertDialog = builder.create()
dialog.show()
}
return view
}
private fun uploadAction(data: Intent) {
try {
val resolver = requireActivity().contentResolver
val stream = resolver!!.openInputStream(data.getData()!!)
if (::photoImage.isInitialized) photoImage.recycle()
photoImage = BitmapFactory.decodeStream(stream)
mlkitImage = InputImage.fromBitmap(photoImage,0)
imageView.setImageBitmap(photoImage)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
}
private fun cameraAction() {
try {
Picasso.get().load(receiptsViewModel.imageURI).into(imageView)
mlkitImage = InputImage.fromFilePath(activity!!, receiptsViewModel.imageURI)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
}
private fun textRecognitionAction() {
var text = ""
receiptsViewModel.textDetector.process(mlkitImage)
.addOnSuccessListener {
for (block in it.textBlocks) text += block.text + "\n"
val receipts = receiptsViewModel.getReceipts(text)
editTotal.setText(receipts.total, TextView.BufferType.EDITABLE)
editLocation.setText(receipts.type, TextView.BufferType.EDITABLE)
editVAT.setText(receipts.vat, TextView.BufferType.EDITABLE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_CODE_GALLERY -> uploadAction(data!!)
REQUEST_CODE_KAMERA -> cameraAction()
}
textRecognitionAction()
}
}
private fun checkPermission(permission: String, requestCode: Int) {
if (ContextCompat.checkSelfPermission(activity!!, permission) == PackageManager.PERMISSION_DENIED) {
// Requesting the permission
ActivityCompat.requestPermissions(activity!!, arrayOf(permission), requestCode)
} else {
Toast.makeText(activity!!, "Permission already granted", Toast.LENGTH_SHORT).show()
}
}
}
class ReceiptsViewModel #Inject constructor() {
lateinit var imageURI: Uri
var textDetector = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)
fun uploadIntent(): Intent {
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_GET_CONTENT
intent.addCategory(Intent.CATEGORY_OPENABLE)
return intent
}
fun cameraIntent(context: Context): Intent {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val imageFileName = "IMG_" + timeStamp + "_"
val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val filephoto = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
)
imageURI = FileProvider.getUriForFile(context, "com.example.nlp_expense_tracker.provider", filephoto)
val pictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageURI)
return pictureIntent
}
fun getReceipts(text: String): Receipts {
val originalResult = text.findFloat()
if (originalResult.isEmpty()) return Receipts()
else {
val receipts = Receipts()
val totalF = Collections.max(originalResult)
val secondLargestF = findSecondLargestFloat(originalResult)
receipts.total = totalF.toString()
receipts.vat = if (secondLargestF == 0.0f) "0" else "%.2f".format(totalF - secondLargestF)
receipts.type = text.firstLine()
return receipts
}
}
private fun findSecondLargestFloat(input: ArrayList<Float>?): Float {
if (input == null || input.isEmpty() || input.size == 1) return 0.0f
else {
try {
val tempSet = HashSet(input)
val sortedSet = TreeSet(tempSet)
return sortedSet.elementAt(sortedSet.size - 2)
} catch (e: Exception) {
return 0.0f
}
}
}
}
Your dependency injection does not seem to be working as implied by the error here
lateinit property receiptsViewModel has not been initialized
Rest of the properties seem okay, this piece of code is not working. You may check whatever it is you are using to see why that is failing.
#Inject
lateinit var receiptsViewModel: ReceiptsViewModel

Android Kotlin: if i don't select images to save on the app, the app do not work

On my app, users can save some notes with image. But, users can not save their notes without image. Thus image is compulsory to save their data. But ı want to change it. I want to allow them to save their note without image. How can ı do this ? This is my saveclcikbutton codes;
class TakeNotesActivity : AppCompatActivity() {
var selectedPicture: Uri? = null
var selectedBitmap: Bitmap? = null
private lateinit var db: FirebaseFirestore
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_take_notes)
auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
}
fun putPictureClick(view: View) {
val popupMenu = PopupMenu(this, view)
val inflater = popupMenu.menuInflater
inflater.inflate(R.menu.secondmenu, popupMenu.menu)
popupMenu.show()
popupMenu.setOnMenuItemClickListener {
if (it.itemId == R.id.galleryImage) {
if (ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
1
)
} else {
val intentToGallery =
Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(intentToGallery, 2)
}
}
if (it.itemId == R.id.capturePhoto) {
if (ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.CAMERA),
10
)
} else {
openCamera()
}
}
if (it.itemId == R.id.cancel) {
Toast.makeText(applicationContext, "Canceled", Toast.LENGTH_LONG).show()
}
true
}
}
fun openCamera() {
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera")
selectedPicture =
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
// Camera Intent
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, selectedPicture)
startActivityForResult(cameraIntent, 20)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == 1) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
val intentToGallery =
Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(intentToGallery, 2)
}
}
if (requestCode == 10) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openCamera()
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_LONG).show()
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 2 && resultCode == Activity.RESULT_OK && data != null) {
selectedPicture = data.data
try {
if (selectedPicture != null) {
if (Build.VERSION.SDK_INT >= 28) {
val source =
ImageDecoder.createSource(this.contentResolver, selectedPicture!!)
selectedBitmap = ImageDecoder.decodeBitmap(source)
imageButton.setImageBitmap(selectedBitmap)
} else {
selectedBitmap =
MediaStore.Images.Media.getBitmap(this.contentResolver, selectedPicture)
imageButton.setImageBitmap(selectedBitmap)
}
}
} catch (e: Exception) {
}
}
//called when image was captured from camera intent
if (requestCode == 20 && resultCode == Activity.RESULT_OK && data != null) {
imageButton.setImageURI(selectedPicture)
}
super.onActivityResult(requestCode, resultCode, data)
}
fun saveClick(view: View) {
//UUID -> Image Name
val uuid = UUID.randomUUID()
val imageName = "$uuid.jpg"
val storage = FirebaseStorage.getInstance()
val reference = storage.reference
val imagesReference = reference.child("images").child(imageName)
if (selectedPicture != null) {
imagesReference.putFile(selectedPicture!!).addOnSuccessListener { taskSnapshot ->
// take the picture link to save the database
val uploadedPictureReference =
FirebaseStorage.getInstance().reference.child("images").child(imageName)
uploadedPictureReference.downloadUrl.addOnSuccessListener { uri ->
val downloadUrl = uri.toString()
println(downloadUrl)
val noteMap = hashMapOf<String, Any>()
noteMap.put("downloadUrl", downloadUrl)
noteMap.put("userEmail", auth.currentUser!!.email.toString())
noteMap.put("noteTitle", titleText.text.toString())
noteMap.put("yourNote", noteText.text.toString())
noteMap.put("date", Timestamp.now())
db.collection("Notes").add(noteMap).addOnCompleteListener { task ->
if (task.isComplete && task.isSuccessful) {
finish()
}
}.addOnFailureListener { exception ->
Toast.makeText(
applicationContext,
exception.localizedMessage?.toString(),
Toast.LENGTH_LONG
).show()
}
}
}
}
}
}
I also try to add on saveClick fun the codes below but did not work. What should I do ?
fun saveClick(view: View) {
//UUID -> Image Name
val uuid = UUID.randomUUID()
val imageName = "$uuid.jpg"
val storage = FirebaseStorage.getInstance()
val reference = storage.reference
val imagesReference = reference.child("images").child(imageName)
if (selectedPicture != null) {
imagesReference.putFile(selectedPicture!!).addOnSuccessListener { taskSnapshot ->
// take the picture link to save the database
val uploadedPictureReference =
FirebaseStorage.getInstance().reference.child("images").child(imageName)
uploadedPictureReference.downloadUrl.addOnSuccessListener { uri ->
val downloadUrl = uri.toString()
println(downloadUrl)
val noteMap = hashMapOf<String, Any>()
noteMap.put("downloadUrl", downloadUrl)
noteMap.put("userEmail", auth.currentUser!!.email.toString())
noteMap.put("noteTitle", titleText.text.toString())
noteMap.put("yourNote", noteText.text.toString())
noteMap.put("date", Timestamp.now())
db.collection("Notes").add(noteMap).addOnCompleteListener { task ->
if (task.isComplete && task.isSuccessful) {
finish()
}
}.addOnFailureListener { exception ->
Toast.makeText(
applicationContext,
exception.localizedMessage?.toString(),
Toast.LENGTH_LONG
).show()
}
}
}
}else {
val noteMap = hashMapOf<String, Any>()
noteMap.put("userEmail", auth.currentUser!!.email.toString())
noteMap.put("noteTitle", titleText.text.toString())
noteMap.put("yourNote", noteText.text.toString())
noteMap.put("date", Timestamp.now())
db.collection("Notes").add(noteMap).addOnCompleteListener { task ->
if (task.isComplete && task.isSuccessful) {
finish()
}
}
}
}
}
So all your logic is basically wrapped up in that putFile success callback, which requires an image to be successfully stored and retrieved (?) before anything will be added to the database.
You need to break that logic up, so you can only run the parts you want to - like just running the database update part if you don't have an image, or running that part later once your image is successfully handled.
So really, you need a "store in database" function to handle the final writing - call that directly if you don't have an image, call it in the success callbacks if you do. I'm just going to pseudocode this but:
saveData(noteMap: Map) {
add note to DB
}
saveClick() {
create noteMap with basic, non-image details (email, title etc)
if image is null, call saveData(noteMap)
else do the image stuff:
onSuccess:
add the downloadUrl to noteMap
call saveData(noteMap)
}
I see you've made an edit with an else branch which creates the map sans url and writes it - you're basically almost there, just make it a function instead, and pass the map in!

change the toolbar menu in android when the recycle view items are longClicked

I have implemented a recycle view and add images to the view by the camera. It is working fine. Now what i am going to do is, when the user long clicks on a recycle view item change the toolbar menu. I am getting the following error.
Process: com.example.fyp_patient, PID: 8797
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:164)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
at android.content.Context.obtainStyledAttributes(Context.java:677)
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:692)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:659)
at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:479)
at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:214)
at com.example.fyp_patient.MainActivity._$_findCachedViewById(Unknown Source:25)
at com.example.fyp_patient.MainActivity.onLongClick(ImageRecycleViewActivity.kt:237)
at android.view.View.performLongClickInternal(View.java:7444)
at android.view.View.performLongClick(View.java:7392)
at android.view.View.performLongClick(View.java:7410)
at android.view.View$CheckForLongPress.run(View.java:27811)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7188)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
My code is as follow.
ImageRecycleViewActivity.kt
var isInActionMode = false
private val uriArrayList = ArrayList<Uri>()
private val arrayList = ArrayList<Model>()
private var driveServiceHelper: DriveServiceHelper? = null
private var RC_AUTHORIZE_DRIVE = 101
private val REQUEST_IMAGE_CAPTURE: Int = 100
private var image_uri: Uri? = null
private val IMAGE_CAPTURE_CODE: Int = 101
private var ACCESS_DRIVE_SCOPE = Scope(Scopes.DRIVE_FILE)
private var SCOPE_EMAIL = Scope(Scopes.EMAIL)
lateinit var googleDriveService: Drive
var mDriveServiceHelper: DriveServiceHelper? = null
var adapter = Adapter(arrayList,this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_imagerecycleview)
setSupportActionBar(toolbar as Toolbar?)
updateView()
counter_text.visibility = View.GONE
btn.setOnClickListener {
checkForGooglePermissions()
createFolderInDrive()
}
fab.setOnClickListener {
getPermission()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.main, menu)
return true
}
/***********get the permission from the device to access the camera***********/
private fun getPermission() {
//if the system is marshmallow or above get the run time permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED ||
checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED
) {
//permission was not enabled
val permission = arrayOf(
android.Manifest.permission.CAMERA,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
)
//show popup to request permission
requestPermissions(permission, REQUEST_IMAGE_CAPTURE)
} else {
//permission already granted
openCamera()
}
} else {
//system os < marshmallow
openCamera()
}
}
/************open the device camera*************/
private fun openCamera() {
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "this is an images")
image_uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
//camera Intent
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE)
}
/*************call when user clicks on the permission request dialog********************/
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
//called when user allow or deny from permission request
when (requestCode) {
REQUEST_IMAGE_CAPTURE -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission from pop up was granted
openCamera()
} else {
//permission from pop up was denied
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show()
}
}
}
}
/************called when an image is captured*************/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
//called when image is captured from camera intent
if (resultCode == Activity.RESULT_OK) {
//set the image to the image view
image_uri?.let { uriArrayList.add(it) }
arrayList.add((image_uri?.let { Model("My title", "My description", it) }!!))
Log.i("check123", image_uri.toString())
updateView()
}
}
private fun updateView() {
val adapter = Adapter(arrayList, this)
recycleView.layoutManager = LinearLayoutManager(this)
recycleView.adapter = adapter
}
override fun onLongClick(view: View?): Boolean {
Log.i("clicktest","clicked")
toolbar.menu.clear()
toolbar.inflateMenu(R.menu.menu_action_mode)
counter_text.visibility=View.VISIBLE
isInActionMode=true
adapter.notifyDataSetChanged()
ActionBar.DISPLAY_HOME_AS_UP
return true
}
}
Adapter.kt
class Adapter(val arrayList: ArrayList<Model>,val context:Context) :
RecyclerView.Adapter<Adapter.ViewHolder>() {
class ViewHolder (itemView : View) : RecyclerView.ViewHolder(itemView){
fun bindItems (model: Model){
itemView.title.text = model.title
itemView.description.text = model.des
itemView.imageIv.setImageURI(model.uri)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.image_list_item, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return arrayList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindItems(arrayList[position])
if (!MainActivity().isInActionMode){
holder.itemView.checkbox.visibility=View.GONE
}else {
holder.itemView.checkbox.visibility=View.VISIBLE
}
holder.itemView.setOnLongClickListener(MainActivity())
}
}
Error occurs from this line
toolbar.menu.clear()
Please help me

Categories

Resources