前言
本章将實作非常實用的功能——下載下傳線上視訊。涉及到多線程、線程更新ui等技術,還需思考産品的設計,如何将新加的功能更好的融入到現有的産品中,并不是簡單的加一個界面就行了,歡迎大家交流産品設計和技術細節實作!
聲明
歡迎轉載,但請保留文章原始出處:)
部落格園:http://www.cnblogs.com
農民伯伯: http://over140.cnblogs.com
系列
正文
一、目标
本章實作視訊下載下傳的功能
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuEzX5ITL20iMxAjMvwlNvwlMxAjMvwFM0EjclZ3bvwVbvN2Xzd2bsJmbj9CXt92YuM3ZvxmYuNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.png)
使用說明:進入線上視訊,點選播放時将彈出選擇框詢問播放還是下載下傳,點選下載下傳後進度條将在本地視訊頂部顯示。如果想邊看便下載下傳,請直接點選本地播放清單中正在下載下傳的視訊。
二、實作(部分主要實作代碼)
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:
四、vitamio公告
正式建立vitamio開發者聯盟qq群!群号為:246969281
注意:目前僅接受已經開發基于vitamio産品的開發者申請加入,申請理由請填寫産品的名詞和連結,擷取最新進展以及與vitamio作者直接交流機會!
結束
有bug不可怕,改了就行,大膽設計、放手寫代碼,謹慎處理已知細節,這樣的軟體才會越來越好。寫了一上午代碼,難免有出錯的地方,歡迎回報~
轉載:http://www.cnblogs.com/over140/archive/2012/06/29/2561244.html