您的位置:首页 > 理论基础 > 计算机网络

Android自定义Movie播放网络gif图片

2015-12-10 14:38 585 查看
之前看到过一些帖子播放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格式的动态图片 ,本人做了一下优化,如有不足或不正确的地方,望指明改正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息