CanHub / Android-Image-Cropper

Image Cropping Library for Android, optimised for Camera / Gallery.
Apache License 2.0
1.24k stars 255 forks source link

[BUG] - MIUI (Xiaomi) cant pick image from gallery #253

Closed alpesh76 closed 2 years ago

alpesh76 commented 2 years ago

Phone Model: Xiomi Redmi K20 Pro Version: Android 11 (RQ1.200826.002) CanHub Version: 3.3.5

I tried your sample project & run it. But it didn't work on my phone. Also, I uploaded a video for the issue.

https://www.youtube.com/watch?v=MY-bo92LFeo

Please check & replay.

Canato commented 2 years ago

Strange bug ><

Will try to reproduce, I'm in a conference these days, until there are any value logs that you could provide?

Canato commented 2 years ago

Maybe if you can log the image URI will already help me a lot to understand :c

ArcherEmiya05 commented 2 years ago

This is a known issue, I don't know why this Android 11 issue is always being close without providing any solution at all. The root cause of issue is getting Activity.RESULT_CANCELED instead of Activity.RESULT_OK, I think the library still use Intent.createChooser which seems very problematic in Android 11 when selecting a file image as it will result a cancel.

alpesh76 commented 2 years ago

Strange bug ><

Will try to reproduce, I'm in a conference these days, until there are any value logs that you could provide?

It didn't gives any logs.

Canato commented 2 years ago

@ArcherEmiya05

This is a known issue, I don't know why this Android 11 issue is always being close without providing any solution at all.

Issue Close because didn't follow the templates Issue Close because didn't follow the templates Issue Wrong information on the discussion, what make impossible to understand and debug the problem Issue Close because didn't follow the templates

Just trying to explain my self, since this is an open source lib that id driven by the community. Anyone is free to join the maintainers team and help, even I encourage it.

Is important to understand that we need to have a level of information, I cannot reproduce the bug so I cannot fixed without more information. If you have another issue example that was closed and you do not agree with it please open a discussion for it, would be happy to understand and improve the way the repository is going ^^

As you can see, in this issue, that give enough information and is organised I did not close and add the label pinned so the stale bot will not close automatically and we can focus on this.

The root cause of issue is getting Activity.RESULT_CANCELED instead of Activity.RESULT_OK, I think the library still use Intent.createChooser which seems very problematic in Android 11 when selecting a file image as it will result a cancel.

Is great that you already spot the problem, please feel free to open a PR with a possible fix that we can test and merge it, for sure will help a lot of users =).

Edited: Plus, you can see many, many, issues or discussion where people open a lot of things/problems that are not really library problems, sadly my time for maintain this as a volunteer work is limited, but trying to do my best, hopefully you can help me =)

Canato commented 2 years ago

Strange bug >< Will try to reproduce, I'm in a conference these days, until there are any value logs that you could provide?

It didn't gives any logs.

@alpesh76 on the class SCropImageViewFragment can you debug the values or add a log for what information we get in this method:

    private val openPicker = registerForActivityResult(PickImageContract()) { imageUri ->
        if (imageUri != null && CropImage.isReadExternalStoragePermissionsRequired(requireContext(), imageUri)
        ) {
            cropImageUri = imageUri
            requestPermissions(
                arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                CropImage.PICK_IMAGE_PERMISSIONS_REQUEST_CODE
            )
        } else {
            binding.cropImageView.setImageUriAsync(imageUri)
        }
    }

I'm curious to see if imageUri is null or some strange value, thanks for the help =D

alpesh76 commented 2 years ago
2021-10-30 00:11:57.824 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435986874
2021-10-30 00:11:57.824 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435986874
2021-10-30 00:11:57.824 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435986874
2021-10-30 00:12:00.661 1336-1336/com.example.croppersample E/Camera Error:: picking image failed
2021-10-30 00:12:00.665 1336-1336/com.example.croppersample D/CompatibilityChangeReporter: Compat change id reported: 147798919; UID 11162; state: ENABLED
2021-10-30 00:12:02.171 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435991220
2021-10-30 00:12:00.661 1336-1336/com.example.croppersample E/Camera Error:: picking image failed
2021-10-30 00:12:00.665 1336-1336/com.example.croppersample D/CompatibilityChangeReporter: Compat change id reported: 147798919; UID 11162; state: ENABLED
2021-10-30 00:12:02.171 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435991220
2021-10-30 00:12:00.661 1336-1336/com.example.croppersample E/Camera Error:: picking image failed
2021-10-30 00:12:00.665 1336-1336/com.example.croppersample D/CompatibilityChangeReporter: Compat change id reported: 147798919; UID 11162; state: ENABLED
2021-10-30 00:12:02.171 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435991220
2021-10-30 00:12:05.029 1336-1336/com.example.croppersample E/Camera Error:: picking image failed
2021-10-30 00:12:07.162 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435996211
2021-10-30 00:12:07.219 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435996269
2021-10-30 00:12:05.029 1336-1336/com.example.croppersample E/Camera Error:: picking image failed
2021-10-30 00:12:05.029 1336-1336/com.example.croppersample E/Camera Error:: picking image failed
2021-10-30 00:12:07.219 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435996269
2021-10-30 00:12:07.162 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435996211
2021-10-30 00:12:07.219 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435996269
2021-10-30 00:12:07.329 882-19444/? I/vendor.qti.hardware.servicetracker@1.2-service: Activity state is changed to : 3
2021-10-30 00:12:10.258 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435999307
2021-10-30 00:12:10.371 1336-1336/com.example.croppersample W/ImageView: Unable to open content: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg

2021-10-30 00:12:10.258 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435999307
2021-10-30 00:12:10.371 1336-1336/com.example.croppersample W/ImageView: Unable to open content: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
2021-10-30 00:12:10.371 1336-1336/com.example.croppersample W/ImageView: resolveUri failed on bad bitmap uri: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
2021-10-30 00:12:12.007 1336-1336/com.example.croppersample D/MIUIInput: [KeyEvent] ViewRootImpl KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x8, repeatCount=0, eventTime=436001051, downTime=436001051, deviceId=-1, source=0x101, displayId=-1 }
2021-10-30 00:12:12.010 1336-1336/com.example.croppersample D/MIUIInput: [KeyEvent] ViewRootImpl KeyEvent { action=ACTION_UP, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x8, repeatCount=0, eventTime=436001051, downTime=436001051, deviceId=-1, source=0x101, displayId=-1 }
2021-10-30 00:12:12.007 1336-1336/com.example.croppersample D/MIUIInput: [KeyEvent] ViewRootImpl KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x8, repeatCount=0, eventTime=436001051, downTime=436001051, deviceId=-1, source=0x101, displayId=-1 }
2021-10-30 00:12:12.010 1336-1336/com.example.croppersample D/MIUIInput: [KeyEvent] ViewRootImpl KeyEvent { action=ACTION_UP, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x8, repeatCount=0, eventTime=436001051, downTime=436001051, deviceId=-1, source=0x101, displayId=-1 }
2021-10-30 00:12:09.751 904-978/? D/DisplayFeatureHal: set brightness to 419, virtual brightness 839
2021-10-30 00:12:13.096 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436002146
2021-10-30 00:12:13.153 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436002202
2021-10-30 00:12:13.205 1336-1364/com.example.croppersample W/System: A resource failed to call dispose. 
2021-10-30 00:12:13.096 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436002146
2021-10-30 00:12:10.258 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:435999307
2021-10-30 00:12:13.153 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436002202
2021-10-30 00:12:13.205 1336-1364/com.example.croppersample W/System: A resource failed to call dispose. 
2021-10-30 00:12:10.371 1336-1336/com.example.croppersample W/ImageView: Unable to open content: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
2021-10-30 00:12:10.371 1336-1336/com.example.croppersample W/ImageView: resolveUri failed on bad bitmap uri: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
2021-10-30 00:12:12.007 1336-1336/com.example.croppersample D/MIUIInput: [KeyEvent] ViewRootImpl KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x8, repeatCount=0, eventTime=436001051, downTime=436001051, deviceId=-1, source=0x101, displayId=-1 }
2021-10-30 00:12:12.010 1336-1336/com.example.croppersample D/MIUIInput: [KeyEvent] ViewRootImpl KeyEvent { action=ACTION_UP, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x8, repeatCount=0, eventTime=436001051, downTime=436001051, deviceId=-1, source=0x101, displayId=-1 }
2021-10-30 00:12:13.096 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436002146
2021-10-30 00:12:16.875 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436005925
2021-10-30 00:12:16.875 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436005925
2021-10-30 00:12:13.153 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436002202
2021-10-30 00:12:13.205 1336-1364/com.example.croppersample W/System: A resource failed to call dispose. 
2021-10-30 00:12:16.993 1336-1336/com.example.croppersample W/ImageView: Unable to open content: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
2021-10-30 00:12:16.993 1336-1336/com.example.croppersample W/ImageView: resolveUri failed on bad bitmap uri: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
2021-10-30 00:12:16.993 1336-1336/com.example.croppersample W/ImageView: Unable to open content: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
2021-10-30 00:12:16.875 1336-1336/com.example.croppersample I/Timeline: Timeline: Activity_launch_request time:436005925
2021-10-30 00:12:16.993 1336-1336/com.example.croppersample W/ImageView: Unable to open content: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
    android.graphics.ImageDecoder$DecodeException: Failed to create image decoder with message 'unimplemented'Input contained an error.
        at android.graphics.ImageDecoder.nCreate(Native Method)
        at android.graphics.ImageDecoder.createFromAssetFileDescriptor(ImageDecoder.java:359)
        at android.graphics.ImageDecoder.access$400(ImageDecoder.java:173)
        at android.graphics.ImageDecoder$ContentResolverSource.createImageDecoder(ImageDecoder.java:294)
        at android.graphics.ImageDecoder.decodeDrawableImpl(ImageDecoder.java:1758)
        at android.graphics.ImageDecoder.decodeDrawable(ImageDecoder.java:1751)
        at android.widget.ImageView.getDrawableFromUri(ImageView.java:1011)
        at android.widget.ImageView.resolveUri(ImageView.java:980)
        at android.widget.ImageView.setImageURI(ImageView.java:557)
        at com.canhub.cropper.sample.SCropResultActivity.onCreate(SCropResultActivity.kt:60)
        at android.app.Activity.performCreate(Activity.java:8127)
        at android.app.Activity.performCreate(Activity.java:8098)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3513)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3700)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2136)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:236)
        at android.app.ActivityThread.main(ActivityThread.java:8061)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
2021-10-30 00:12:16.993 1336-1336/com.example.croppersample W/ImageView: resolveUri failed on bad bitmap uri: content://com.example.croppersample.cropper.fileprovider/my_images/Pictures/cropped4232336690980655399.jpg
Canato commented 2 years ago

Back this week =)

@alpesh76 if you debug your device and look into Device File Explorer can you see this image inside the app folder?

I will work on an solution this week, thanks for the help so far

Canato commented 2 years ago

@ArcherEmiya05 I was checking the link you provide, but they say:

You were never supposed to use Intent.createChooser with ACTION_OPEN_DOCUMENT.

We are not using ACTION_OPEN_DOCUMENT, any case I was trying to remove createChooser but didn't found any replacement for it. Any suggestion how we could show Camera Or Gallery option? 🤔

alpesh76 commented 2 years ago

Back this week =)

@alpesh76 if you debug your device and look into Device File Explorer can you see this image inside the app folder?

I will work on an solution this week, thanks for the help so far

Sorry for late replay.

I checked it, I Can't see temp_image in Device File Explorer after picking from gallery. But it available when you capture image from camera. (Camera work perfectly)

Canato commented 2 years ago

@alpesh76 can you reproduce in any of the emulator? so I can try?

Canato commented 2 years ago

Was doing some test to reproduce, @alpesh76 can you check if work on this device for the version 3.1.3 of the lib?

alpesh76 commented 2 years ago

Was doing some test to reproduce, @alpesh76 can you check if work on this device for the version 3.1.3 of the lib?

It doesn't work in 3.1.3

ArcherEmiya05 commented 2 years ago

It seems only Xiaomi Android 11 does experiencing this issue probably because of MIUI 12 and other custom that Chinese brand implements. Tried to run it on emulator but it works just fine.

ArcherEmiya05 commented 2 years ago

@ArcherEmiya05 I was checking the link you provide, but they say:

You were never supposed to use Intent.createChooser with ACTION_OPEN_DOCUMENT.

We are not using ACTION_OPEN_DOCUMENT, any case I was trying to remove createChooser but didn't found any replacement for it. Any suggestion how we could show Camera Or Gallery option? 🤔

Yes I already tried before to remove the createChooser with the sample project and cropping works after selecting image file, unfortunately the camera option will no longer be available. Maybe lets not concatenate the Intents and create a layout with our own chooser implementation. Thus we no longer need to rely on createChooser which is causing the issue.

Canato commented 2 years ago

Thus we no longer need to rely on createChooser which is causing the issue.

I'm trying this solution, would you know any option to make this? We could maybe open a dialog for it, with Camera/Gallery options and open the right intent, what you think?

Wanna do this PR?

Otherwise I can try to find time on weekend

ArcherEmiya05 commented 2 years ago

Thus we no longer need to rely on createChooser which is causing the issue.

I'm trying this solution, would you know any option to make this? We could maybe open a dialog for it, with Camera/Gallery options and open the right intent, what you think?

Wanna do this PR?

Otherwise I can try to find time on weekend

Yes a simple AlertDialog can do the job, we just need to open a dialog with list of options: Camera, Gallery, File Manager and separate each intent from this.

@JvmStatic
    fun getPickImageChooserIntent(
        context: Context,
        title: CharSequence?,
        options: PickImageContractOptions
    ): Intent {
        val includeCamera = options.includeCamera
        val includeGallery = options.includeGallery
        val allIntents: MutableList<Intent> = ArrayList()
        val packageManager = context.packageManager

        // collect all camera intents if Camera permission is available
        if (!isExplicitCameraPermissionRequired(context) && includeCamera)
            allIntents.addAll(getCameraIntents(context, packageManager))

        if (includeGallery)
            allIntents.addAll(getGalleryIntents(packageManager, Intent.ACTION_GET_CONTENT))

        // Create a chooser from the main  intent
        val chooserIntent = Intent.createChooser(allIntents.removeAt(allIntents.size - 1), title)

        // Add all other intents
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, allIntents.toTypedArray<Parcelable>())

        return chooserIntent
    }

You might also need to make this AlertDialog style editable so users can manipulate the UI according to their requirements as well.

Canato commented 2 years ago

You might also need to make this AlertDialog style editable so users can manipulate the UI according to their requirements as well.

Would make without custom style for the first version. Even because if someone wanna use a custom dialog, they can create they own and call image pick directly with gallery or camera only (what would avoid the dialog) and/or pass the uri directly

ArcherEmiya05 commented 2 years ago

You might also need to make this AlertDialog style editable so users can manipulate the UI according to their requirements as well.

Would make without custom style for the first version. Even because if someone wanna use a custom dialog, they can create they own and call image pick directly with gallery or camera only (what would avoid the dialog) and/or pass the uri directly

Can you give the sample on accessing separately the intent of camera, gallery and file manager that is already in this library? I am looking at the Java sample and README file but cannot replicate it and there is also no PickImageContractOptions. Based on my understanding you need to provide Uri once you capture an image when using camera intent but that means you need to implement again the same feature that the library has just to escape this bug cause by fragmented ecosystem. I saw the sample which has startCameraWithoutUri() but I don't quite get what is the difference of its CropImageContractOptions from startCameraWithUri() that will make the library's camera to launch. Thus I suggest to just make a dialog where the basic style is public either by setter or builder. Thanks

hyuwah commented 2 years ago

It seems only Xiaomi Android 11 does experiencing this issue probably because of MIUI 12 and other custom that Chinese brand implements. Tried to run it on emulator but it works just fine.

Can confirm this, i've recently stumbled upon the same issue in another app with devices running MIUI on Android 11. The fix was rather simple but it must be done on user / device side, which was by choosing a default app when opening the intent.

https://user-images.githubusercontent.com/5181388/141261419-0c6cdbdc-462f-40af-826f-9d1a25468a7c.mp4

Here's related StackOverflow post regarding this issue

One workaround for the code is to check if the device is running MIUI on Android 11, then skips the chooser and just uses the first found camera/gallery app

Canato commented 2 years ago

Thanks for the update @hyuwah, since this is a problem of MIUI we should not change the behaviour for others platforms that are using Android correctly.

So the best solution would be add a check for MIUI when true it should display the alert dialog, otherwise should keep the behaviour we have today. Making it self contained.

Canato commented 2 years ago

@ArcherEmiya05

Can you give the sample on accessing separately the intent of camera, gallery and file manager that is already in this library?

We have gallery or camera options only now. Inside PickImageContractOptions you can check the parameters for each. In the class SCropImageFragmentJava you can see the code:

Screenshot 2021-11-11 at 08 30 53

Where you can play with the variables for camera and gallery

I am looking at the Java sample and README file but cannot replicate it and there is also no PickImageContractOptions.

Check SCropImageFragmentJava

Based on my understanding you need to provide Uri once you capture an image when using camera intent but that means you need to implement again the same feature that the library has just to escape this bug cause by fragmented ecosystem.

Yes, since this is a XIAOMI issue, until someone open a PR to fix it, each dev need to do a workaround, or someone open a PR and fix for everyone ^^

I saw the sample which has startCameraWithoutUri() but I don't quite get what is the difference of its CropImageContractOptions from startCameraWithUri() that will make the library's camera to launch.

One have URI and another do not have URI, if you don't provide the URI, the library will open a picker option

Thus I suggest to just make a dialog where the basic style is public either by setter or builder. Thanks

Feel free to drop the PR and we can discuss =D

alpesh76 commented 2 years ago

@Canato, Please check this. Direct open camera is working perfectly, But open chooser & select camera is not working in cropping image.

https://user-images.githubusercontent.com/29017178/141294357-ef391145-4634-42e0-b50e-db1112f6e220.mp4

Canato commented 2 years ago

@Canato, Please check this. Direct open camera is working perfectly, But open chooser & select camera is not working in cropping image.

Hey @alpesh76 I think this is what we have discussion right? What hyuwah said in his comment ^^

Or there is some new information that I'm missing on the video? 🤔

ArcherEmiya05 commented 2 years ago

@ArcherEmiya05

Can you give the sample on accessing separately the intent of camera, gallery and file manager that is already in this library?

We have gallery or camera options only now. Inside PickImageContractOptions you can check the parameters for each. In the class SCropImageFragmentJava you can see the code: Screenshot 2021-11-11 at 08 30 53

Where you can play with the variables for camera and gallery

I am looking at the Java sample and README file but cannot replicate it and there is also no PickImageContractOptions.

Check SCropImageFragmentJava

Based on my understanding you need to provide Uri once you capture an image when using camera intent but that means you need to implement again the same feature that the library has just to escape this bug cause by fragmented ecosystem.

Yes, since this is a XIAOMI issue, until someone open a PR to fix it, each dev need to do a workaround, or someone open a PR and fix for everyone ^^

I saw the sample which has startCameraWithoutUri() but I don't quite get what is the difference of its CropImageContractOptions from startCameraWithUri() that will make the library's camera to launch.

One have URI and another do not have URI, if you don't provide the URI, the library will open a picker option

Thus I suggest to just make a dialog where the basic style is public either by setter or builder. Thanks

Feel free to drop the PR and we can discuss =D

Again can't access PickImageContractOptions I tried to manually import it import com.canhub.cropper.PickImageContractOptions; but it looks like it is not accessible or removed from the latest version. Can you check this one?

ArcherEmiya05 commented 2 years ago

Nvm it seems that one was just recently added at 3.3.6.

ArcherEmiya05 commented 2 years ago

I doubt Xiaomi and other problematic Chinese brand will fix this anytime soon, too bad we need to repeat the camera intent.

Canato commented 2 years ago

If possible please test

To test this changes implementation 'com.github.CanHub:Android-Image-Cropper:271-read-files-without-permission-38df1455d6-1'

All feedbacks at #280