1. 程式人生 > >Android自定義Movie播放網路gif圖片

Android自定義Movie播放網路gif圖片

之前看到過一些帖子播放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格式的動態圖片 ,本人做了一下優化,如有不足或不正確的地方,望指明改正!