- We cannot access Internet in main thread, such that we have to implement a background thread to load the gif from Internet.
- Once loaded, we have to ask Android system to re-layout with updated graph.
- In the example code, dummy delay is added to simulate network delay.
- Both decodeStream(InputStream) and decodeByteArray(InputStream) are implemented, you can choice it by setting DECODE_STREAM true or false.
- It can be noted that textViewInfo is filled with 0, 0 x 0; because the GIF is not loaded when onCreate() called.
- uses-permission android:name="android.permission.INTERNET" is needed in AndroidManifest.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.androidgif.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android_er" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff000090"
android:orientation="vertical"
android:padding="5dp" >
<com.example.androidgif.GifView
android:id="@+id/gifview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/textinfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="info..." />
</LinearLayout>
GifView.java
package com.example.androidgif;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Toast;
public class GifView extends View {
//Set true to use decodeStream
//Set false to use decodeByteArray
private static final boolean DECODE_STREAM = true;
private InputStream gifInputStream;
private Movie gifMovie;
private int movieWidth, movieHeight;
private long movieDuration;
private long mMovieStart;
final static String gifAddr = "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6myuJnVNIFw_fX5kZ3ru5B_xtomsmaUZsq2IWaFIKDcy_88cRvwaX9sn8x2rIBWsrOezV9w3BJHcwG2mSq3VLZB0eXCWb2so3znRvZeF3fpK3h0uAZy9WX5S7afEJYvEPl4AJln99dJI/s1600/android_er.gif";
public GifView(Context context) {
super(context);
init(context);
}
public GifView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GifView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(final Context context){
setFocusable(true);
gifMovie = null;
movieWidth = 0;
movieHeight = 0;
movieDuration = 0;
Thread threadLoadGif = new Thread(new Runnable(){
@Override
public void run() {
try {
URL gifURL = new URL(gifAddr);
HttpURLConnection connection = (HttpURLConnection)gifURL.openConnection();
gifInputStream = connection.getInputStream();
//Insert dummy sleep
//to simulate network delay
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(DECODE_STREAM){
gifMovie = Movie.decodeStream(gifInputStream);
}else{
byte[] array = streamToBytes(gifInputStream);
gifMovie = Movie.decodeByteArray(array, 0, array.length);
}
movieWidth = gifMovie.width();
movieHeight = gifMovie.height();
movieDuration = gifMovie.duration();
((MainActivity)context).runOnUiThread(new Runnable(){
@Override
public void run() {
//request re-draw layout
invalidate();
requestLayout();
Toast.makeText(context,
movieWidth + " x " + movieHeight + "\n"
+ movieDuration,
Toast.LENGTH_LONG).show();
}});
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}});
threadLoadGif.start();
}
private static byte[] streamToBytes(InputStream is) {
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int len;
try {
while ((len = is.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}
} catch (java.io.IOException e) {
}
return os.toByteArray();
}
@Override
protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
setMeasuredDimension(movieWidth, movieHeight);
}
public int getMovieWidth(){
return movieWidth;
}
public int getMovieHeight(){
return movieHeight;
}
public long getMovieDuration(){
return movieDuration;
}
@Override
protected void onDraw(Canvas canvas) {
long now = android.os.SystemClock.uptimeMillis();
if (mMovieStart == 0) { // first time
mMovieStart = now;
}
if (gifMovie != null) {
int dur = gifMovie.duration();
if (dur == 0) {
dur = 1000;
}
int relTime = (int)((now - mMovieStart) % dur);
gifMovie.setTime(relTime);
gifMovie.draw(canvas, 0, 0);
invalidate();
}
}
}
Other files, MainActivity.java and AndroidManifest.xml to turn OFF hardwareAccelerated, refer to the post "Play animated GIF using android.graphics.Movie, with Movie.decodeStream(InputStream)".
(Remark: to load from Internet, uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
Download the files.
Another example of playing new Google animated GIF, load from Internet.
hi while using above code..in my project image shows blue view..can u help me how to reslove this issue
ReplyDeleteThanking you
hello PRoV,
ReplyDeleteI cannot commit, but you can send me the link of your gif, I try to see if any reason.
What device you test on?
how to assign the url from the main activity.
ReplyDeletethanx sir My Apps is Succesfull by the your side.
ReplyDelete