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


    前言

      本章将实现非常实用的功能——下载在线视频。涉及到多线程、线程更新UI等技术,还需思考产品的设计,如何将新加的功能更好的融入到现有的产品中,并不是简单的加一个界面就行了,欢迎大家交流产品设计和技术细节实现!
     
    声明
      欢迎转载,但请保留文章原始出处:) 
        博客园:http://www.cnblogs.com
        农民伯伯: http://over140.cnblogs.com 
     
    系列

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

    正文
      一、目标

        本章实现视频下载的功能

          

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

      二、实现(部分主要实现代码)
        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不可怕,改了就行,大胆设计、放手写代码,谨慎处理已知细节,这样的软件才会越来越好。写了一上午代码,难免有出错的地方,欢迎反馈~
  • 相关阅读:
    Oracle SQL语句大全—查看表空间
    Class to disable copy and assign constructor
    在moss上自己总结了点小经验。。高手可以飘过 转贴
    在MOSS中直接嵌入ASP.NET Page zt
    Project Web Access 2007自定义FORM验证登录实现 zt
    SharePoint Portal Server 2003 中的单一登录 zt
    vs2008 开发 MOSS 顺序工作流
    VS2008开发MOSS工作流几个需要注意的地方
    向MOSS页面中添加服务器端代码的另外一种方式 zt
    状态机工作流的 SpecialPermissions
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4308017.html
Copyright © 2020-2023  润新知