天天看點

使用Vitamio打造自己的Android萬能播放器(7)——線上播放(下載下傳視訊)

一、目标

    本章實作視訊下載下傳的功能

      

    使用說明:進入線上視訊,點選播放時将彈出選擇框詢問播放還是下載下傳,點選下載下傳後進度條将在本地視訊頂部顯示。如果想邊看便下載下傳,請直接點選本地播放清單中正在下載下傳的視訊。 二、實作(部分主要實作代碼)

    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) {

                        if (inputStream != null)

                            inputStream.close();

                }

                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.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();

            case FileDownloadHelper.MESSAGE_STOP://下載下傳結束

                FileBusiness.insertFile(getActivity(), p);

            case FileDownloadHelper.MESSAGE_ERROR:

                Toast.makeText(getActivity(), url, Toast.LENGTH_LONG).show();

            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() {

                            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:

繼續閱讀