Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CropImage.getActivityResult(data).bitmap = NULL #49

Closed
Morons opened this issue Feb 7, 2021 · 13 comments · Fixed by #70
Closed

CropImage.getActivityResult(data).bitmap = NULL #49

Morons opened this issue Feb 7, 2021 · 13 comments · Fixed by #70

Comments

@Morons
Copy link
Contributor

Morons commented Feb 7, 2021

Version 2.0.3

The Issue
CropImage.getActivityResult(data).bitmap = NULL

The Code

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
		
		super.onActivityResult(requestCode, resultCode, data)
		if (resultCode == RESULT_OK) {
			when (requestCode) {
				
				GALLERY_REQUEST_CODE -> {
					data?.data?.let { uri ->
						activity?.let {
							Log.d(TAG, "UpdateBlogFragment: onActivityResult: $uri")
							launchImageCrop(uri)
						}
					} ?: showImageSelectionError()
				}
				
				CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE -> {
					
					val resultBitmap: ByteArray?
					
					Log.d(TAG, "CROP: CROP_IMAGE_ACTIVITY_REQUEST_CODE")
					val result = CropImage.getActivityResult(data)
					if (result == null) {
						Log.d(TAG, "UpdateBlogFragment: onActivityResult: result = NULL")
					}
					val resultUri = result?.uri
					Log.d(TAG, "UpdateBlogFragment: onActivityResult resultUri: ${resultUri.toString()}")
					resultBitmap = result?.bitmap?.toByteArray()
					Log.d(TAG, "UpdateBlogFragment: onActivityResult resultBitmap Size: ${resultBitmap?.size}")
					val resultImage: String = Base64.decode(resultBitmap, Base64.DEFAULT).decodeToString()
					viewModel.setUpdatedUri(resultImage)
				}
				
				CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE -> {
					Log.d(TAG, "CROP: ERROR")
					showImageSelectionError()
				}
			}
		}
	}
	
	// extension function to convert bitmap to byte array
	private fun Bitmap.toByteArray(): ByteArray {
		ByteArrayOutputStream().apply {
			compress(Bitmap.CompressFormat.JPEG, 10, this)
			return toByteArray()
		}
	}
	
	// extension function to convert byte array to bitmap
	private fun ByteArray.toBitmap(): Bitmap {
		return BitmapFactory.decodeByteArray(this, 0, size)
	}

Expected behavior
I store my Images for the application in the backend and cashe as base64 strings (Works nice!)
I need the result to be in ByteArray not URI (I actually dont know how to extract a ByteArray from the URI)
So I try and extract the bitmap with .bitmap from th URI and then convert it to a ByteArray with the Extention function I wrote below
My viewModel also expects a base64 string or ByteArray

What happens
D/AppDebug: CROP: CROP_IMAGE_ACTIVITY_REQUEST_CODE
UpdateBlogFragment: onActivityResult resultUri: content://za.co.zone.cupio.cropper.fileprovider/my_images/Pictures/cropped7411884326467077015.jpg
UpdateBlogFragment: onActivityResult resultBitmap Size: null
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
...
Caused by: java.lang.NullPointerException: Attempt to get length of null array
at android.util.Base64.decode(Base64.java:138)
at za.co.zone.cupio.ui.main.blog.UpdateBlogFragment.onActivityResult(UpdateBlogFragment.kt:132)

Code Involved
val resultImage: String = Base64.decode(resultBitmap, Base64.DEFAULT).decodeToString()

Smartphone
AVD Pixel 4 XL API 30 64

@Morons Morons added the bug label Feb 7, 2021
@Morons Morons changed the title [Issue] - CropImage.getActivityResult(data).bitmap = NULL Feb 7, 2021
@Canato Canato added the pinned label Feb 7, 2021
@Canato
Copy link
Member

Canato commented Feb 7, 2021

@Morons how are you calling the library? getCroppedImageAsync ?

Another question, how is the output of this logs?

Log.d(TAG, "UpdateBlogFragment: onActivityResult: result = NULL")

Log.d(TAG, "UpdateBlogFragment: onActivityResult resultUri: ${resultUri.toString()}")

Log.d(TAG, "UpdateBlogFragment: onActivityResult resultBitmap Size: ${resultBitmap?.size}")

@Canato
Copy link
Member

Canato commented Feb 7, 2021

One more @Morons can you check if data is not null before call it?

@Morons
Copy link
Contributor Author

Morons commented Feb 7, 2021

I added

		if (data == null) {
			Log.d(TAG, "onActivityResult: data: Intent? is null")
		} else {
			Log.d(TAG, "onActivityResult: data: Intent? is not null")
		}

D/AppDebug: onActivityResult: data: Intent? is not null

D/AppDebug: UpdateBlogFragment: onActivityResult: content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F84/ORIGINAL/NONE/image%2Fjpeg/1954601542

D/AppDebug: onActivityResult: data: Intent? is not null

D/AppDebug: CROP: CROP_IMAGE_ACTIVITY_REQUEST_CODE

D/AppDebug: UpdateBlogFragment: onActivityResult resultUri: content://za.co.zone.cupio.cropper.fileprovider/my_images/Pictures/cropped6023895601553057964.jpg

D/AppDebug: UpdateBlogFragment: onActivityResult resultBitmap Size: null

@Morons
Copy link
Contributor Author

Morons commented Feb 7, 2021

So both the original URI and the Changed URI has values -> I can access them by result?.uri

@Morons
Copy link
Contributor Author

Morons commented Feb 7, 2021

I can search my Pictures on the device and crop one then ........

@Morons
Copy link
Contributor Author

Morons commented Feb 7, 2021

	private fun launchImageCrop(uri: Uri) {
		context?.let {
			CropImage.activity(uri)
				.setGuidelines(CropImageView.Guidelines.ON)
				.start(it, this)
		}
	}

@Canato
Copy link
Member

Canato commented Feb 7, 2021

@Morons I'm trying here, will put some effort to fix this! cannot guarantee will be something fast, sorry for this.

One more request, on this lines:

resultBitmap = result?.bitmap?.toByteArray()
Log.d(TAG, "UpdateBlogFragment: onActivityResult resultBitmap Size: ${resultBitmap?.size}")

Can you do:

resultBitmap = result?.bitmap
Log.d(TAG, "UpdateBlogFragment: onActivityResult resultBitmap Size: ${resultBitmap?}")

val array = resultBitmap?.toByteArray()
Log.d(TAG, "UpdateBlogFragment: onActivityResult resultBitmap Size: ${array?}")

Please! But will try to solve. In any case, if you have time, you can check the library code and try to solve. So we can release =)

Will tag here @CanHub/imagecropcollaborators if anyone have time to check this, interesting bug

@Morons
Copy link
Contributor Author

Morons commented Feb 7, 2021

CROP_IMAGE_ACTIVITY_REQUEST_CODE -> {
	
	val resultBitmap: Bitmap?
	
	Log.d(BaseBlogFragment.TAG, "CROP: CROP_IMAGE_ACTIVITY_REQUEST_CODE: ${CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE}")
	val result = CropImage.getActivityResult(data)
	if (result == null) {
		Log.d(BaseBlogFragment.TAG, "UpdateBlogFragment: onActivityResult: result = NULL")
	}
	val resultUri = result?.uri
	Log.d(BaseBlogFragment.TAG, "UpdateBlogFragment: onActivityResult resultUri: ${resultUri.toString()}")
	resultBitmap = result?.bitmap
	Log.d(BaseBlogFragment.TAG, "UpdateBlogFragment: onActivityResult resultBitmap Bitmap: $resultBitmap")
	
	val array = resultBitmap?.toByteArray()
	Log.d(BaseBlogFragment.TAG, "UpdateBlogFragment: onActivityResult resultBitmap array: $array")
	
	val resultImage: String = Base64.decode(array, Base64.DEFAULT).decodeToString()
	viewModel.setUpdatedUri(resultImage)
}

Results AppDebug
onActivityResult: data: Intent? is not null

D/AppDebug: UpdateBlogFragment: onActivityResult: before crop: content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F78/ORIGINAL/NONE/image%2Fwebp/1182126952

D/AppDebug: onActivityResult: data: Intent? is not null

D/AppDebug: CROP: CROP_IMAGE_ACTIVITY_REQUEST_CODE: 203

D/AppDebug: UpdateBlogFragment: onActivityResult resultUri: content://za.co.zone.cupio.cropper.fileprovider/my_images/Pictures/cropped7735694781174099916.jpg

D/AppDebug: UpdateBlogFragment: onActivityResult resultBitmap Bitmap: null

D/AppDebug: UpdateBlogFragment: onActivityResult resultBitmap array: null

@Morons
Copy link
Contributor Author

Morons commented Feb 7, 2021

I found this while re-factoring old working code from passing the URi to passing a base64 String for the image.
The Above is when I edit a existing picture, however I did not get to the part where I create a new blog and save a new picture .
That part is actually working as intended and I have though of a work around - but it will not solve this issue.
It will however finish my project - I will keep this version for testing and work on the work around whereby I will grab the picture rendered by Glide from the view and convert that to ByteArray and then to base64 String.
If it works on making a new Blog post I will implement it on this Edit blog also.

The BUG then would be that Crop does not build the URI correctly and the extraction to bitmap fails, am I correct?

Afterthought
As I think about it the Intent to pass the picture as a base64 String will / or can blow the data parcel size
Passing the URi between Activities might be better suited to older API versions.
However sharing the picture as a base64 String to Other applications like Telegram/WhatsApp/Gmail with Implicit Intent will be OK

@Canato
Copy link
Member

Canato commented Feb 7, 2021

@Morons totally, will work on fixing this ASAP

@Morons
Copy link
Contributor Author

Morons commented Feb 25, 2021

Any progress? fixing the bitmap output from CropImage

@Canato
Copy link
Member

Canato commented Feb 25, 2021

Any progress? fixing the bitmap output from CropImage

Not yet @Morons I'm very busy with normal work and changing jobs.
But on Monday I added new code on the sample that should make easy to reproduce this and fix.

You can jump in if you feel like, otherwise will need to wait a little.

I would love to be faster to tackle the bugs, but this code was 2 years without update when I handover so I need to have more time adding it structure so I'm sure I'm not breaking anything with the changes we add.

In any case, sorry for the delay, but be sure I'm putting as much time I can to improve it =)

@Canato
Copy link
Member

Canato commented Feb 26, 2021

@Morons I was taking a look with more attention today.

We have an issue because a bitmap is a huge data to pass between activities. When you try to get getOriginalBitmap we have the documentation:

Null if uri used to load image or activity result is used.

I was trying to improve this, creating a bitmap, but is too huge for the Parcel in the result activity.

So the solution for the library is to have a new method that will need the context to get the bitmap from the internal uri. Hope this solve you problem. is coming on next release 2.1.1 as soon the tickets are merged

Canato added a commit that referenced this issue Feb 26, 2021
@Canato Canato mentioned this issue Feb 26, 2021
4 tasks
Canato added a commit that referenced this issue Feb 26, 2021
* change stale days

* improve documentation

* Fix #49

* update changelog
@Canato Canato mentioned this issue Feb 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants