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

Add support for displaying animated gif images on Image tag #1099

Closed
rclai opened this issue Nov 13, 2015 · 15 comments
Closed

Add support for displaying animated gif images on Image tag #1099

rclai opened this issue Nov 13, 2015 · 15 comments

Comments

@rclai
Copy link
Contributor

rclai commented Nov 13, 2015

On iOS at least, you have to do custom native stuff to get a GIF to actually animate, otherwise, it doesn't move.

Perhaps an attribute of animated="true" on the XML tag would be nice in addition with a programmatic option too.

It would also be really cool if it was 2-way-bindable as well, for "play and stop" functionality.

@rclai
Copy link
Contributor Author

rclai commented Nov 13, 2015

Actually, looks like on iOS at least (from this SO discussion), all the images need to be broken out into their frames. So the XML would probably need to look like this:

<Image duration="1" repeatCount="0">
  <Image.animationImages>
    <AnimationImage src="..." />
    <AnimationImage src="..." />
    <AnimationImage src="..." />
  <Image.animationImages>
</Image>

I'm basing that off of how you would do it in iOS, however, I'm not sure how it would look like for Android?

@bradmartin
Copy link
Contributor

👍

@enchev
Copy link
Contributor

enchev commented Feb 15, 2016

I know @bradmartin is cooking something here! :)

@bradmartin
Copy link
Contributor

This works for Android, iOS will be available in the coming weeks. If anyone is interested I have a few cocoapods in mind, just PM me for info.

https://www.npmjs.com/package/nativescript-gif

@bradmartin
Copy link
Contributor

Hoping to have the iOS side done this week 👍 just gotta put this into the plugin
iosgifs

@enchev
Copy link
Contributor

enchev commented Apr 13, 2016

Well done @bradmartin!

@bradmartin
Copy link
Contributor

Just published the plugin. https://www.npmjs.com/package/nativescript-gif

Only limitation is Android supports local .gif files right now. The library should work with remote .gif urls but I haven't been able to figure it out quite yet. Anyone wanting to contribute, that would be awesome.

This block here is where it needs to be implemented.

@enchev
Copy link
Contributor

enchev commented Apr 20, 2016

Hey @bradmartin,

Maybe you can use something like:

var bytes = r.content.raw.toByteArray();
var buffer = java.nio.ByteBuffer.wrap(bytes);

@bradmartin
Copy link
Contributor

@enchev I tried that and various other approaches which none have worked as I thought they would, which could be a problem with the library itself but I'm not a Java expert by any means to go debugging and figure out those issues without wasting too much time 😄. The author of the Android library did give me a snippet to try out, I converted it to JS and it worked fine but I had to change the StrictPolicy to allow the network request to run on the main thread. Very bad, I know, but wanted to see if it worked and it did.

Java Sample

String url = "https://media4.giphy.com/media/BgBf6pW9qOgQU/200.gif";
URLConnection urlConnection = new URL(url).openConnection();
urlConnection.connect();
final int contentLength = urlConnection.getContentLength();
ByteBuffer buffer = ByteBuffer.allocateDirect(contentLength);
ReadableByteChannel channel = Channels.newChannel(urlConnection.getInputStream());
while (buffer.remaining() > 0)
    channel.read(buffer);
channel.close();
GifDrawable drawable = new GifDrawable(buffer);

Translated to JS

 var url = new java.net.URL(this.src);
 var urlConnection = url.openConnection();
 urlConnection.connect();
 var contentLength = urlConnection.getContentLength();
 console.log('contentLength: ' + contentLength);
 var buffer = java.nio.ByteBuffer.allocateDirect(contentLength);
 console.log('buffer: ' + buffer);
 var channel = java.nio.channels.Channels.newChannel(urlConnection.getInputStream());
 console.log('channel: ' + channel);
 while (buffer.remaining() > 0) {
     channel.read(buffer);
 }
 channel.close();                
 console.log('channel close');
 this._drawable = new pl.droidsonroids.gif.GifDrawable(buffer);

Which will of course fail because that would make the request on the main thread which is blocked, so to just test that it was working I added this prior to the js block to make the request.

StrictMode change

 if (android.os.Build.VERSION.SDK_INT > 9) {
     var policy = new android.os.StrictMode.ThreadPolicy.Builder().permitAll().build();
     android.os.StrictMode.setThreadPolicy(policy);
 }

Once that change has been made the GifDrawable will be constructed using the buffer and it will work, but again, can't actual use this so I tried to do the same with the http module making the request and using the bytes returned but I can't get it to work.

Http Request Attempt

    http.request({ url: this.src, method: "GET" }).then(function(r) {

                    /***** Enchev suggestion - didn't work :(     *****/
                    // var bytes = r.content.raw.toByteArray();
                    // console.log('bytes: ' + bytes);
                    // var buffer = java.nio.ByteBuffer.wrap(bytes);
                    // console.log('buffer: ' + buffer);


                    /***** Attempt to use the Content-Length header, this part is okay  *****/                    
                    var contentLength;
                    for (var header in r.headers) {
                        if (header === "Content-Length") {
                            contentLength = r.headers[header];
                            break;
                        }
                    };

                    console.log('contentLength: ' + contentLength);

                    /***** The buffer is created    ******/                    
                    var buffer = java.nio.ByteBuffer.allocateDirect(contentLength);
                    console.log('buffer: ' + buffer);


                    // returns OutputStreamChannel --- PROBLEM HERE IS it returns an OutputStream 
                    // the Java sample code passed in urlConnection.getInputStream() which returns an Input stream and it works
                    // Need to get an input stream as the channel and the while loop should work and then the buffer should also work
                    // when passed to the GifDrawable
                    var channel = java.nio.channels.Channels.newChannel(r.content.raw); 
                    console.log('channel: ' + channel);

                    // NEED INPUT STREAM CHANNEL TO WORKING
                    while (buffer.remaining() > 0) {
                        channel.read(buffer);
                    }

                    channel.close();

                    this._drawable = new pl.droidsonroids.gif.GifDrawable(buffer);
                    console.log('this._drawable: ' + this._drawable);

                }, function (err) {
                    console.log(err);
                });

@bradmartin
Copy link
Contributor

You were right @enchev that worked, I just screwed up the TS 💣

@NathanaelA fixed up the code and I just published the update so now the plugin supports local and remote .gifs for Android and iOS.

https://www.npmjs.com/package/nativescript-gif

@enchev
Copy link
Contributor

enchev commented Apr 21, 2016

Great! :D I'm closing this issue!

@enchev enchev closed this as completed Apr 21, 2016
@dxshindeo
Copy link

but I had to change the StrictPolicy to allow the network request to run on the main thread. Very bad, I know, but wanted to see if it worked and it did.

Why is it bad?

@bradmartin
Copy link
Contributor

Been a long time since I worked on this. Trying to recall the android specifics but basically overriding that policy is a recipe for disaster and also running all network on main thread could lock up other running tasks if you had 10 gifs being pulled down. Or anything else really. Sorry I don't recall the specifics. Google for that policy and you'll find info from the android docs about it

@brunohenriquesk1
Copy link

brunohenriquesk1 commented Apr 3, 2017

How can I use a variable with the src? like

<Gif src={{url}} ></Gif>

@lock
Copy link

lock bot commented Aug 28, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked and limited conversation to collaborators Aug 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants