facebook / fresco

An Android library for managing images and the memory they use.
https://frescolib.org/
MIT License
17.07k stars 3.75k forks source link

Failed resolution of: Landroid/graphics/ColorSpace #2638

Open KimiChiu opened 2 years ago

KimiChiu commented 2 years ago

Description

It worked fine before I updated my Android Studio to 2020.3.1. I just discovered that android.graphics.ColorSpace was introduced in Android API 26. So all the devices which are under Android 8 will throw this exception. But how could it work so great when I was using Android Studio 4.1.3 to build app bundle?

Reproduction

Use Android Studio to 2020.3.1 and the latest Gradle plugin, build app bundle, run on devices which are using Android 5, 6, 7.

Fatal Exception: java.lang.NoClassDefFoundError
Failed resolution of: Landroid/graphics/ColorSpace;
com.facebook.imageutils.ImageMetaData.getColorSpace (ImageMetaData.java:31)
com.facebook.imagepipeline.image.EncodedImage.readImageMetaData (EncodedImage.java:398)
com.facebook.imagepipeline.image.EncodedImage.internalParseMetaData (EncodedImage.java:363)
com.facebook.imagepipeline.image.EncodedImage.parseMetaData (EncodedImage.java:341)
com.facebook.imagepipeline.producers.NetworkFetchProducer.notifyConsumer (NetworkFetchProducer.java:187)
com.facebook.imagepipeline.producers.NetworkFetchProducer.maybeHandleIntermediateResult (NetworkFetchProducer.java:151)
com.facebook.imagepipeline.producers.NetworkFetchProducer.onResponse (NetworkFetchProducer.java:108)
com.facebook.imagepipeline.producers.NetworkFetchProducer$1.onResponse (NetworkFetchProducer.java:75)
com.facebook.imagepipeline.backends.okhttp3.OkHttpNetworkFetcher$2.onResponse (OkHttpNetworkFetcher.java:185)
okhttp3.internal.connection.RealCall$AsyncCall.run (RealCall.java:504)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1113)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:588)
java.lang.Thread.run (Thread.java:818)

The exception was threw by this method.

private ImageMetaData readImageMetaData() {
    InputStream inputStream = null;
    ImageMetaData metaData = null;
    try {
      inputStream = getInputStream();
      metaData = BitmapUtil.decodeDimensionsAndColorSpace(inputStream);
      mColorSpace = metaData.getColorSpace();
      Pair<Integer, Integer> dimensions = metaData.getDimensions();
      if (dimensions != null) {
        mWidth = dimensions.first;
        mHeight = dimensions.second;
      }
    } finally {
      if (inputStream != null) {
        try {
          inputStream.close();
        } catch (IOException e) {
          // Head in the sand
        }
      }
    }
    return metaData;
  }

But there was already a ColorSpace usage in this method and it did check the API level before using it. This method didn't throw runtime exception.

public static ImageMetaData decodeDimensionsAndColorSpace(InputStream is) {
    Preconditions.checkNotNull(is);
    ByteBuffer byteBuffer = DECODE_BUFFERS.acquire();
    if (byteBuffer == null) {
      byteBuffer = ByteBuffer.allocate(DECODE_BUFFER_SIZE);
    }
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    try {
      options.inTempStorage = byteBuffer.array();
      BitmapFactory.decodeStream(is, null, options);

      ColorSpace colorSpace = null;
      if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        colorSpace = options.outColorSpace;
      }
      return new ImageMetaData(options.outWidth, options.outHeight, colorSpace);
    } finally {
      DECODE_BUFFERS.release(byteBuffer);
    }
  }

Here are what I tried.

Gradle clean command.

Build -> Clean project.

Build -> Rebuild project.

Change buildToolsVersion to the latest.

Change androidx.appcompat:appcompat to 2.5.0.

Add multidex-config.txt and multidex-config.pro

But none of these worked.

Solution

Use Android Studio 4.1.3 to build app bundle.

Additional Information

tehutiscribe commented 2 years ago

I'm observing the same issue after upgrading to Gradle Plugin 7.0.3 and enabling minification in my app on Android 7.x and earlier.

Perhaps a change to R8 in AGP 7.X has over optimized code shrinking and is removing some upstream code path which prevented callers from accessing ColorSpace on earlier Android versions. 🤔

I was able to resolve the issue locally by forking the this repo and applying the following version guard check to EncodedImage#readImageMetaData:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
   mColorSpace = metaData.getColorSpace();
}

If the core team can comment, I'm happy to create a PR with this change.

tilda-bg commented 2 years ago

we have the same error

prakhar-parth commented 2 years ago

Put this piece of code in your proguard-rules.pro file :-

-keep public class com.facebook.imageutils.** {
   public *;
}

This will work like a charm.

stale[bot] commented 2 years ago

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "bug" or "enhancement" and I will leave it open. Thank you for your contributions.

whitipet commented 2 years ago

Option from @prakhar-parth is temporary. The core team should consider the option from @tehutiscribe

pvegh commented 2 years ago

Please release a hotfix version with this ASAP. It leads to crashes in production for many users.

geeknection commented 2 years ago

Put this piece of code in your proguard-rules.pro file :-

-keep public class com.facebook.imageutils.** {
   public *;
}

This will work like a charm.

Its works for me. React Native 0.68

prerakd commented 1 year ago

Facing this issue in react-native@0.69.12. Do we have a proper solution then one which is mentioned by @geeknection

vovan888 commented 9 months ago

This issue is still not resolved in the latest version