Android实现多线程断点下载

本案例在于实现文件的多线程断点下载,即文件在下载一部分中断后,可继续接着已有进度下载,并通过进度条显示进度。也就是说在文件开始下载的同时,自动创建每个线程的下载进度的本地文件,下载中断后,重新进入应用点击下载,程序检查有没有本地文件的存在,若存在,获取本地文件中的下载进度,继续进行下载,当下载完成后,自动删除本地文件。

1. 定义布局文件需要用到的属性名及内容


2. 设置用户的Internet权限和关于SD卡的权限

  1. <span style="font-size:14px;"><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
  2. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  3. <uses-permission android:name="android.permission.INTERNET"/></span>  
<span style="font-size:14px;"><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.INTERNET"/></span>

3. 开始界面的布局

基本效果图如下:


用到两个TextView控件,一个EditText控件,一个Button控件,一个ProgressBar控件

需要注意的是:进度条用<ProgressBar />控件,设置sytle属性:style="?Android:attr/progressBarStyleHorizontal"

4.MainActivity的主要程序如下,代码中有注释详解:

  1. package www.csdn.net.download;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.InputStream;  
  7. import java.io.RandomAccessFile;  
  8. import java.net.HttpURLConnection;  
  9. import java.net.URL;  
  10.   
  11. import www.csdn.net.utils.StreamTools;  
  12. import android.R.integer;  
  13. import android.app.Activity;  
  14. import android.os.Bundle;  
  15. import android.os.Environment;  
  16. import android.text.TextUtils;  
  17. import android.view.View;  
  18. import android.widget.EditText;  
  19. import android.widget.ProgressBar;  
  20. import android.widget.TextView;  
  21. import android.widget.Toast;  
  22.   
  23. public class DownloadActivity extends Activity {  
  24.   
  25.     // 线程开启的数量  
  26.     private int threadNum = 3;  
  27.     private int threadRunning = 3;  
  28.   
  29.     private EditText et_url;  
  30.     private ProgressBar progressBar;  
  31.     private TextView tv_pb;  
  32.       
  33.     private int currentProgress;  
  34.   
  35.     @Override  
  36.     protected void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.         setContentView(R.layout.activity_download);  
  39.         // 获取控件对象  
  40.         et_url = (EditText) findViewById(R.id.et_url);  
  41.         progressBar = (ProgressBar) findViewById(R.id.pb_down);  
  42.         tv_pb = (TextView) findViewById(R.id.tv_pb);  
  43.           
  44.         File sdDir = Environment.getExternalStorageDirectory();  
  45.         File pbFile = new File(sdDir,"pb.txt");  
  46.         InputStream is = null;  
  47.         try {  
  48.             //判断文件是否存在  
  49.             if (pbFile.exists()) {  
  50.                 is = new FileInputStream(pbFile);  
  51.             }  
  52.         } catch (FileNotFoundException e) {  
  53.             // TODO Auto-generated catch block  
  54.             e.printStackTrace();  
  55.         }  
  56.         if (is != null) {  
  57.             String value = StreamTools.streamToStr(is);  
  58.             String[] arr = value.split(";");  
  59.             progressBar.setMax(Integer.valueOf(arr[0]));//最大值  
  60.             currentProgress = Integer.valueOf(arr[1]);//当前值  
  61.             progressBar.setProgress(currentProgress);  
  62.             tv_pb.setText("当前的进度是:"+arr[2]);//显示百分比  
  63.         }  
  64.     }  
  65.   
  66.     // 下载文件(得到服务器端文件的大小)  
  67.     public void downLoadFile(View v) {  
  68.   
  69.         // 获取下载路径  
  70.         final String spec = et_url.getText().toString();  
  71.         if (TextUtils.isEmpty(spec)) {  
  72.             Toast.makeText(this"下载的地址不能为空", Toast.LENGTH_LONG).show();  
  73.         } else {  
  74.             new Thread() {  
  75.                 public void run() {  
  76.                     // HttpURLConnection  
  77.                     try {  
  78.                         // 根据下载的地址构建URL对象  
  79.                         URL url = new URL(spec);  
  80.                         // 通过URL对象的openConnection()方法打开连接,返回一个连接对象  
  81.                         HttpURLConnection httpURLConnection = (HttpURLConnection) url  
  82.                                 .openConnection();  
  83.                         // 设置请求的头  
  84.                         httpURLConnection.setRequestMethod("GET");  
  85.                         httpURLConnection.setReadTimeout(5000);  
  86.                         httpURLConnection.setConnectTimeout(5000);  
  87.                         // 判断是否响应成功  
  88.                         if (httpURLConnection.getResponseCode() == 200) {  
  89.                             // 获取下载文件的长度  
  90.                             int fileLength = httpURLConnection  
  91.                                     .getContentLength();  
  92.                             //设置进度条的最大值  
  93.                             progressBar.setMax(fileLength);  
  94.                             //判断sd卡是否管用  
  95.                             if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {  
  96.                                 // 保存文件  
  97.                                 // 外部存储设备的路径  
  98.                                 File sdFile = Environment  
  99.                                         .getExternalStorageDirectory();  
  100.                                 //获取文件的名称  
  101.                                 String fileName = spec.substring(spec.lastIndexOf("/")+1);  
  102.                                 //创建保存的文件  
  103.                                 File file = new File(sdFile, fileName);  
  104.                                 //创建可以随机访问对象  
  105.                                 RandomAccessFile accessFile = new RandomAccessFile(  
  106.                                         file, "rwd");  
  107.                                 // 保存文件的大小  
  108.                                 accessFile.setLength(fileLength);  
  109.                                 // 关闭  
  110.                                 accessFile.close();  
  111.                                 // 计算出每个线程的下载大小  
  112.                                 int threadSize = fileLength / threadNum;  
  113.                                 // 计算出每个线程的开始位置,结束位置  
  114.                                 for (int threadId = 1; threadId <= 3; threadId++) {  
  115.                                     int startIndex = (threadId - 1) * threadSize;  
  116.                                     int endIndex = threadId * threadSize - 1;  
  117.                                     if (threadId == threadNum) {// 最后一个线程  
  118.                                         endIndex = fileLength - 1;  
  119.                                     }  
  120.   
  121.                                     System.out.println("当前线程:" + threadId  
  122.                                             + " 开始位置:" + startIndex + " 结束位置:"  
  123.                                             + endIndex + " 线程大小:" + threadSize);  
  124.                                     // 开启线程下载  
  125.                                     new DownLoadThread(threadId, startIndex,  
  126.                                             endIndex, spec).start();  
  127.                                 }  
  128.                             }else {  
  129.                                 DownloadActivity.this.runOnUiThread(new Runnable() {  
  130.                                     public void run() {  
  131.                                         Toast.makeText(DownloadActivity.this"SD卡不管用", Toast.LENGTH_LONG).show();  
  132.                                     }  
  133.                                 });  
  134.                             }  
  135.                         }else {  
  136.                             //在主线程中运行  
  137.                             DownloadActivity.this.runOnUiThread(new Runnable() {  
  138.                                 public void run() {  
  139.                                     Toast.makeText(DownloadActivity.this"服务器端返回错误", Toast.LENGTH_LONG).show();  
  140.                                 }  
  141.                             });  
  142.                         }  
  143.   
  144.                     } catch (Exception e) {  
  145.                         // TODO Auto-generated catch block  
  146.                         e.printStackTrace();  
  147.                     }  
  148.                 };  
  149.   
  150.             }.start();  
  151.         }  
  152.     }  
  153.   
  154.     class DownLoadThread extends Thread {  
  155.   
  156.         private int threadId;  
  157.         private int startIndex;  
  158.         private int endIndex;  
  159.         private String path;  
  160.   
  161.         /** 
  162.          * 构造函数 
  163.          *  
  164.          * @param threadId 
  165.          *            线程的序号 
  166.          * @param startIndex 
  167.          *            线程开始位置 
  168.          * @param endIndex 
  169.          * @param path 
  170.          */  
  171.         public DownLoadThread(int threadId, int startIndex, int endIndex,  
  172.                 String path) {  
  173.             super();  
  174.             this.threadId = threadId;  
  175.             this.startIndex = startIndex;  
  176.             this.endIndex = endIndex;  
  177.             this.path = path;  
  178.         }  
  179.   
  180.         @Override  
  181.         public void run() {  
  182.             try {  
  183.                 File sdFile = Environment.getExternalStorageDirectory();  
  184.                 //获取每个线程下载的记录文件  
  185.                 File recordFile = new File(sdFile, threadId + ".txt");  
  186.                 if (recordFile.exists()) {  
  187.                     // 读取文件的内容  
  188.                     InputStream is = new FileInputStream(recordFile);  
  189.                     // 利用工具类转换  
  190.                     String value = StreamTools.streamToStr(is);  
  191.                     // 获取记录的位置  
  192.                     int recordIndex = Integer.parseInt(value);  
  193.                     // 将记录的位置赋给开始位置  
  194.                     startIndex = recordIndex;  
  195.                 }  
  196.   
  197.                 // 通过path路径构建URL对象  
  198.                 URL url = new URL(path);  
  199.                 // 通过URL对象的openConnection()方法打开连接,返回一个连接对象  
  200.                 HttpURLConnection httpURLConnection = (HttpURLConnection) url  
  201.                         .openConnection();  
  202.                 // 设置请求的头  
  203.                 httpURLConnection.setRequestMethod("GET");  
  204.                 httpURLConnection.setReadTimeout(5000);  
  205.                 // 设置下载文件的开始位置结束位置  
  206.                 httpURLConnection.setRequestProperty("Range""bytes="  
  207.                         + startIndex + "-" + endIndex);  
  208.                 // 获取的状态码  
  209.                 int code = httpURLConnection.getResponseCode();  
  210.                 // 判断是否成功  
  211.                 if (code == 206) {  
  212.                     // 获取每个线程返回的流对象  
  213.                     InputStream is = httpURLConnection.getInputStream();  
  214.                     //获取文件的名称  
  215.                     String fileName = path.substring(path.lastIndexOf("/")+1);  
  216.                     // 根据路径创建文件  
  217.                     File file = new File(sdFile, fileName);  
  218.                     // 根据文件创建RandomAccessFile对象  
  219.                     RandomAccessFile raf = new RandomAccessFile(file, "rwd");  
  220.                     raf.seek(startIndex);  
  221.                     // 定义读取的长度  
  222.                     int len = 0;  
  223.                     // 定义缓冲区  
  224.                     byte b[] = new byte[1024 * 1024];  
  225.                     int total = 0;  
  226.                     // 循环读取  
  227.                     while ((len = is.read(b)) != -1) {  
  228.                         RandomAccessFile threadFile = new RandomAccessFile(  
  229.                                 new File(sdFile, threadId + ".txt"), "rwd");  
  230.                         threadFile.writeBytes((startIndex + total) + "");  
  231.                         threadFile.close();  
  232.                         raf.write(b, 0, len);  
  233.                         // 已经下载的大小  
  234.                         total += len;  
  235.                         //解决同步问题  
  236.                         synchronized (DownloadActivity.this) {  
  237.                             currentProgress += len;  
  238.                             progressBar.setProgress(currentProgress);  
  239.                             //计算百分比的操作 l表示long型  
  240.                             final String percent = currentProgress*100l/progressBar.getMax()+"%";  
  241.                             DownloadActivity.this.runOnUiThread(new Runnable() {  
  242.                                 public void run() {  
  243.                                     tv_pb.setText("当前的进度是:"+percent);  
  244.                                 }  
  245.                             });  
  246.                             //创建保存当前进度和百分比的操作  
  247.                             RandomAccessFile pbFile = new RandomAccessFile(  
  248.                                     new File(sdFile, "pb.txt"), "rwd");  
  249.                             pbFile.writeBytes(progressBar.getMax()+";"+currentProgress+";"+percent);  
  250.                             pbFile.close();  
  251.                         }  
  252.                     }  
  253.                     raf.close();  
  254.                     is.close();  
  255.                     runOnUiThread(new Runnable() {  
  256.                         public void run() {  
  257.                             Toast.makeText(DownloadActivity.this"当前线程--" + threadId + "--下载完毕", Toast.LENGTH_LONG).show();  
  258.                         }  
  259.                     });  
  260.                     deleteRecordFiles();  
  261.                 } else {  
  262.                     runOnUiThread(new Runnable() {  
  263.                         public void run() {  
  264.                             Toast.makeText(DownloadActivity.this"服务器端下载错误", Toast.LENGTH_LONG).show();  
  265.                         }  
  266.                     });  
  267.                 }  
  268.             } catch (Exception e) {  
  269.                 // TODO Auto-generated catch block  
  270.                 e.printStackTrace();  
  271.             }  
  272.   
  273.         }  
  274.   
  275.     }  
  276.   
  277.     // synchronized避免线程同步  
  278.     public synchronized void deleteRecordFiles() {  
  279.         File sdFile = Environment.getExternalStorageDirectory();  
  280.         threadRunning--;  
  281.         if (threadRunning == 0) {  
  282.             for (int i = 1; i <= 3; i++) {  
  283.                 File recordFile = new File(sdFile, i + ".txt");  
  284.                 if (recordFile.exists()) {  
  285.                     // 删除文件  
  286.                     recordFile.delete();  
  287.                 }  
  288.                 File pbFile = new File(sdFile,"pb.txt");  
  289.                 if (pbFile.exists()) {  
  290.                     pbFile.delete();  
  291.                 }  
  292.             }  
  293.         }  
  294.     }  
  295. }  
package www.csdn.net.download;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import www.csdn.net.utils.StreamTools;
import android.R.integer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class DownloadActivity extends Activity {

	// 线程开启的数量
	private int threadNum = 3;
	private int threadRunning = 3;

	private EditText et_url;
	private ProgressBar progressBar;
	private TextView tv_pb;
	
	private int currentProgress;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_download);
		// 获取控件对象
		et_url = (EditText) findViewById(R.id.et_url);
		progressBar = (ProgressBar) findViewById(R.id.pb_down);
		tv_pb = (TextView) findViewById(R.id.tv_pb);
		
		File sdDir = Environment.getExternalStorageDirectory();
		File pbFile = new File(sdDir,"pb.txt");
		InputStream is = null;
		try {
			//判断文件是否存在
			if (pbFile.exists()) {
				is = new FileInputStream(pbFile);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (is != null) {
			String value = StreamTools.streamToStr(is);
			String[] arr = value.split(";");
			progressBar.setMax(Integer.valueOf(arr[0]));//最大值
			currentProgress = Integer.valueOf(arr[1]);//当前值
			progressBar.setProgress(currentProgress);
			tv_pb.setText("当前的进度是:"+arr[2]);//显示百分比
		}
	}

	// 下载文件(得到服务器端文件的大小)
	public void downLoadFile(View v) {

		// 获取下载路径
		final String spec = et_url.getText().toString();
		if (TextUtils.isEmpty(spec)) {
			Toast.makeText(this, "下载的地址不能为空", Toast.LENGTH_LONG).show();
		} else {
			new Thread() {
				public void run() {
					// HttpURLConnection
					try {
						// 根据下载的地址构建URL对象
						URL url = new URL(spec);
						// 通过URL对象的openConnection()方法打开连接,返回一个连接对象
						HttpURLConnection httpURLConnection = (HttpURLConnection) url
								.openConnection();
						// 设置请求的头
						httpURLConnection.setRequestMethod("GET");
						httpURLConnection.setReadTimeout(5000);
						httpURLConnection.setConnectTimeout(5000);
						// 判断是否响应成功
						if (httpURLConnection.getResponseCode() == 200) {
							// 获取下载文件的长度
							int fileLength = httpURLConnection
									.getContentLength();
							//设置进度条的最大值
							progressBar.setMax(fileLength);
							//判断sd卡是否管用
							if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
								// 保存文件
								// 外部存储设备的路径
								File sdFile = Environment
										.getExternalStorageDirectory();
								//获取文件的名称
								String fileName = spec.substring(spec.lastIndexOf("/")+1);
								//创建保存的文件
								File file = new File(sdFile, fileName);
								//创建可以随机访问对象
								RandomAccessFile accessFile = new RandomAccessFile(
										file, "rwd");
								// 保存文件的大小
								accessFile.setLength(fileLength);
								// 关闭
								accessFile.close();
								// 计算出每个线程的下载大小
								int threadSize = fileLength / threadNum;
								// 计算出每个线程的开始位置,结束位置
								for (int threadId = 1; threadId <= 3; threadId++) {
									int startIndex = (threadId - 1) * threadSize;
									int endIndex = threadId * threadSize - 1;
									if (threadId == threadNum) {// 最后一个线程
										endIndex = fileLength - 1;
									}

									System.out.println("当前线程:" + threadId
											+ " 开始位置:" + startIndex + " 结束位置:"
											+ endIndex + " 线程大小:" + threadSize);
									// 开启线程下载
									new DownLoadThread(threadId, startIndex,
											endIndex, spec).start();
								}
							}else {
								DownloadActivity.this.runOnUiThread(new Runnable() {
									public void run() {
										Toast.makeText(DownloadActivity.this, "SD卡不管用", Toast.LENGTH_LONG).show();
									}
								});
							}
						}else {
							//在主线程中运行
							DownloadActivity.this.runOnUiThread(new Runnable() {
								public void run() {
									Toast.makeText(DownloadActivity.this, "服务器端返回错误", Toast.LENGTH_LONG).show();
								}
							});
						}

					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				};

			}.start();
		}
	}

	class DownLoadThread extends Thread {

		private int threadId;
		private int startIndex;
		private int endIndex;
		private String path;

		/**
		 * 构造函数
		 * 
		 * @param threadId
		 *            线程的序号
		 * @param startIndex
		 *            线程开始位置
		 * @param endIndex
		 * @param path
		 */
		public DownLoadThread(int threadId, int startIndex, int endIndex,
				String path) {
			super();
			this.threadId = threadId;
			this.startIndex = startIndex;
			this.endIndex = endIndex;
			this.path = path;
		}

		@Override
		public void run() {
			try {
				File sdFile = Environment.getExternalStorageDirectory();
				//获取每个线程下载的记录文件
				File recordFile = new File(sdFile, threadId + ".txt");
				if (recordFile.exists()) {
					// 读取文件的内容
					InputStream is = new FileInputStream(recordFile);
					// 利用工具类转换
					String value = StreamTools.streamToStr(is);
					// 获取记录的位置
					int recordIndex = Integer.parseInt(value);
					// 将记录的位置赋给开始位置
					startIndex = recordIndex;
				}

				// 通过path路径构建URL对象
				URL url = new URL(path);
				// 通过URL对象的openConnection()方法打开连接,返回一个连接对象
				HttpURLConnection httpURLConnection = (HttpURLConnection) url
						.openConnection();
				// 设置请求的头
				httpURLConnection.setRequestMethod("GET");
				httpURLConnection.setReadTimeout(5000);
				// 设置下载文件的开始位置结束位置
				httpURLConnection.setRequestProperty("Range", "bytes="
						+ startIndex + "-" + endIndex);
				// 获取的状态码
				int code = httpURLConnection.getResponseCode();
				// 判断是否成功
				if (code == 206) {
					// 获取每个线程返回的流对象
					InputStream is = httpURLConnection.getInputStream();
					//获取文件的名称
					String fileName = path.substring(path.lastIndexOf("/")+1);
					// 根据路径创建文件
					File file = new File(sdFile, fileName);
					// 根据文件创建RandomAccessFile对象
					RandomAccessFile raf = new RandomAccessFile(file, "rwd");
					raf.seek(startIndex);
					// 定义读取的长度
					int len = 0;
					// 定义缓冲区
					byte b[] = new byte[1024 * 1024];
					int total = 0;
					// 循环读取
					while ((len = is.read(b)) != -1) {
						RandomAccessFile threadFile = new RandomAccessFile(
								new File(sdFile, threadId + ".txt"), "rwd");
						threadFile.writeBytes((startIndex + total) + "");
						threadFile.close();
						raf.write(b, 0, len);
						// 已经下载的大小
						total += len;
						//解决同步问题
						synchronized (DownloadActivity.this) {
							currentProgress += len;
							progressBar.setProgress(currentProgress);
							//计算百分比的操作 l表示long型
							final String percent = currentProgress*100l/progressBar.getMax()+"%";
							DownloadActivity.this.runOnUiThread(new Runnable() {
								public void run() {
									tv_pb.setText("当前的进度是:"+percent);
								}
							});
							//创建保存当前进度和百分比的操作
							RandomAccessFile pbFile = new RandomAccessFile(
									new File(sdFile, "pb.txt"), "rwd");
							pbFile.writeBytes(progressBar.getMax()+";"+currentProgress+";"+percent);
							pbFile.close();
						}
					}
					raf.close();
					is.close();
					runOnUiThread(new Runnable() {
						public void run() {
							Toast.makeText(DownloadActivity.this, "当前线程--" + threadId + "--下载完毕", Toast.LENGTH_LONG).show();
						}
					});
					deleteRecordFiles();
				} else {
					runOnUiThread(new Runnable() {
						public void run() {
							Toast.makeText(DownloadActivity.this, "服务器端下载错误", Toast.LENGTH_LONG).show();
						}
					});
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

	// synchronized避免线程同步
	public synchronized void deleteRecordFiles() {
		File sdFile = Environment.getExternalStorageDirectory();
		threadRunning--;
		if (threadRunning == 0) {
			for (int i = 1; i <= 3; i++) {
				File recordFile = new File(sdFile, i + ".txt");
				if (recordFile.exists()) {
					// 删除文件
					recordFile.delete();
				}
				File pbFile = new File(sdFile,"pb.txt");
				if (pbFile.exists()) {
					pbFile.delete();
				}
			}
		}
	}
}

对于流的输出可以封装一个StreamTools方法,在主程序中可以应用,代码如下:

  1. package www.csdn.net.utils;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6.   
  7. public class StreamTools {  
  8.       
  9.     public static String streamToStr(InputStream is){  
  10.         String value = null;  
  11.         try {  
  12.             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  13.             // 定义读取的长度  
  14.             int len = 0;  
  15.             // 定义缓冲区  
  16.             byte b[] = new byte[1024];  
  17.             // 循环读取  
  18.             while ((len = is.read(b)) != -1) {  
  19.                 baos.write(b, 0, len);  
  20.             }  
  21.             baos.close();  
  22.             is.close();  
  23.             value = new String(baos.toByteArray());  
  24.         } catch (IOException e) {  
  25.             // TODO Auto-generated catch block  
  26.             e.printStackTrace();  
  27.         }  
  28.   
  29.         return value;  
  30.     }  
  31.   
  32. }  
package www.csdn.net.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class StreamTools {
	
	public static String streamToStr(InputStream is){
		String value = null;
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			// 定义读取的长度
			int len = 0;
			// 定义缓冲区
			byte b[] = new byte[1024];
			// 循环读取
			while ((len = is.read(b)) != -1) {
				baos.write(b, 0, len);
			}
			baos.close();
			is.close();
			value = new String(baos.toByteArray());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return value;
	}

}
5. 程序运行结果如图:


sd卡中出现的临时文件,当下载完成会自动删除:


6. 出现的bug原因可能有:

Internet权限没加,服务器没启动,访问下载路径有错,没有获取控件对象等。

如果文件下载中,进度条显示的进度是负数,可能原因是文件大小进行百分比计算时超出内存空间,解决办法:在定义百分比的时候,在100后面加上l,表示long型,即String percent = currentProgress*100l/progressBar.getMax()+"%"。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值