Android自定義Movie播放網路gif圖片
阿新 • • 發佈:2018-12-15
之前看到過一些帖子播放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格式的動態圖片 ,本人做了一下優化,如有不足或不正確的地方,望指明改正!