kotlin fragment in imagecropper not working - android

hi guys sory for my english not good :)
I write in fragment this code is not working and ı create new project and write this code in empty activity(is not activityfragment) is working
I'm thinking onActivityResult primary working but secondary not working
fragmentActivity logchat ->
0
1
2
3
4
999
emtyactivity logchat ->
0
1
2
3
4
999
1
5
6
7
8
9
10
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
println("1")
when (requestCode) {
GALLERY_REQUEST_CODE -> {
println("2")
if (resultCode == Activity.RESULT_OK) {
data?.data?.let { uri ->
println("3")
launchImageCrop(uri)
}
}
else{
Log.e(TAG, "Image selection error: Couldn't select that image from memory." )
}
}
CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE -> {
println("5")
val result = CropImage.getActivityResult(data)
if (resultCode == Activity.RESULT_OK) {
println("6")
setImage(result.uri)
}
else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Log.e(TAG, "Crop error: ${result.getError()}" )
}
}
}
}
private fun setImage(uri: Uri){
println("7")
Glide.with(this)
.load(uri)
.into(binding.imageView5)
selectedPicture=uri
println("8")
val storage= FirebaseStorage.getInstance()
val reference=storage.reference
val imagesReference=reference.child(UserUID)
imagesReference.putFile(selectedPicture!!).addOnSuccessListener { taskSnapshop->
println("9")
object : CountDownTimer(10000,1000){
override fun onFinish() {
val uploadPictureReference= FirebaseStorage.getInstance().reference.child(UserUID)
uploadPictureReference.downloadUrl.addOnSuccessListener { uri->
println("10")
println(uri.toString())
userphotohash.put("UserProfilePhoto",uri.toString())
db.collection("users").document(UserUID).update(userphotohash)
}
}
override fun onTick(millisUntilFinished: Long) {//her coundownda olması istenilen görevi yapıyor
}
}.start()
}
}
private fun launchImageCrop(uri: Uri){
println("4")
CropImage.activity(uri)
.setGuidelines(CropImageView.Guidelines.ON)
.setAutoZoomEnabled(false)
.setMaxCropResultSize(800,800)
.setCropShape(CropImageView.CropShape.RECTANGLE) // default is rectangle
.start(this)
println("999")
}
private fun pickFromGallery() {
println("0")
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
intent.type = "image/*"
val mimeTypes = arrayOf("image/jpeg", "image/png", "image/jpg")
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(intent, GALLERY_REQUEST_CODE)
}

Related

onActivityResult deprecated, is there alternative (KOTLIN)

Currently I am working on a project for my college, and i have discovered that onActivityResult is deprecated. What can be done to handle it?
This is my code that troubles me
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
val result = CropImage.getActivityResult(data)
if (resultCode == RESULT_OK) {
image = result.uri
Glide.with(this).load(image).into(binding.imgPick)
} else {
Snackbar.make(
binding.root,
"Image not selected",
Snackbar.LENGTH_SHORT
).show()
}
}
}
I tried to find a solution on stackoverflow and already tried to implement couple of thing but with no luck.
You can use the following way :
fun openActivityForResult() {
startForResult.launch(Intent(this, AnotherActivity::class.java))
}
val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
val intent = result.data
// Handle the Intent
//do stuff here
}
}
You can use this in activity or fragment.
First define intent result launcher.
var picker: ActivityResultLauncher<Intent>
then
picker = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK && it.data != null) {
//add your code here
}
}
And now launch your activity.
val intent = Intent(context, ImagePickerActivity::class.java)
picker.launch(intent)

How to receive path from internal storage in android and transform it into view?

I'm new to android development and I've been building an app for studies purposes that is supposed to display one of the images selected from the gallery previously in a recyclerview.
private fun configDocImageDialog(pathGallery: Int, pathCamera: Int) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.camera_or_gallery))
.setMessage(getString(R.string.image_path))
.setPositiveButton(getString(R.string.gallery)) { _, _ ->
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_GET_CONTENT
startActivityForResult(Intent.createChooser(intent, "Select: "), pathGallery)
}.setNegativeButton(getString(R.string.camera)) { _, _ ->
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(Intent.createChooser(intent, "Take: "), pathCamera)
}.setNeutralButton(getString(R.string.cancel)) { dialog, _ ->
dialog.dismiss()
}.show()
}
Not I'm not worried about the camera result.
Then receiving the result as:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(resultCode == RESULT_OK) {
val selectedImage = data!!.data
val pathImage = selectedImage.toString()
try {
when (requestCode) {
GALLERY_1 -> {
binding.imageDoc1.setImageURI(selectedImage)
}
CAMERA_1 -> {
binding.imageDoc1.setImageURI(selectedImage)
}
GALLERY_2 -> {
binding.imageDoc2.setImageURI(selectedImage)
}
CAMERA_2 -> {
binding.imageDoc2.setImageURI(selectedImage)
}
GALLERY_3 -> {
binding.imageDoc3.setImageURI(selectedImage)
}
CAMERA_3 -> {
binding.imageDoc3.setImageURI(selectedImage)
}
}
imageList.add(pathImage)
} catch (e: Exception){
e.printStackTrace()
}
}
}
I received as a result from the intent a list with this kind of content:
content://com.android.providers.media.documents/document/image%3A20
And those are saved into the database, the list of paths. /
Is it possible to use this path to my exhibit the image in my adapter? I've been trying different treatments but it always blank.
I've trying to use Picasso as:
override fun onBindViewHolder(holder: DocViewHolder, position: Int) {
val doc = docs[position]
holder.binding.apply {
Picasso.get()
.load(doc.docImageList[0])
.into(imageDoc)
textDocName.text = doc.title
textValidity.text = doc.validity
}
holder.itemView.setOnClickListener {
onItemClickListener?.let {
it(doc)
}
}
}
I want to display an image from internal storage in a recyclerview but the image is always blank.
Any ideas how to do it properly? Thanks

Android 11 ActivityResult throwing only RESULT_CANCELED

We are selecting image/video files with this code
//Pick an image from storage
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType(type); //Can be image/* or video/*
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
activityResultLauncher.launch(Intent.createChooser(intent, "Select Item"));
Then obtain the file Uri(s) on new ActivityResult API
protected final ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
Log.wtf("WTF", result.toString());
if (result.getResultCode() == Activity.RESULT_OK) {
// There are no request codes
Intent data = result.getData();
if (data == null) {
Toast.makeText(getContext(), R.string.unknown_error, Toast.LENGTH_SHORT).show();
return;
}
activityResult(true, data);
}
else
activityResult(false, null);
});
Unfortunately after updating to Android 11 all we got is RESULT_CANCELED.
E/WTF: ActivityResult{resultCode=RESULT_CANCELED, data=null}
As what Ian said, you were not supposed to user Intent.createChooser with ACTION_OPEN_DOCUMENT though it works prior to Android 11.
Here is a helper class you use as a contract to select image/video/pdf using Activity Result API that will return you a list of Uri's. It can be configured for single or multiple selection of files.
Tested in android 10 and 11.
class SelectFileContract : ActivityResultContract<Pair<SELECTION_TYPE, Boolean>, List<Uri>?>() {
var TAG = this.javaClass.simpleName
override fun createIntent(context: Context, input: Pair<SELECTION_TYPE, Boolean>): Intent {
var intent: Intent? = null
intent = when (input.first) {
SELECTION_TYPE.IMAGE -> Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)
SELECTION_TYPE.VIDEO -> Intent(
Intent.ACTION_PICK,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
)
SELECTION_TYPE.PDF -> {
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
type = "application/pdf"
addCategory(Intent.CATEGORY_OPENABLE)
}
}
}
if (input.second == true) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
return intent!!
}
override fun parseResult(resultCode: Int, intent: Intent?): List<Uri>? = when (resultCode) {
Activity.RESULT_OK -> {
val uriList = mutableListOf<Uri>()
/**
* in case of single selection the Uri will be inside [intent.data]
*/
intent?.data?.let { uriList.add(it) }
/**
* in case of multiple selection the Uri will be inside [intent.clipData]
*/
intent?.clipData?.let { clipData: ClipData ->
for (i in 0 until clipData.itemCount) {
uriList.add(clipData.getItemAt(i).uri)
}
}
Log.d(TAG, uriList.toString())
uriList
}
else -> null
}
}
enum class SELECTION_TYPE {
IMAGE,
VIDEO,
PDF
}
Then in activity specific the contract:
private val simpleContractRegistration =
registerForActivityResult(SelectFileContract()) { result: List<Uri>? ->
result?.let {
Log.d(TAG, result.toString())
}
}
Then launch the registration:
binding.button.setOnClickListener {
simpleContractRegistration.launch(
Pair(
SELECTION_TYPE.IMAGE,
false
)
)
}

Method from OnActivityResult Fragment executed, but nothing happend in View

can you help me., ?
I am new in develop Android use kotlin, and still learning.,
this my code on Fragment.,
......
private fun takePhotoFromCamera() {
Dexter.withActivity(requireActivity())
.withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
// Here after all the permission are granted launch the CAMERA to capture an image.
if (report!!.areAllPermissionsGranted()) {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra("Document", 2)
startActivityForResult(intent, CAMERA)
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?,
) {
showRationalDialogForPermissions()
}
}).onSameThread()
.check()
}
private fun choosePhotoFromGallery() {
Dexter.withActivity(activity)
.withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
// Here after all the permission are granted launch the gallery to select and image.
if (report!!.areAllPermissionsGranted()) {
val galleryIntent = Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)
galleryIntent.putExtra("Document", 2)
startActivityForResult(galleryIntent, GALLERY)
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?,
) {
showRationalDialogForPermissions()
}
}).onSameThread()
.check()
}
and this onActivityResult from parent Activity for Fragment
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
for (fragment in supportFragmentManager.fragments) {
fragment.onActivityResult(requestCode, resultCode, data)
}
}
And this OnActivityResult from Fragment
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
if (requestCode == GALLERY) {
if (data != null) {
val contentURI = data.data
try {
// Here this is used to get an bitmap from URI
#Suppress("DEPRECATION")
val selectedImageBitmap =
MediaStore.Images.Media.getBitmap(requireActivity().contentResolver,
contentURI)
// TODO (Step 3 : Saving an image which is selected from GALLERY. And printed the path in logcat.)
// START
val saveImageToInternalStorage =
saveImageToInternalStorage(selectedImageBitmap)
Log.i("Saved Image : ", "Path :: $saveImageToInternalStorage")
// END
binding.btnNpwpCaptureAgain.visibility=View.VISIBLE
binding.ivPvNpwp.foreground.clearColorFilter()
binding.cvNpwp.visibility=View.GONE
binding.btnCaptureNpwp.visibility=View.GONE
binding.ivNpwpPreview.setImageBitmap(selectedImageBitmap) // Set the selected image from GALLERY to imageView.
} catch (e: IOException) {
e.printStackTrace()
Toast.makeText(requireActivity(), "Failed!", Toast.LENGTH_SHORT).show()
}
}
} else if (requestCode == CAMERA) {
val thumbnail: Bitmap = data!!.extras!!.get("data") as Bitmap // Bitmap from camera
// TODO (Step 4 : Saving an image which is selected from CAMERA. And printed the path in logcat.)
// START
val saveImageToInternalStorage =
saveImageToInternalStorage(thumbnail)
Log.i("Saved Image : ", "Path :: $saveImageToInternalStorage")
//binding.btnCaptureKtp.text = getString(R.string.regist_step_2_KTP_retake).toString()
// END
binding.btnNpwpCaptureAgain.visibility=View.VISIBLE
binding.ivPvNpwp.foreground.clearColorFilter()
binding.btnCaptureNpwp.visibility=View.GONE
binding.cvNpwp.visibility=View.GONE
binding.ivNpwpPreview.setImageBitmap(thumbnail) // Set to the imageView.
}
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.e("Cancelled", "Cancelled")
}
//
}
My Problem is why this block is executed, but nothing happend ??
....
binding.btnNpwpCaptureAgain.visibility=View.VISIBLE
binding.ivPvNpwp.foreground.clearColorFilter()
binding.btnCaptureNpwp.visibility=View.GONE
binding.cvNpwp.visibility=View.GONE
binding.ivNpwpPreview.setImageBitmap(thumbnail)
......
Thank you for respond my question.,
Try with putting another null check for "contentURI". Like :-
if(contentURI != null){
try {
// Here this is used to get an bitmap from URI
#Suppress("DEPRECATION")
val selectedImageBitmap =
MediaStore.Images.Media.getBitmap(requireActivity().contentResolver,
contentURI)
// TODO (Step 3 : Saving an image which is selected from GALLERY. And printed the path in logcat.)
// START
val saveImageToInternalStorage =
saveImageToInternalStorage(selectedImageBitmap)
Log.i("Saved Image : ", "Path :: $saveImageToInternalStorage")
// END
binding.btnNpwpCaptureAgain.visibility=View.VISIBLE
binding.ivPvNpwp.foreground.clearColorFilter()
binding.cvNpwp.visibility=View.GONE
binding.btnCaptureNpwp.visibility=View.GONE
binding.ivNpwpPreview.setImageBitmap(selectedImageBitmap) // Set the selected image from GALLERY to imageView.
} catch (e: IOException) {
e.printStackTrace()
Toast.makeText(requireActivity(), "Failed!", Toast.LENGTH_SHORT).show()
}
}
As onActivityResult() method is deprecated, its better to use registerForActivityResult(). Like below :
private val startForResultToLoadImage = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
try {
val selectedImage: Uri? = result.data?.data
if (selectedImage != null){
// From Gallery
// Use uri to get the image
}else{
// From Camera code goes here.
// Get the bitmap directly from camera
val bitmap: Bitmap = result.data?.extras?.get("data") Bitmap
}
} catch (error: Exception) {
Log.d("log==>>", "Error : ${error.localizedMessage}")
}
}
}
For gallery call it like:
val intent = Intent (Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startForResultToLoadImage.launch(intent)
For camera call it like:
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.putExtra(MediaStore.EXTRA_OUTPUT, it)
startForResultToLoadImage.launch(intent)
I believe you should:
Print log at the start of the function with all of the parameters printed to always know how the code will branch. Something like Log.i("onActivityResult: ", "requestCode=" + requestCode + “, resultCode=” + resultCode + “, data=” + data);
Check your request code before you check result code since different requests may have different results.
You’re assuming the result would be either Activity.RESULT_CANCELED or Activity.RESULT_OK but the result code might be a custom result, so please add another else branch after you check Activity.RESULT_CANCELED to be sure you’re covering all results.
Don’t call Fragment.onActivityResult from Activity.onActivityResult if your activity inherits from AppCompatActivity. Activity automatically forward the result to fragments (it even allows request code duplication across fragments without mixing the fragments).
The structure of onActivityResult should be mainly:
if (requestCode == REQUEST_1) {
if (resultCode == RESULT_1) {
// Do your thing
} else if (resultCode == RESULT_2) {
// Do your thing
} else if (resultCode == RESULT_LAST) {
// Do your thing
} else {
// Important!! Expect the unexpected
}
} else if (requestCode == REQUEST_2) {
...
} else if (requestCode == REQUEST_LAST) {
...
}
I would use switch-case instead if-else but it’s you code style so I won’t judge :)

Overwrite data in firebase database

I try to make an storage where i can save my image in firebase storage but everytime i upload a new image it will replace the old one,i want evertime a new image will be save on storage,i am on android studio using kotlin,Is my code is wrong?here is my code
class Activity2 : AppCompatActivity() {
var curFile: Uri? = null
val imageRef = Firebase.storage.reference
private val userCollection = Firebase.firestore.collection("persons")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity2)
//here where a button to get an image from gallery
tvpilihfoto.setOnClickListener {
Intent(Intent.ACTION_GET_CONTENT).also {
it.type = "image/*"
val REQUEST_CODE_IMAGE_PICK = 0
startActivityForResult(it, REQUEST_CODE_IMAGE_PICK)
}
//this button for an upload activity to send the image to database firebase
btnupload.setOnClickListener {
uploadImageToStorage("my image")
}
}
private fun uploadImageToStorage(filename : String) = CoroutineScope(Dispatchers.IO).launch {
try {
curFile?.let {
imageRef.child("images/$filename").putFile(it).await()
withContext(Dispatchers.Main) {
Toast.makeText(this#Activity2,"Foto anda telah dipilih",
Toast.LENGTH_LONG).show()
}
}
} catch (e : Exception) {
withContext(Dispatchers.Main) {
Toast.makeText(this#Activity2,e.message,Toast.LENGTH_LONG).show()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val REQUEST_CODE_IMAGE_PICK = 0
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_IMAGE_PICK) {
data?.data?.let {
curFile = it
ivfoto.setImageURI(it)
//this where my image get or display in app
}
}
}
}
Since you're always calling uploadImageToStorage("my image"), the image will alway be called my image. So each time you make that call, it will overwrite the previous my image in storage.
To always add a new image, generate a unique filename in your code. For example:
uploadImageToStorage(UUID.randomUUID().toString())

Categories

Resources