React-native: Unable to use GIF or WebP in a release apk, Fresco imagepipeline is stripped by ProGuard

Created on 25 May 2016  路  13Comments  路  Source: facebook/react-native

If we build an apk in release with ProGuard enabled, when we load a scene that include a GIF or WebP image from the Image component, the application will crash with the following error :

java.lang.UnsatisfiedLinkError: JNI_ERR returned from JNI_OnLoad in "/data/app/com.imagepipeline-1/lib/x86/libgifimage.so"

Tested with [email protected].

Steps to reproduce

import { Image } from 'react-native';

export default function ImagePipeline() {
  return (
    <Image
      style={{ flex: 1 }}
      source={{ uri: 'https://media.giphy.com/media/GRld0uPxi1V1C/giphy.gif' }}
      resizeMode={'cover'}
    />
  );
}
  1. Be sure you're using a GIF or WebP icon with the Image component.
  2. Enable ProGuard in release builds. In android/app/build.gradle def enableProguardInReleaseBuilds = true
  3. Build your application in release.
  4. Open the scene that contains the GIF or WebP.
  5. Enjoy the crash.

    Proposed solution

Fresco documentation recommends the following ProGuard configuration :

# Keep our interfaces so they can be used by other ProGuard rules.
# See http://sourceforge.net/p/proguard/bugs/466/
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip

# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
    @com.facebook.common.internal.DoNotStrip *;
}

# Keep native methods
-keepclassmembers class * {
    native <methods>;
}

-dontwarn okio.**
-dontwarn com.squareup.okhttp.**
-dontwarn javax.annotation.**
-dontwarn com.android.volley.toolbox.**

So I tested this by adding it to the React Native proguard file like this :

 # React Native

 # Keep our interfaces so they can be used by other ProGuard rules.
 # See http://sourceforge.net/p/proguard/bugs/466/
 -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
 -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
+-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip

 # Do not strip any method/class that is annotated with @DoNotStrip
 -keep @com.facebook.proguard.annotations.DoNotStrip class *
+-keep @com.facebook.common.internal.DoNotStrip class *
 -keepclassmembers class * {
     @com.facebook.proguard.annotations.DoNotStrip *;
+    @com.facebook.common.internal.DoNotStrip *;
 }

I built the apk and everything worked fine.

An another solution would be to add this line to the proguard :

-keep class com.facebook.imagepipeline.** { *; }

I'll do the pull request, but before that I just need your opinion.

Do you think this could have side effects?
Do you prefer a method?
Any other ideas?

cc @AndrewJack, @mkonicek, @janicduplessis

Ran Commands Locked

Most helpful comment

@charpeni The fresco dependencies have been split, I missed that when upgrading.

We either need to add a selection of these dependencies to the react-native library or allow users to add the gif/webp support themselves.

  // If your app supports Android versions before Ice Cream Sandwich (API level 14)
  compile 'com.facebook.fresco:animated-base-support:0.10.0'

  // For animated GIF support
  compile 'com.facebook.fresco:animated-gif:0.10.0'

  // For WebP support, including animated WebP
  compile 'com.facebook.fresco:animated-webp:0.10.0'
  compile 'com.facebook.fresco:webpsupport:0.10.0'

  // For WebP support, without animations
  compile 'com.facebook.fresco:webpsupport:0.10.0'

I'll investigate further.

cc @bestander

All 13 comments

@facebook-github-bot label Android

The first solution seems a bit better since it might avoid similar problems in the future.

@AndrewJack I tested to display a GIF with [email protected], it doesn't work since Fresco has been updated. (Without ProGuard)

final_failed @ onFailure: failure: java.lang.NullPointerException: Attempt to invoke interface method 'com.facebook.imagepipeline.image.CloseableImage com.facebook.imagepipeline.animated.factory.AnimatedImageFactory.decodeGif(com.facebook.imagepipeline.image.EncodedImage, com.facebook.imagepipeline.common.ImageDecodeOptions, android.graphics.Bitmap$Config)' on a null object reference

@charpeni The fresco dependencies have been split, I missed that when upgrading.

We either need to add a selection of these dependencies to the react-native library or allow users to add the gif/webp support themselves.

  // If your app supports Android versions before Ice Cream Sandwich (API level 14)
  compile 'com.facebook.fresco:animated-base-support:0.10.0'

  // For animated GIF support
  compile 'com.facebook.fresco:animated-gif:0.10.0'

  // For WebP support, including animated WebP
  compile 'com.facebook.fresco:animated-webp:0.10.0'
  compile 'com.facebook.fresco:webpsupport:0.10.0'

  // For WebP support, without animations
  compile 'com.facebook.fresco:webpsupport:0.10.0'

I'll investigate further.

cc @bestander

It probably would not hurt to add gif/webp libs to RN because FB has all those libraries internally anyway.
Although it would be better to make users decide if they want the feature or not.
The leaner core is the faster builds are after all.

After adding compile 'com.facebook.fresco:animated-gif:0.10.0' to gradle file and rebuilding,
animated gifs <Image> wrapped in <Text> keep still, while those out of <Text> work fine.

react-natve @0.27.2

<View>
  <Text>
    <Text>Inline animated gif --> </Text>
    <Image
      style={{width: 20, height: 20}}
      source={{uri: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/5c/huanglianwx_org.gif'}}/>
  </Text>
  <Image
    style={{width: 20, height: 20}}
    source={{uri: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/5c/huanglianwx_org.gif'}}/>
</View>

@AndrewJack @janicduplessis

Another bug on iOS:
After pressing home key and then went back to the App, all the gif images disappeared. And came back after the component was re-rendered.

ios_gif

First, let me say thanks to everyone on this ticket. You saved me a headache! I just ran into this problem.

@bestander et al. I agree it would be nice to add the libs.

1, easy for those of us upgrading to expect continued support of what we've put in various projects.
2, I remember being impressed when I saw gifs work in RN.
3, The functionality between mobile and web is nicely bridged by RN, keeping so with gif seems aligned.

Thanks again!

@mdluo Another bug on iOS: After pressing home key and then went back to the App,all the gif images disappeared. do you know reason?

@mdluo @RongjieChen It will be fixed by #7612.

Thank you all, I will close this issue and submit a pull request to ensure the best experience with Fresco to the React Native developers.

Hi,

I had the GIF support issue now it's working in react native android now I want to know how can I make GIF image corner rounded I tried 'borderRadius: 10' it's working on other image format PNG or JPG but it's not working with GIF images.

@NitishAgrawal Can a workaround be that you wrap the image in a View and set borderRadius: 10 and overflow: 'hidden' on that?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

lazywei picture lazywei  路  3Comments

madwed picture madwed  路  3Comments

jlongster picture jlongster  路  3Comments

axelg12 picture axelg12  路  3Comments