使用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.pswp.cn/news/259338.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259338.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259338.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

生成0到1之間隨機數的C代碼

#include <stdlib.h>#include <stdio.h>#include <time.h>int main(){srand((unsigned)time(NULL));int i;double r;for(i0;i<50;i){r(float)rand()/RAND_MAX; printf("%f\n",r);}return 0;}

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…

《G檔案》中關于游戲程序設計的文章

剛拿到前導的《G檔案》&#xff0c;發現了主程劉剛的文章&#xff0c;是目前我所見 到的關于游戲編程的最好的一篇&#xff0c;與大家共享。轉載&#xff1a;http://www.360doc.cn/article/2778_53476.html PC游戲編程 目錄 1 游戲程序理論 1.1 技術基礎 1.2 游戲底層 1.3 編…

shell筆記

system 磁盤 磁盤空間使用情況df查看文件或目錄大小du掛載usb sudo fdisk -l # Find what the drive is called e.g. /dev/sdb1 sudo mkdir /media/usb sudo mount /dev/sdb1 /media/usb sudo umount /media/usb# umount sudo umount /media/usb utils awk 打印文件的第一列(域…

html5編輯文檔,HTML5帶各種趣味動畫的文本編輯器

CSS語言&#xff1a;CSSSCSS確定body {background-color: #eee;}html,body {margin: 0px;height: 100%;overflow: hidden;}.toolbar {width: 100%;background: #fff;padding: 4px 10px;}.characters {display: inline-block;margin-right: 20px;vertical-align: top;}.characte…

社會轉型

轉載&#xff0c;版權由作者所有。 常常在政府工作報告中看到關于“社會轉型期”的說法&#xff0c;不是太明白&#xff0c;在百度里找了找&#xff0c;果然有不少&#xff0c;摘抄下來&#xff0c;做為學習資料用&#xff1a; 一是指體制轉型&#xff0c;即從計劃經濟體制向市…

在WPF中處理Windows消息

在Winform中 處理Windows消息通過重寫WndProc方法 在WPF中 使用的是System.Windows. Sytem.Windows.Controls等名字空間&#xff0c;沒有WndProc函數 WPF中處理消息首先要獲取窗口句柄&#xff0c;創建HwndSource對象 通過HwndSource對象添加消息處理回調函數。 此外 WPF中沒有…

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…

C# 委托:把方法組合到一個數組中使用

C# 委托&#xff1a;把方法組合到一個數組中使用 using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace ConsoleApplication1 {class MathOperations{public static double MultiplyByTwo(double value){return value * 2;}public…

上傳Text文檔并轉換為PDF

今天在ASP.NET MVC環境中學習一些PDF相關的知識&#xff0c;想法是上傳文件成功時&#xff0c;并把文件轉換為PDF文檔。 打開你的專案&#xff0c;運行NuGet包管理器&#xff0c;下載一個叫iTextSharp的東東&#xff1a;點擊Install&#xff0c;按鈕提示確認安裝&#xff0c;成…

某著名公司2015暑期實習招聘試題及相關內容復習

1.&#xff09;輸出下面的結果<pre name"code" class"cpp">#include <iostream> using namespace std;int main(int argc, char *argv[]) {int **a[5][4];int *b[5][4];int *c[5];int d[5][4];char *e"helloworld";char g[]"01…

遞歸函數(九):最小不動點定理

遞歸函數&#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; …

PhotoShop

前景色填充&#xff1a;Altdelete 背景色填充&#xff1a;Ctrldelete 切換前景/背景色&#xff1a;X 鍵 接按d 是默認的黑色和白色轉載于:https://www.cnblogs.com/xingfuzzhd/p/3358156.html

python 循環技巧

原文地址&#xff1a;http://docs.pythontab.com/python/python3.4/datastructures.html#tut-tuples 在字典中循環時&#xff0c;關鍵字和對應的值可以使用 iteritems() 方法同時解讀出來。 knights {gallahad: the pure, robin: the brave}for k,v in knights.items():print(…

C++內存管理詳解

C內存管理詳解 轉載&#xff1a;http://blog.csdn.net/yingxunren/article/details/4344933 偉大的Bill Gates 曾經失言&#xff1a;   640K ought to be enough for everybody — Bill Gates 1981   程序員們經常編寫內存管理程序&#xff0c;往往提心吊膽。如果不想觸…