android中实现文件线程下载并记录进度值,不支持断点下载(一)

今天遇到了这样的一项任务,就是给定url下载apk文件到指定的位置。

基本上是从网上下载下来代码改一改就可以了,中间遇到了一些小麻烦,下载的时候报异常。

 

java.net.SocketException: recvfrom failed: ECONNRESET

位置为:InputStream is = conn.getInputStream();

获取返回的输入流的时候。

解决方式:

1.用buffered流包装一下。

2.使用HttpURLConnection进行链接并添加头声明

具体解决方法写在类里面了。下面的这个类经过测试可用,下载10M以下的apk文件应该没问题。

当然这种不支持断点下载的方式是很差劲的,虽然给的要求并没有明确提出支持断点下载,但是作为一名开发者还是为未来考虑一下更合适,毕竟这功能以后肯定是会需要的。

大体上的思路也已经了解了,以后有空会写第二个类支持断点下载的。

/**
 * @author tim_liu
 */
public class DownLoadOneApp {
	Context context;
	private String appname;
	private String downloadurl;
	private String outfilepath;
	//the progress is displayed.
	public int progress;
	//the app file size
	public int fileSize;
	//means download size
	public int downLoadFileSize;

	public DownLoadOneApp(Context context,String outfilepath,String downloadurl) {
		this.context = context;
		this.downloadurl=downloadurl;
		this.outfilepath=outfilepath;
		this.appname=getAppName(downloadurl);
	}

	/**
	 * @param outpath
	 * @param url
	 */
	public void startdownfile() {
		
		final String downurl=downloadurl;
		final String outpath=outfilepath+appname;
		File pathfile=new File(outfilepath);
		if(!pathfile.exists()){
			Log_I("the path "+outfilepath+" is not exists,so we mkdirs it");
			if(pathfile.mkdirs()){
				Log_I("mkdirs "+outfilepath+" success!");
			}else{
				Log_I("mkdirs "+outfilepath+" occur error!");
				return ;
			}
		}
		
		new Thread() {
			public void run() {
				try {
					// 下载文件,参数:第一个URL,第二个存放路径
					down_file(downurl,outpath);
				} catch (ClientProtocolException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}.start();
	}
	
	/**
	 * download file
	 * @param url
	 * @param path
	 * @throws IOException
	 */
	private void down_file(String url, String outpath) throws IOException {
		// 获取文件名
		URL myURL = new URL(url);
		HttpURLConnection conn = (HttpURLConnection) myURL.openConnection();
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		conn.setRequestProperty("Accept-Language", "zh-CN");
		conn.setRequestProperty("Referer", myURL.toString());
		conn.setRequestProperty("Charset", "UTF-8");
		conn.setRequestProperty("Connection", "Keep-Alive");
		// 设置范围,格式为Range:bytes x-y;
		conn.connect();
		this.fileSize = conn.getContentLength();// 根据响应获取文件大小
//		conn.setRequestProperty("RANGE", "bytes=0-"+fileSize);
		InputStream is = conn.getInputStream();
		if (this.fileSize <= 0)
			throw new RuntimeException("无法获知文件大小 ");
		if (is == null)
			throw new RuntimeException("stream is null");
		FileOutputStream fos = new FileOutputStream(outpath);

		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		bis = new BufferedInputStream(is);
		bos = new BufferedOutputStream(fos);

		// 把数据存入路径+文件名
		byte buf[] = new byte[4048];
		downLoadFileSize = 0;
		sendMsg(0);
		do {
			// 循环读取
			int numread = bis.read(buf);
			if (numread == -1) {
				break;
			}
			bos.write(buf, 0, numread);
			downLoadFileSize += numread;
			sendMsg(1);// 更新进度条
		} while (true);
		sendMsg(2);// 通知下载完成
		try {
			is.close();
		} catch (Exception ex) {
			Log_E("error: " + ex.getMessage());
		} finally {
			bis.close();
			bos.close();
			fos.close();
		}
	}

	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {// 定义一个Handler,用于处理下载线程与UI间通讯
			if (!Thread.currentThread().isInterrupted()) {
				
				//msg.what is flag.if flag is 0 means start download,flag is 1 means update process,flag is 2 is means 
				switch (msg.what) {
				case 0:
					Log_I("start download app file");
				case 1:
					progress = downLoadFileSize * 100 / fileSize;
					Log_I("progress:"+progress);
					break;
				case 2:
					downloadAPPFile();
					break;
				case -1:
					downloadOccurError(msg.getData().getString("error"));
					break;
				}
			}
			super.handleMessage(msg);
		}
	};
	
	private void sendMsg(int flag) {
		Message msg = new Message();
		msg.what = flag;
		handler.sendMessage(msg);
	}
	
	private String getAppName(String urlstr){
		return urlstr.substring(urlstr.lastIndexOf("/")+1);
	}
	
	private void Log_I(String log) {
		Log.i("WV_"+this.getClass().getName(), log);
	}
	
	private void Log_E(String log) {
		Log.e("WV_"+this.getClass().getName(), log);
	}
	
	
	/**
	 * The following method for the call
	 */

	/**
	 * get info about down file size for MB,for example 2.10MB
	 */
	public String getFileSizeByMB() {
		double size = ((double) fileSize / 1024.0) / 1024.0;
		DecimalFormat df = new DecimalFormat("#####0.00 ");
		String sizestr = df.format(size);
		return sizestr;
	}
	
	/**
	 * get info about download size for byte
	 */
	public String getdownLoadSize(){
		return Integer.toString(downLoadFileSize);
	}
	
	/**
	 * The download is complete
	 */
	public void downloadAPPFile(){
		Toast.makeText(context, "文件下载完成", Toast.LENGTH_SHORT).show();
	}
	
	/**
	 * The download process is abnormal
	 */
	public void downloadOccurError(String error){
		Toast.makeText(context, error, Toast.LENGTH_SHORT).show();
	}
}


你可能感兴趣的:(android中实现文件线程下载并记录进度值,不支持断点下载(一))