版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZuoZuoShengHen/article/details/50249569
之前看到过一些帖子播放gif图片的,大概看过两种版本,一种是使用把gif解码,分为一帧一帧的播放,另一种就是直接播放gif图片。可以使用Movie类来播放,一种是使用框架,一个是android-gifview,另一个是android-gif-drawable,前者加载小的gif图片没问题,但是gif图片大了就OOM,后者据说是不支持Android5.0,使用到了jni,对内存做了一定优化,倒是不会出现OOM的问题,具体可参考
Android开源项目:GifView——Android显示GIF动画。但如果是Eclipse的话配置环境需要SDK最低是4.3的版本,因为本人的SDK版本是4.2的,所以决定使用Movie来播放。
Movie有三个方法去加载gif图片,分别是
Movie.decodestream(InputStream is);
Movie.decodeFile(String pathName);
Movie.decodeByteArray(byte[] data, int offset,int length);
要从网上显示gif图片,肯定需要gif的url,所以我在构造方法里添加了url的参数,之后先从本地读取gif图片,如果本地不存在,就从网络上先下载到本地,随后从本地中读取,当然你可以直接从网络上得到一个InputStream流,但是为了省流量,做了一个一级缓存,下次访问的时候先从本地读取,没有的话再从网络上下下来。具体代码如下:
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
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.graphics.Paint;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import cn.tedu.news.R;
public class GifView extends View {
private static final String TAG = GifView.class.getSimpleName();
private Movie mMovie;
private long mPlayMovieTime;
private String DOWNLOAD_ADDR = "";
private Context context;
private int mViewWidth;
private int mViewHeight;
private boolean isPlaying;
public GifView(Context context) {
super(context);
this.context = context;
readGifFormNet();
}
public GifView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
/**
* 设置gif图片的url,开始播放gif
* @param url
*/
public void setUrl(String url) {
DOWNLOAD_ADDR = url;
//先从本地读取,如果本地没有,在从网络上获取
mMovie = readGifFormLoacl();
if (mMovie == null) {
//先下载只本地
gifDownload();
readGifFormNet();
}
}
/**
* 从资源文件中读取gif图片
*/
public void readGifFormNative() {
InputStream in;
in = context.getResources().openRawResource(R.drawable.dfsd8);
mMovie = Movie.decodeStream(in);
}
/**
* 加载本地图片
*/
public Movie readGifFormLoacl() {
try {
File dir = context.getCacheDir().getAbsoluteFile();
String fileName = DOWNLOAD_ADDR.substring(
DOWNLOAD_ADDR.lastIndexOf("/"), DOWNLOAD_ADDR.length());
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, fileName);
return mMovie = Movie.decodeFile(file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 下载网络图片
*/
private void readGifFormNet() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
httpTest();
return null;
}
@Override
protected void onPostExecute(Void result) {
mHandler.sendEmptyMessage(0);
}
}.execute();
}
public void setPlaying(boolean flag) {
isPlaying = flag;
}
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
invalidate();
break;
default:
break;
}
super.handleMessage(msg);
}
};
/**
* 下载网络图片到本地
*/
public void gifDownload() {
new Thread() {
public void run() {
InputStream in = null;
FileOutputStream fos = null;
try {
URL url = new URL(DOWNLOAD_ADDR);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
int size = connection.getContentLength();
Log.e(TAG, "size = " + size);
in = connection.getInputStream();
File dir = context.getCacheDir().getAbsoluteFile();
String fileName = DOWNLOAD_ADDR.substring(
DOWNLOAD_ADDR.lastIndexOf("/"),
DOWNLOAD_ADDR.length());
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, fileName);
Log.d("info", "file->" + file.getAbsolutePath());
fos = new FileOutputStream(file);
int len = -1;
byte[] buffer = new byte[1024 * 8];
while ((len = in.read(buffer)) != -1) {
fos.write(buffer, 0, len);
fos.flush();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
}.start();
}
/**
* 下载网络图片
*/
private void httpTest() {
try {
URL url = new URL(DOWNLOAD_ADDR);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
// connection.setRequestMethod("GET");
int size = connection.getContentLength();
Log.e(TAG, "size = " + size);
InputStream in = connection.getInputStream();
byte[] array = streamToBytes(in);
mMovie = Movie.decodeByteArray(array, 0, array.length);
// 得到图片宽高
if (mMovie != null) {
mViewWidth = mMovie.width();
mViewHeight = mMovie.height();
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
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 onDraw(Canvas canvas) {
Paint p = new Paint();
p.setAntiAlias(true);
setLayerType(LAYER_TYPE_SOFTWARE, p);
//获取屏幕宽高,将gif图片宽或高铺满屏幕
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
if (mMovie != null) {
mViewWidth = mMovie.width();
mViewHeight = mMovie.height();
float x = 0;
float y = 0;
//float width = getWidth();
//float height = getHeight();
float width = metrics.widthPixels;
float height = metrics.heightPixels;
float saclex = (float) width / (float) mViewWidth;
float sacley = (float) height / (float) mViewHeight;
float sameRate = saclex > sacley ? sacley : saclex;
canvas.scale(sameRate, sameRate);
x = ((width - mViewWidth * sameRate) / 2) / (metrics.density);
y = ((height - mViewHeight * sameRate) / 2) / (sameRate);
if (isPlaying) {
long now = android.os.SystemClock.uptimeMillis();
if (mPlayMovieTime == 0) { // first time
mPlayMovieTime = now;
}
int dur = mMovie.duration();
if (dur == 0) {
dur = 1000;
}
int relTime = (int) ((now - mPlayMovieTime) % dur);
mMovie.setTime(relTime);
mMovie.draw(canvas, x, y);
// if ((now - mPlayMovieTime) > dur) {
// mPlayMovieTime = 0;
// isPlaying = false;
// }
} else {
mMovie.setTime(0);
mMovie.draw(canvas, x, y);
}
invalidate();
}
}
}
本博客部分代码摘自:android 播放网络或本地gif格式的动态图片 ,本人做了一下优化,如有不足或不正确的地方,望指明改正!