GIFs not animating in the Android version of my React Native app
Asked Answered
E

8

8

I am struggling to get my GIFs to animate on the Android version of my RN application. The iOS version is animating the looping GIFs as expected but I only see a stuck "single frame" image from the GIF on the Android device.

According to the debugging and RN-documentation it's required to add a few lines of implementation to the dependencies within the /android/app/build.gradle, but even after cleaning the gradle (running ./gradlew clean in the /android folder) and deleting the cache of the RN app (running react-native start --reset-cache in the project root folder), I do not see any difference in my application.

I have googled and tried a lot. Based on my debugging adventure, I have tried and double-checked these suggestions, that seems to work for others but it doesn't seem to work for me...

  • I have tried several versions of the fresco-libraries that seems to be required and I have also tried placing the lines in both the bottom as well as the top of the dependencies.
  • Some answers also suggest to add one or more lines of code to the android/app/proguard-rules.pro but this doesn't change anything either.
  • I use GIFs in different ways of my application but it always has width and height included to the style property on the <Image />.
  • I have tried with GIF-uris from different CDNs and domains.
  • Reinstalled the app on my test devices.
  • Closed and reopened my code editors.

I'm using the following versions:

  • Java: 11.0.12
  • React Native: 0.65
  • Android SDK: 30.0.2
  • npm: 6.14.4

This is my full /android/app/build.gradle:

apply plugin: "com.android.application"

import com.android.build.OutputFile


project.ext.react = [
    enableHermes: false,  // clean and rebuild if changing
]

apply from: "../../node_modules/react-native/react.gradle"


def enableSeparateBuildPerCPUArchitecture = false
def enableProguardInReleaseBuilds = false
def jscFlavor = 'org.webkit:android-jsc:+'
def enableHermes = project.ext.react.get("enableHermes", false);

android {
    ndkVersion rootProject.ext.ndkVersion

    compileSdkVersion rootProject.ext.compileSdkVersion

    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://reactnative.dev/docs/signed-apk-android.
            signingConfig signingConfigs.debug
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }

    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // https://developer.android.com/studio/build/configure-apk-splits.html
            // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
            def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        defaultConfig.versionCode * 1000 + versionCodes.get(abi)
            }

        }
    }
}

dependencies {

    implementation fileTree(dir: "libs", include: ["*.jar"])
    //noinspection GradleDynamicVersion
    implementation "com.facebook.react:react-native:+"  // From node_modules

    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"

    debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
      exclude group:'com.facebook.fbjni'
    }

    debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
        exclude group:'com.squareup.okhttp3', module:'okhttp'
    }

    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
    }

    if (enableHermes) {
        def hermesPath = "../../node_modules/hermes-engine/android/";
        debugImplementation files(hermesPath + "hermes-debug.aar")
        releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
        implementation jscFlavor
    }


    implementation project(':react-native-notifications')
    implementation 'com.google.firebase:firebase-core:16.0.0'
    implementation 'com.google.android.gms:play-services-ads:19.8.0'
    implementation "androidx.appcompat:appcompat:1.0.0"

    implementation 'com.facebook.fresco:fresco:2.4.0'
    implementation 'com.facebook.fresco:animated-gif:2.4.0'
    implementation 'com.facebook.fresco:webpsupport:2.4.0'
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

apply plugin: 'com.google.gms.google-services'

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

Let me know if I've missed something obvious. I am definitely more experienced in iOS-development, so it is very possible that I missed something :-)

Elvia answered 22/8, 2021 at 16:20 Comment(9)
Did I miss the part where you actually had the JSX rendering an image on screen? If not maybe add that into the question too.Judejudea
Have you tried disabling flipper? Is that something you can elect to turn off just to see if it's interfering?Judejudea
I know it is not an answer to the question, but instead of GIF, I use Lottie animations that are lightweight animations see more at: lottiefiles.comDislike
@Judejudea the JSX is not included because it's just a basic Image-component as described in my question and I use this in 50+ places in my app and they all work perfectly on iOS. This is an example: <Image style={{width: '100%', height: '100%'}} source={{uri: 'media4.giphy.com/media/8PdWdNWkVOlHJsleC7/…'}} />Elvia
@Dislike yeah, Lottie is great for animations but I'm looking for a way to show my animated GIFs :-)Elvia
have you tried "animated-gif:2.0.0" (version 2.0.0 to be specific). The later fresco versions seem to have issues with react native - github issueGuajardo
@Guajardo no luck with version 2.0.0 either..Elvia
Its highly likely that it's some configuration issue. Can you create a blank project that reproduces this issue? maybe you can create a copy of your project and strip all the private code to keep the existing configurations intactGuajardo
just updated from 0.64 to 0.65, move from animated-gif 2.0.0 to 2.6.0 and it fixed the gif issue.Metatherian
P
10

A easier fix would be using FastImage library which have Gif support build in with added benefits of caching and more

Purify answered 31/8, 2021 at 5:10 Comment(3)
Hi Muhammed, thank you for your suggestion. Have you experienced that FastImage could solve this specific issue. It would take a while to refactor my application for a new library like this, so I would like to be sure that this library does not just use the same React-Native-component (<Image>) as a base and then add new stuff on top :-)Elvia
It is not build upon ReactNative Image component. I am using it in my projects to display gifs. works well.Purify
Hi again Muhammed, I tried out the FastImage library and it works perfectly! It also solved another issue of mine, which was a quick white-flickering on <Image />s when rerendering screens on both iOS and Android. Thank you :-)Elvia
I
14

I had the same issue using react-native 0.66.3, and updating com.facebook.fresco:animated-gif to 2.6.0 in app/build.gradle worked for me

Inessive answered 23/11, 2021 at 14:57 Comment(3)
This Worked, Thanks mate 💯Abutting
Thank you. I spent days looking for this.Dreadful
This should be the accepted answer. Saved me!Ruble
P
10

A easier fix would be using FastImage library which have Gif support build in with added benefits of caching and more

Purify answered 31/8, 2021 at 5:10 Comment(3)
Hi Muhammed, thank you for your suggestion. Have you experienced that FastImage could solve this specific issue. It would take a while to refactor my application for a new library like this, so I would like to be sure that this library does not just use the same React-Native-component (<Image>) as a base and then add new stuff on top :-)Elvia
It is not build upon ReactNative Image component. I am using it in my projects to display gifs. works well.Purify
Hi again Muhammed, I tried out the FastImage library and it works perfectly! It also solved another issue of mine, which was a quick white-flickering on <Image />s when rerendering screens on both iOS and Android. Thank you :-)Elvia
L
2

GIF and WebP support on Android

When building your own native code, GIF and WebP are not supported by default on Android.

You will need to add some optional modules in android/app/build.gradle, depending on the needs of your app.

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

  // For animated GIF support
  implementation 'com.facebook.fresco:animated-gif:2.5.0'

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

  // For WebP support, without animations
  implementation 'com.facebook.fresco:webpsupport:2.5.0'
}

You can follow the official documentation Link

Lactary answered 9/5, 2022 at 7:12 Comment(0)
G
1

I myself had problems with GIF's on android and ended up moving over to animated webp's which google seems to embrace and even has their own conversion tools for. They've had android support for it for many years and seems to work much more consistantly. Might even work by changing the extension to webp instead of PNG?

https://frescolib.org/docs/webp-support.html

Gudren answered 31/8, 2021 at 5:11 Comment(1)
Hi, thank your for your suggestion. The content within my app is user-generated, so I cannot force the users to use specific file types because of a content legacy :-)Elvia
C
0

How do I display an animated gif in React Native?

add android/app/build.gradle

    // For animated GIF support
    compile 'com.facebook.fresco:animated-gif:1.+'
Christalchristalle answered 24/8, 2021 at 17:29 Comment(2)
Hi iyoda and welcome to Stackoverflow :-) As described in my question (and code) I have already added fresco:animated-gif in my build.gradle file. I also tested with versions like 1.0 and 1.3 without any luck.Elvia
I'm sorry. I didn't read it carefully. - @SimonDegnChristalchristalle
A
0

u just only need react-native-fast-image library..

<FastImage source={{ uri: img, // headers: { Authorization: 'someAuthToken' }, priority: FastImage.priority.normal, }} resizeMode={FastImage.resizeMode.cover} onError={() => console.log( 'image doest not exist or look like http:', ) } style={{ width: '100%', height: '100%',enter code here borderRadius: 10, }} />

Apograph answered 21/11, 2022 at 6:38 Comment(0)
M
0

I had this issue using React Native 0.73.8 and updating com.facebook.fresco:fresco and com.facebook.fresco:animated-gif to 3.1.3 in app/build.gradle fixed it

Mila answered 7/8 at 9:31 Comment(0)
R
0

Yes, @jljonnard is right, the office document shows when you are on RN 0.73.8, the animate lib is 2.5.0. That's wrong, the working version is 3.1.3 which RN is 0.74.*, bad document... https://reactnative.dev/docs/0.73/image

Rhatany answered 19/9 at 7:11 Comment(1)
I just encountered this issue upgrading to RN 0.75.3 and it appears 'com.facebook.fresco:animated-gif:3.2.0' is now required. The RN documentation is still out of date.Hobnailed

© 2022 - 2024 — McMap. All rights reserved.