The first thing to declare is that multi-threaded download here does not refer to multiple threads downloading a file, but each thread is responsible for a file. Real multi-threaded hope behind can bring you.
------------- Welcome to learn to love the small partners add Group -------------
-------------android AC Group: 230274309-------------
-------------share together and progress together! Need You--------------
--------------look forward to the arrival of our friends who love to learn--------------
This article is followed by the previous http://blog.csdn.net/u011733020/article/details/47016715 continue to write. Interested in the small partner can look at the front.
Interface effect
2015/7/31 Improvement
2015/7/31 the first to say this improved two points.
1th, the previous said that the project is only suitable for learning, as a commercial words, inefficient, because at that time click on the pause, click on the download to continue downloading, if the file before the download part of the larger, will be relatively slow, because Java InputStream skip (long size) jump This method does not follow the bytes you want to skip, but rather skips the smaller one, so it is time-consuming to iterate until it returns to meet the criteria. For example, the file size 30M, you download 20M, you click on the pause and then continue to download, it is necessary to skip this 20M, but you can skip the method of skipping 4096 bytes each time, so the time to skip 20M will be very long. This should be well understood.
2nd, the original project, you this time the download is not completed, the next time the download is deleted from the original new download, this time changed to continue the last place to download.
Spit trough, about the download, I have been watching the download of open source for the past week, but helpless level limited, harvest very little, often is to see the last brain short.
The method of this change is relatively simple, only changed the project Downloadmanager this class. Looking at the Run method of the Downloadmanager class,
/p>
@Overridepublic void Run () {info.setdownloadstate (state_downloading);//change the download status notifydownloadstatechanged (info) first; File File = new file (Info.getpath ());//Get download file Httpresult httpresult = Null;inputstream stream = null;if (Info.getcurrentsi Ze () = = 0 | | !file.exists () | | File.length ()! = Info.getcurrentsize ()) {//If the file does not exist, or the progress is 0, or the progress and file length do not match, you need to re-download <span></span> Info.setcurrentsize (0); File.delete ();} Httpresult = Httphelper.download (Info.geturl ()); if (Httpresult = = null| | (stream = Httpresult.getinputstream ()) = = null) {info.setdownloadstate (state_error);//No download content returned, Modified to Error status notifydownloadstatechanged (info);} else {try {Skipbytesfromstream (stream, info.getcurrentsize ());} catch (Exception E1) {e1.printstacktrace ();} FileOutputStream fos = null;try {fos = new FileOutputStream (file, true); int count = -1;byte[] buffer = new Byte[1024];whil E (((count = stream.read (buffer))! =-1) && info.getdownloadstate () = = state_downloading) {//each time the data is read, All need to determine whether the download status, if not, the download needs to terminate, if so, then refresh the progress Fos.write(buffer, 0, count); Fos.flush (); Info.setcurrentsize (Info.getcurrentsize () + count); notifydownloadprogressed (info); /Refresh Progress}} catch (Exception e) {info.setdownloadstate (state_error); notifydownloadstatechanged (info); Info.setcurrentsize (0); File.delete ();} Finally {ioutils.close (FOS); if (httpresult! = null) {Httpresult.close ();}} <span></span>//determine if the progress is equal to the total app length if (info.getcurrentsize () = = Info.getappsize ()) {info.setdownloadstate ( state_downloaded); notifydownloadstatechanged (info);} else if (info.getdownloadstate () = = state_paused) {//Judgment status notifydownloadstatechanged (info);} else { Info.setdownloadstate (State_error); notifydownloadstatechanged (info); info.setcurrentsize (0);// Error status need to delete file File.delete ();}} Mtaskmap.remove (Info.getid ());}
The stream of traffic returned from the server is ultimately in the Httphelper class
HttpResponse response = Httpclient.execute (Requestbase, HttpContext);//Access Network
Through the httpclient to the networking request.
I have not tried httpclient AddHeader ("Range", "bytes=" + Begin + "-" + end); Can you continue the download.
Instead, it's changed to request data through HttpURLConnection.
Now the Run () method is the case.
@Overridepublic void Run () {info.setdownloadstate (state_downloading);//change the download status notifydownloadstatechanged (info) first; File File = new file (Info.getpath ());//Get download file/**********************************************************///try {try {URL url = new URL (info.geturl ()); HttpURLConnection conn = (httpurlconnection) url.openconnection (); Conn.setrequestmethod ("GET"); Conn.setconnecttimeout (30000); Conn.setreadtimeout (30000); if (!file.exists ()) {info.setcurrentsize (0); file.delete ();} else if (file.length () > Info.getappsize ()) {info.setcurrentsize (0); File.delete ();} else if (file.length () = = Info.getappsize ()) {} else if (File.length () < Info.getappsize ()) {info.setcurrentsize (File.length ());} if (info.getcurrentsize () = = 0 | |!file.exists () | | file.length ()! = Info.getcurrentsize ()) {//If the file does not exist, or the progress is 0, or the progress and file length are not Match, you need to re-download info.setcurrentsize (0); File.delete ();} else if (file.length () = = Info.getcurrentsize () && file.length () < Info.getappsize ()) { Conn.setrequestproperty ("Range", "byteS= "+ info.getcurrentsize () +"-"+ info.getappsize ());} int code = Conn.getresponsecode (); Randomaccessfile RAF = new Randomaccessfile (file, "RW"); InputStream is = Conn.getinputstream (); byte[] buffer = new BYTE[10 8];int len = -1;int total = 0;//The length of the overall data downloaded by the current thread if (code = =) {} else if (code = = 206) {Raf.seek (File.length ());} while ((len = is.read (buffer))! =-1) && (info.getdownloadstate () = = state_downloading)) {//The process of downloading data. Raf.write (buffer, 0, Len); Total + = len;//The current data needs to be recorded. Info.setcurrentsize (info.getcurrentsize () + len); notifydownloadprogressed (info);//Refresh Progress}is.close (); Raf.close ();} catch (Malformedurlexception e) {//TODO auto-generated catch Blocke.printstacktrace ();} catch (Protocolexception e) {//T ODO auto-generated catch Blocke.printstacktrace ();} catch (FileNotFoundException e) {//Todo auto-generated catch Blocke.printstacktrace ();} catch (IOException e) {//Todo Au To-generated catch Blocke.printstacktrace ();} /************************* for various situations, need to delete the download task, new download Please yourselfChange code *****************************///Determine if the progress is equal to the total app length//} catch (Exception e) {//system.out.println (e.tostring ());// Info.setdownloadstate (State_error);//info.setcurrentsize (0);//file.delete ();//e.printstacktrace ();//}if ( Info.getcurrentsize () = = Info.getappsize ()) {info.setdownloadstate (state_downloaded); Notifydownloadstatechanged ( info);} else if (info.getdownloadstate () = = state_paused) {//Judgment status notifydownloadstatechanged (info);} else { Info.setdownloadstate (State_error); notifydownloadstatechanged (info); info.setcurrentsize (0);// Error status need to delete file File.delete ();} /**********************************************************/mtaskmap.remove (Info.getId ());}
Determine if the file does not exist, and if the size satisfies the condition, make a judgment here
if (info.getcurrentsize () = = 0 | |!file.exists () | | file.length ()! = Info.getcurrentsize ()) {//If the file does not exist, or the progress is 0, or the progress and file length are not Match, you need to re-download info.setcurrentsize (0); File.delete ();} else if (file.length () = = Info.getcurrentsize () && file.length () < Info.getappsize ()) { Conn.setrequestproperty ("Range", "bytes=" + info.getcurrentsize () + "-" + info.getappsize ()); }
If the current size of the file is 0, or if the file does not exist, or if the length is not equal to the current length, download again, otherwise set Range
The following is a normal code =200 indicates success, if a range is set then code returns 206 to indicate normal. This time we passed Randomaccessfile
Randomaccessfile This class implements the Randomaccessfile implements Datainput, DataOutput, which is a class that can be read and written.
Randomaccessfile This class to handle how many bytes are skipped, I said earlier that the Inpustream.skeep () method is inaccurate, but randomaccessfile this class is possible.
Randomaccessfile RAF = new Randomaccessfile (file, "RW"); InputStream is = Conn.getinputstream (); byte[] buffer = new BYTE[10 8];int len = -1;int total = 0;//The length of the overall data downloaded by the current thread if (code = =) {} else if (code = = 206) {Raf.seek (File.length ());}
These bytes are skipped by the Seek method.
And then
while ((len = is.read (buffer))! =-1) && (info.getdownloadstate () = = state_downloading)) {//The process of downloading data. Raf.write (buffer, 0, Len); Total + = len;//The current data needs to be recorded. Info.setcurrentsize (info.getcurrentsize () + len); notifydownloadprogressed (info);//Refresh Progress}is.close (); Raf.close ();
Very common code, write out the data. Refreshes the current progress continuously and closes the stream last.
This can guarantee a fast pause continue to download, and this download did not complete, point a pause, the next application, continue to download the time will be the last download, but the network, or you turn off the net, the next time in the recovery network, or download at the point, I did not deal with the need to deal with it, it should be captured different Often seckouttimeexception, and then save the data. Try it yourself and you'll find out.
This is the time to be here. About multiple thread fragments download a file, and so I have time to sort it out.
Share
Copyright NOTICE: This article is the original article of Bo Master
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
J Brother---------Android multi-threaded download Imitation download assistant (improved version)