Android實(shí)現(xiàn)多線程斷點(diǎn)下載的方法
本文實(shí)例講述了Android實(shí)現(xiàn)多線程斷點(diǎn)下載的方法。分享給大家供大家參考。具體實(shí)現(xiàn)方法如下:
package cn.itcast.download; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import cn.itcast.mutiledownload.StreamTool; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class MutiledownloadActivity extends Activity implements OnClickListener { private ProgressBar pb; private Button bt; private TextView tv; private EditText et; boolean flag = true; boolean stopflag = false; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { pb.setProgress(total); int max = pb.getMax(); if (total >= (max - 1)) { total = max; flag = false; } int result = total * 100 / max; tv.setText("當(dāng)前進(jìn)度 :" + result + "%"); super.handleMessage(msg); } }; int total = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); pb = (ProgressBar) this.findViewById(R.id.pb); bt = (Button) this.findViewById(R.id.bt); tv = (TextView) this.findViewById(R.id.tv_process); et = (EditText) this.findViewById(R.id.et); bt.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt: // 創(chuàng)建一個(gè)子線程 定期的更新ui if("開始下載".equals(bt.getText().toString())){ bt.setText("暫停"); stopflag = false; //開始下載 } else { bt.setText("開始下載"); stopflag = true; } new Thread() { @Override public void run() { super.run(); while (flag) { try { sleep(1000); // 如果total > = 文件長(zhǎng)度 Message msg = new Message(); handler.sendMessage(msg); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); // 開始執(zhí)行下載的操作 String path = et.getText().toString().trim(); if ("".equals(path)) { Toast.makeText(this, "路徑不能為空", 1).show(); return; } try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); int code = conn.getResponseCode(); if (code == 200) { int len = conn.getContentLength(); RandomAccessFile file = new RandomAccessFile( "/mnt/sdcard/" + getFilenName(path), "rwd"); // 1.設(shè)置本地文件大小跟服務(wù)器的文件大小一致 file.setLength(len); // 設(shè)置進(jìn)度條的最大值 pb.setMax(len); // 2 .假設(shè)開啟3 個(gè)線程 int threadnumber = 3; int blocksize = len / threadnumber; /** * 線程1 0~ blocksize 線程2 1*bolocksize ~ 2*blocksize 線程3 * 2*blocksize ~ 文件末尾 */ for (int i = 0; i < threadnumber; i++) { int startposition = i * blocksize; int endpositon = (i + 1) * blocksize; if (i == (threadnumber - 1)) { // 最后一個(gè)線程 endpositon = len; } DownLoadTask task = new DownLoadTask(i, path, startposition, endpositon); task.start(); } } } catch (Exception e) { Toast.makeText(this, "下載出現(xiàn)異常", 0).show(); e.printStackTrace(); } break; } } class DownLoadTask extends Thread { int threadid; String filepath; int startposition; int endpositon; public DownLoadTask(int threadid, String filepath, int startposition, int endpositon) { this.threadid = threadid; this.filepath = filepath; this.startposition = startposition; this.endpositon = endpositon; } @Override public void run() { try { File postionfile = new File("/mnt/sdcard/" + threadid + ".txt"); URL url = new URL(filepath); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); System.out.println("線程" + threadid + "正在下載 " + "開始位置 : " + startposition + "結(jié)束位置 " + endpositon); if (postionfile.exists()) { FileInputStream fis = new FileInputStream(postionfile); byte[] result = StreamTool.getBytes(fis); String str = new String(result); if (!"".equals(str)) { int newstartposition = Integer.parseInt(str); if (newstartposition > startposition) { startposition = newstartposition; } } } // "Range", "bytes=2097152-4194303") conn.setRequestProperty("Range", "bytes=" + startposition + "-" + endpositon); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); InputStream is = conn.getInputStream(); RandomAccessFile file = new RandomAccessFile("/mnt/sdcard/" + getFilenName(filepath), "rwd"); // 設(shè)置 數(shù)據(jù)從文件哪個(gè)位置開始寫 file.seek(startposition); byte[] buffer = new byte[1024]; int len = 0; // 代表當(dāng)前讀到的服務(wù)器數(shù)據(jù)的位置 ,同時(shí)這個(gè)值已經(jīng)存儲(chǔ)的文件的位置 int currentPostion = startposition; // 創(chuàng)建一個(gè)文件對(duì)象 ,記錄當(dāng)前某個(gè)文件的下載位置 while ((len = is.read(buffer)) != -1) { if (stopflag) { return; } file.write(buffer, 0, len); synchronized (MutiledownloadActivity.this) { total += len; } currentPostion += len; // 需要把currentPostion 信息給持久化到存儲(chǔ)設(shè)備 String position = currentPostion + ""; FileOutputStream fos = new FileOutputStream(postionfile); fos.write(position.getBytes()); fos.flush(); fos.close(); } file.close(); System.out.println("線程" + threadid + "下載完畢"); // 當(dāng)線程下載完畢后 把文件刪除掉 if (postionfile.exists()) { postionfile.delete(); } } catch (Exception e) { e.printStackTrace(); } super.run(); } } public String getFilenName(String path) { int start = path.lastIndexOf("/") + 1; return path.substring(start, path.length()); } }
希望本文所述對(duì)大家的Android程序設(shè)計(jì)有所幫助。
- android中多線程下載實(shí)例
- android實(shí)現(xiàn)多線程下載文件(支持暫停、取消、斷點(diǎn)續(xù)傳)
- Android實(shí)現(xiàn)多線程下載文件的方法
- Android版多線程下載 仿下載助手(最新)
- Android編程開發(fā)實(shí)現(xiàn)帶進(jìn)度條和百分比的多線程下載
- Android FTP 多線程斷點(diǎn)續(xù)傳下載\上傳的實(shí)例
- Android多線程+單線程+斷點(diǎn)續(xù)傳+進(jìn)度條顯示下載功能
- Android多線程斷點(diǎn)續(xù)傳下載功能實(shí)現(xiàn)代碼
- Android實(shí)現(xiàn)多線程下載圖片的方法
- Android線程池控制并發(fā)數(shù)多線程下載
相關(guān)文章
listview的上滑下滑監(jiān)聽,上下滑監(jiān)聽隱藏頂部選項(xiàng)欄的實(shí)例
下面小編就為大家分享一篇listview的上滑下滑監(jiān)聽,上下滑監(jiān)聽隱藏頂部選項(xiàng)欄的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-01-01android實(shí)現(xiàn)數(shù)獨(dú)游戲機(jī)器人
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)數(shù)獨(dú)游戲機(jī)器人,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Android ImageView 固定寬高比例的實(shí)現(xiàn)方法
這篇文章主要介紹了Android ImageView 固定寬高比例的實(shí)現(xiàn)方法的相關(guān)資料,,方法一:設(shè)置 adjustViewBounds="true",方法二:使用 Universal-Image-Loader 圖片緩存類,需要注意的是方法二和方法一同時(shí)使用導(dǎo)致設(shè)置無效,需要的朋友可以參考下2017-07-07Flutter實(shí)現(xiàn)紅包動(dòng)畫效果的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Flutter實(shí)現(xiàn)紅包的動(dòng)畫效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下2023-06-06Android App中實(shí)現(xiàn)簡(jiǎn)單的刮刮卡抽獎(jiǎng)效果的實(shí)例詳解
這篇文章主要介紹了Android App中實(shí)現(xiàn)簡(jiǎn)單的刮刮卡抽獎(jiǎng)效果的實(shí)例詳解,文中主要借助Bitmap的canvas.drawPath的api來實(shí)現(xiàn),需要的朋友可以參考下2016-03-03android使用service和activity獲取屏幕尺寸的方法
這篇文章主要介紹了android使用service和activity獲取屏幕尺寸的方法,實(shí)例分析了基于service和activity兩種方法獲取屏幕尺寸的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-08-08Android入門之利用Spinner實(shí)現(xiàn)彈出選擇對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android里如何巧用Spinner做彈出選擇對(duì)話框,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下2022-11-11Android手機(jī)衛(wèi)士之確認(rèn)密碼對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android手機(jī)衛(wèi)士之確認(rèn)密碼對(duì)話框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10Kotlin注解實(shí)現(xiàn)Parcelable序列化流程詳解
有時(shí)我們會(huì)在界面跳轉(zhuǎn)的過程中,做對(duì)象傳值,這時(shí)就需要對(duì)該對(duì)象做序列化處理了。Android中對(duì)對(duì)象的序列化處理有兩種方式,這篇文章主要介紹了Kotlin注解實(shí)現(xiàn)Parcelable序列化2022-12-12