使用Vitamio打造自己的Android万能播放器(7)——在线播放(下载视频)

前言

本章将实现非常实用的功能——下载在线视频。涉及到多线程、线程更新UI等技术,还需思考产品的设计,如何将新加的功能更好的融入到现有的产品中,并不是简单的加一个界面就行了,欢迎大家交流产品设计和技术细节实现!
声明
欢迎转载,但请保留文章原始出处:) 
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com 
系列
1、使用Vitamio打造自己的Android万能播放器(1)——准备
2、使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放
3、使用Vitamio打造自己的Android万能播放器(3)——本地播放(主界面、视频列表)

  4、使用Vitamio打造自己的Android万能播放器(4)——本地播放(快捷搜索、数据存储)
  5、使用Vitamio打造自己的Android万能播放器(5)——在线播放(播放优酷视频)

6、使用Vitamio打造自己的Android万能播放器(6)——在线播放(播放列表)

 

正文
一、目标

    本章实现视频下载的功能

      

    使用说明:进入在线视频,点击播放时将弹出选择框询问播放还是下载,点击下载后进度条将在本地视频顶部显示。如果想边看便下载,请直接点击本地播放列表中正在下载的视频。

 

二、实现(部分主要实现代码)
FileDownloadHelper
复制代码
public class FileDownloadHelper {
    private static final String TAG = "FileDownloadHelper";
    /** 线程池 */
    private ThreadPool mPool = new ThreadPool();
    /** 开始下载 */
    public static final int MESSAGE_START = 0;
    /** 更新进度 */
    public static final int MESSAGE_PROGRESS = 1;
    /** 下载结束 */
    public static final int MESSAGE_STOP = 2;
    /** 下载出错 */
    public static final int MESSAGE_ERROR = 3;
    /** 中途终止 */
    private volatile boolean mIsStop = false;
    private Handler mHandler;
    public volatile HashMap<String, String> mDownloadUrls = new HashMap<String, String>();

    public FileDownloadHelper(Handler handler) {
        if (handler == null)
            throw new IllegalArgumentException("handler不能为空!");

        this.mHandler = handler;
    }

    public void stopALl() {
        mIsStop = true;
        mPool.stop();
    }

    public void newDownloadFile(final String url) {
        newDownloadFile(url, Environment.getExternalStorageDirectory() + "/" + FileUtils.getUrlFileName(url));
    }

    /**
     * 下载一个新的文件
     * 
     * @param url
     * @param savePath
     */
    public void newDownloadFile(final String url, final String savePath) {
        if (mDownloadUrls.containsKey(url))
            return;
        else
            mDownloadUrls.put(url, savePath);
        mPool.start(new Runnable() {

            @Override
            public void run() {
                mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_START, url));
                HttpClient client = new DefaultHttpClient();
                HttpGet get = new HttpGet(url);
                InputStream inputStream = null;
                FileOutputStream outputStream = null;
                try {
                    HttpResponse response = client.execute(get);
                    HttpEntity entity = response.getEntity();
                    final int size = (int) entity.getContentLength();
                    inputStream = entity.getContent();
                    if (size > 0 && inputStream != null) {
                        outputStream = new FileOutputStream(savePath);
                        int ch = -1;
                        byte[] buf = new byte[1024];
                        //每秒更新一次进度
                        new Timer().schedule(new TimerTask() {

                            @Override
                            public void run() {
                                try {
                                    FileInputStream fis = new FileInputStream(new File(savePath));
                                    int downloadedSize = fis.available();
                                    if (downloadedSize >= size)
                                        cancel();
                                    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_PROGRESS, downloadedSize, size, url));
                                } catch (Exception e) {

                                }
                            }
                        }, 50, 1000);

                        while ((ch = inputStream.read(buf)) != -1 && !mIsStop) {
                            outputStream.write(buf, 0, ch);
                        }
                        outputStream.flush();
                    }
                } catch (Exception e) {
                    Log.e(TAG, e.getMessage(), e);
                    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ERROR, url + ":" + e.getMessage()));
                } finally {
                    try {
                        if (outputStream != null)
                            outputStream.close();
                    } catch (IOException ex) {
                    }
                    try {
                        if (inputStream != null)
                            inputStream.close();
                    } catch (IOException ex) {
                    }
                }
                mDownloadUrls.remove(url);
                mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_STOP, url));
            }
        });
    }
复制代码

    代码说明:

a. ThreadPool是线程池,请参照项目代码。

      b. 这里使用了Time定时来刷进度,而没有直接在write数据时更新进度,这样的原因时每秒write较高,更新UI过于频繁,可能导致超时等问题。

    Handle

复制代码
    public Handler mDownloadHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            PFile p;
            String url = msg.obj.toString();
            switch (msg.what) {
            case FileDownloadHelper.MESSAGE_START://开始下载
                p = new PFile();
                p.path = mParent.mFileDownload.mDownloadUrls.get(url);
                p.title = new File(p.path).getName();
                p.status = 0;
                p.file_size = 0;
                if (mDownloadAdapter == null) {
                    mDownloadAdapter = new FileAdapter(getActivity(), new ArrayList<PFile>());
                    mDownloadAdapter.add(p, url);
                    mTempListView.setAdapter(mDownloadAdapter);
                    mTempListView.setVisibility(View.VISIBLE);
                } else {
                    mDownloadAdapter.add(p, url);
                    mDownloadAdapter.notifyDataSetChanged();
                }
                break;
            case FileDownloadHelper.MESSAGE_PROGRESS://正在下载
                p = mDownloadAdapter.getItem(url);
                p.temp_file_size = msg.arg1;
                p.file_size = msg.arg2;
                int status = (int) ((msg.arg1 * 1.0 / msg.arg2) * 10);
                if (status > 10)
                    status = 10;
                p.status = status;
                mDownloadAdapter.notifyDataSetChanged();
                break;
            case FileDownloadHelper.MESSAGE_STOP://下载结束
                p = mDownloadAdapter.getItem(url);
                FileBusiness.insertFile(getActivity(), p);
                break;
            case FileDownloadHelper.MESSAGE_ERROR:
                Toast.makeText(getActivity(), url, Toast.LENGTH_LONG).show();
                break;
            }
            super.handleMessage(msg);
        }
复制代码

    }; 

    代码说明:

a. mTempListView是新增的,默认是隐藏,请参见项目代码layout部分。

      b. 下载流程:开始(显示mTempListView) -> 正在下载(更新进度图片和大小)  -> 完成(入裤)

    Dialog

复制代码
                if (FileUtils.isVideoOrAudio(url)) {
                    Dialog dialog = new AlertDialog.Builder(getActivity()).setIcon(android.R.drawable.btn_star).setTitle(" 播放/下载").setMessage(url).setPositiveButton("播放", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(getActivity(), VideoPlayerActivity.class);
                            intent.putExtra("path", url);
                            startActivity(intent);
                        }
                    }).setNeutralButton("下载", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            MainFragmentActivity activity = (MainFragmentActivity) getActivity();
                            activity.mFileDownload.newDownloadFile(url);
                            Toast.makeText(getActivity(), " 正在下载 .." + FileUtils.getUrlFileName(url) + " ,可从本地视频查看进 度!", Toast.LENGTH_LONG).show();
                        }
                    }).setNegativeButton("取消", null).create();
                    dialog.show();
                    return true;
复制代码

                } 

 

三、下载

    至本章节往后,代码均不再提供下载,请移步Google Code:
    http://code.google.com/p/android-oplayer

 

  四、Vitamio公告

      正式建立Vitamio开发者联盟QQ群!群号为:246969281

      注意:目前仅接受已经开发基于Vitamio产品的开发者申请加入,申请理由请填写产品的名词和链接,获取最新进展以及与Vitamio作者直接交流机会!

 

结束
有BUG不可怕,改了就行,大胆设计、放手写代码,谨慎处理已知细节,这样的软件才会越来越好。写了一上午代码,难免有出错的地方,欢迎反馈~

转载于:https://www.cnblogs.com/Free-Thinker/p/4308017.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259338.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML声明文档类型后样式出错,doctype如何声明

如何doctype声明&#xff0c;新增的结构元素和功能元素HTML5已形成了最终的标准&#xff0c;概括来讲&#xff0c;它主要是关于图像&#xff0c;位置&#xff0c;存储&#xff0c;多任务等功能的增加。 新增的元素有绘画 canvas &#xff0c;用于媒介回放的 video 和 audio 元素…

Error-Project facet Java version 1.8 is not supported

最近导入最新的Strtus2.5.10.1 Demo时出现了这个错误 解决方案如下&#xff1a; 选中工程——右键——Properties 然后依次展开找到如图所示内容&#xff0c;将1.8改成1.7即可。 原因&#xff1a;工程默认配置是1.8&#xff0c;而本地环境JDK版本为1.7&#xff0c;两则不匹配造…

6.2

转载于:https://www.cnblogs.com/tutuaixiaomei/p/3354356.html

Tomcat全攻略

内容&#xff1a; 一&#xff1a;简单介绍二&#xff1a;安装及配置三&#xff1a;应用四&#xff1a;综述參考资料关于作者宗 锋西北大学计算机系硕士2001 年 12 月 随着java的流行&#xff0c;其在web上的应用也越来越广&#xff0c;tomcat作为一个开源的servlet容器&#xf…

Android Material风格的应用(三)--DrawerLayout

添加抽屉导航 Android Material风格的应用(一)--AppBar TabLayoutAndroid Material风格的应用(二)--RecyclerViewAndroid Material风格的应用(三)--DrawerLayoutAndroid Material风格的应用(四)--FloatActionButtonAndroid Material风格的应用(五)--CollapsingToolbar DrawerLa…

html5 数据缓存,HTML5: 本地缓存

HTML5 提供了两种在客户端存储数据的新对象&#xff1a;localStorage&#xff1a;没有时间限制的数据存储&#xff0c;在同一个浏览器中&#xff0c;只要没被手动清理&#xff0c;第二天、第二周或下一年之后&#xff0c;数据依然可用。sessionStorage&#xff1a;针对一个 ses…

上传Text文档并转换为PDF

今天在ASP.NET MVC环境中学习一些PDF相关的知识&#xff0c;想法是上传文件成功时&#xff0c;并把文件转换为PDF文档。 打开你的专案&#xff0c;运行NuGet包管理器&#xff0c;下载一个叫iTextSharp的东东&#xff1a;点击Install&#xff0c;按钮提示确认安装&#xff0c;成…

递归函数(九):最小不动点定理

递归函数&#xff08;一&#xff09;&#xff1a;开篇递归函数&#xff08;二&#xff09;&#xff1a;编写递归函数的思路和技巧递归函数&#xff08;三&#xff09;&#xff1a;归纳原理递归函数&#xff08;四&#xff09;&#xff1a;全函数与计算的可终止性递归函数&#…

html中单选框颜色怎么改,如何更改单选按钮的颜色?

侃侃无极一种快速的解决方法是使用来覆盖单选按钮的输入样式:after&#xff0c;但是创建自己的自定义工具箱可能是更好的做法。 input[typeradio]:after { width: 15px; height: 15px; border-radius: 15px; top: -2px; left: -1px; …

如何先执行input (checkbox,radio)再执行函数

2019独角兽企业重金招聘Python工程师标准>>> 遇到一个问题&#xff0c;当input type"checkbox"点击时&#xff0c;没有立即执行勾选或去勾&#xff0c;而是先执行函数&#xff0c;如下代码 $(".sidebar_cart .cart_list ul").on("click&qu…

Linux服务器上监控网络带宽的18个常用命令

本文介绍了一些可以用来监控网络使用情况的Linux命令行工具。这些工具可以监控通过网络接口传输的数据&#xff0c;并测量目前哪些数据所传输的速度。入站流量和出站流量分开来显示。 作者&#xff1a;布加迪编译来源&#xff1a;51CTO.com|2014-04-11 10:10移动端收藏分享【51…

[转]Windows Phone 7程序设计”完全版电子书可以免费下载了

本文转自&#xff1a;http://www.cnblogs.com/salam/archive/2010/10/29/1864246.html 现在学习Windows Phone 7开发资料十分有限&#xff0c;除了MSDN的官方开发文档外和一些博客外&#xff0c;几无其他的学习渠道。幸运地是美国的资深程序员兼作家Charles Petzold为大家免费放…

linux-redhat替换yum网络源为centos网络源

2019独角兽企业重金招聘Python工程师标准>>> 1.为什么要替换 redhat系统使用yum命令安装软件时会出现This system is not registered with RHN. RHN support will be disabled. 原因是redhat的yum安装软件需要注册&#xff0c;是收费的。而centos的yum源是免费的。这…

计算机如何打开无线网络适配器,win7系统下网络适配器打不开怎么解决

通常情况下我们的电脑中都会有一个网络适配器&#xff0c;这是计算机联网的设备&#xff0c;不过最近有深度技术win7旗舰版系统用户却遇到了网络适配器打不开的情况&#xff0c;该怎么办呢&#xff0c;接下来系统城小编就给大家分享一下win7系统下网络适配器打不开的具体解决方…

【Intellij Idea】设置JDK

1&#xff0c;File-->Project Structure 说明&#xff1a;可以设置整个工程的JDK&#xff0c;也设置每个modules的JDK,但是一般整个工程的JDK. 2&#xff0c;或者通过快捷键&#xff1a;ctrlaltshifts 转载于:https://www.cnblogs.com/august-shi/p/6655469.html

绘图用计算机配置要求,绘图笔记本电脑基本配置要求 绘图笔记本推荐

现在很多工业图、工程图都需要用电脑来话&#xff0c;比如CAD、PS、三维画图这些软件对电脑的配置要求还是比较高的&#xff0c;还有一些对色彩要求高的动画软件&#xff0c;那就更加需要配置了&#xff0c;下面小编就来简单说说绘图笔记本电脑最基本的配置要求以及绘图笔记本推…

计算机无法正常更新,无法完成更新正在撤销更改请不要关闭你的计算机如何修复...

我们电脑开机的时候可能会遇到各种问题&#xff0c;比如就有用户发现电脑开机的时候&#xff0c;一直提示无法完成更新正在撤销更改请不要关闭你的计算机&#xff0c;等待了很长时间也进不去系统&#xff0c;遇到这样的问题该怎么办呢&#xff1f;不用担心小编给大家支招&#…

自媒体和计算机相关吗,做自媒体,台式电脑跟笔记本电脑用哪个好呢?

四阿哥fly回答数&#xff1a;143 | 被采纳数&#xff1a;162019-06-29 12:16:21作为去年折腾了一年自媒体&#xff0c;各种情况遇到过&#xff0c;分享下台式电脑和笔记本到底哪个好&#xff1f;好在哪里&#xff1f;如果真的要选择&#xff0c;个人还是推荐用台式比较好。工…

React进阶—性能优化

React性能优化思路 软件的性能优化思路就像生活中去看病&#xff0c;大致是这样的&#xff1a; 使用工具来分析性能瓶颈&#xff08;找病根&#xff09;尝试使用优化技巧解决这些问题&#xff08;服药&#xff09;使用工具测试性能是否确实有提升&#xff08;疗效确认&#xff…

Supervised Descent Method and its Applications to Face Alignment

广播说明&#xff1a; 进入深度学习时代&#xff0c;如下的方法已经失去可比性&#xff0c;且我们的代码实现地很粗糙&#xff0c;如果坚持要用&#xff0c;推荐如下代码 https://github.com/wanglin193/SupervisedDescentMethod &#xff08;看起来作者对sdm实现的不错&…