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流,但是为了省流量,做了一个一级缓存,下次访问的时候先从本地读取,没有的话再从网络上下下来。具体代码如下:
本博客部分代码摘自:android 播放网络或本地gif格式的动态图片 ,本人做了一下优化,如有不足或不正确的地方,望指明改正!
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格式的动态图片 ,本人做了一下优化,如有不足或不正确的地方,望指明改正!
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories