Background Multi-task multithreaded breakpoint download

Source: Internet
Author: User

Tags: breakpoints multi-task background multithreading

Forgot:



Multi-threaded breakpoint download is not very difficult, mainly is three aspects:

1, according to the size of the file and the number of download threads, determine the size of each download thread to download the split file;

2, record each download thread has completed the progress of the download;

3. Merge the split files downloaded by each thread into a single file.

So how to split a remote file into three parts to download it? In fact, in the HTTP protocol, there is a Range field for client-to-server requests, through which you can specify the size of the download file, and its units, in the format: range:bytes x-y,eg:range:bytes=0-100 download from No. 0-100 The contents of the byte range; there is one such thing can be easily implemented multi-threaded download.

The next step is to record the progress of each thread download, in the Android storage methods can be used, such as sqlite, files, etc. a download thread each time the length of the file is added to the cumulative value of the current thread so far the progress of the download, and we want to record this is the value.

Finally merge, first of all, create a local file, the size of the file and the size of the file we want to download is equal, and then use Java to provide the Randomaccessfile class, this class has a method seek (), which is where to start writing data, And this is where we're going to pass in the argument is an int type.

Through the above steps can be a simple implementation of multi-threaded download, and then a little bit about the main code flow:


1. Upload the name and address of the file we want to download to the service

2. Create a downloader (Downloader) for each download task and save it to a collection so that you can download the multi-tasking

3, get the details of the downloader (file size, progress, address), at the same time in this step also need to initialize the downloader, locally create a file of the same size, and determine the size of each thread to download, save to the database

4. The open thread begins to download the file and writes the downloaded data to the created file.

5. Pass the progress of each thread download to the service to update the progress bar

Detailed code is not affixed, just paste the main source code, in particular, you can next source.

Package Com.wpy.multithreadeddownload.service;import Java.util.hashmap;import Java.util.map;import Android.app.service;import Android.content.intent;import Android.os.handler;import Android.os.IBinder;import Android.util.log;import Com.wpy.multithreadeddownload.constant.constant;import Com.wpy.multithreadeddownload.dao.sqlitedao;import Com.wpy.multithreadeddownload.entity.downloaderinfo;import Com.wpy.multithreadeddownload.entity.filestate;import com.wpy.multithreadeddownload.util.downloader;/** * * Project Name: Multithreadeddownload Class Name: Downloadservice class Description: Background download Creator: Wpy * Created: 2014-10-10 pm 5:18:31 * */public class Downloadser Vice extends Service {//Downloader private Downloader downloader;private Sqlitedao dao;/** * Store each downloader */private map<string, Dow nloader> downloaders = new hashmap<string, downloader> ();/** * Total length of each download file */private map<string, Integer > filesizes = new hashmap<string, integer> ();/** * Store the length of each download file */private map<string, integer> Completesi zes = new HaShmap<string, integer> ();/** * Message processing receives data transmitted by each thread in download */private Handler mhandler = new Handler () {public void H Andlemessage (Android.os.Message msg) {if (msg.what = = 1) {String url = (String) msg.obj;int length = Msg.arg1;int complete Size = completesizes.get (URL); completesize = completesize + length;completesizes.put (URL, completesize);//LOG.E ("test >> "," Message Processor handler Current progress: "+ completesize); int fileSize = Filesizes.get (URL); if (completesize = = fileSize) {//download complete DA O.updatastatebyurl (URL);d ownloaders.get (URL). Delete (URL);d ownloaders.remove (URL), if (Downloaders.isempty ()) {// If all downloads are complete, close servicestopself ();}} Send broadcast update download management progress Intent Intent = new intent (); intent.setaction (constant.downloadmanageaction); Intent.putextra (" Completesize ", completesize); Intent.putextra (" url ", url);D ownloadService.this.sendBroadcast (intent);};}; @Overridepublic void OnCreate () {super.oncreate ();d ao = new Sqlitedao (this);} @Overridepublic int Onstartcommand (Intent Intent, int flags, int startid) {StringURLPath = Intent.getstringextra ("DownloadURL"); String name = Intent.getstringextra ("name"); String flag = Intent.getstringextra ("flag"), if (Flag.equals ("Startdownload")) {startdownload (name, URLPath, true);} if (Flag.equals ("Changestate")) {changestate (name, URLPath);} Return Super.onstartcommand (Intent, flags, Startid);} @Overridepublic ibinder onbind (Intent Intent) {return null;} /** * Start Download * * @param urlpath * */private void Startdownload (final string name, final string urlpath,final bo Olean IsFirst) {log.e ("test>>", "File name:" + name); LOG.E ("test>>", "File:" + URLPath);//Initializes a downloader downloader = Downloaders.get (URLPath); if (null = = Downloader) { Downloader = new Downloader (name, URLPath, Constant.localpath,constant.threadcount, this, Mhandler);d ownloaders.put ( URLPath, downloader);} if (downloader.isdownloading ()) {return;} New Thread () {public void run () {Downloaderinfo downloaderinfo = Downloader.getdownloaderinfos (); Completesizes.put ( URLPath, Downloaderinfo.getcomplete()); if (Filesizes.get (urlpath) = = null) {Filesizes.put (URLPath, Downloaderinfo.getfilesize ());} Filestate state = Dao.query (URLPath), if (IsFirst) {log.e ("test>>", "File:" + name + "first time download"); Filestate filestate = new Filestate (name, URLPath, 1,downloaderinfo.getcomplete (), downloaderinfo.getfilesize ()); Dao.savefilestate (filestate);} Downloader.download ();};}. Start ();} /** * Change the download status (if the file is being downloaded, pause it, or start downloading if paused) * * @param URL * */public void changestate (string name, string url) {down Loader loader = downloaders.get (URL), if (loader! = null) {if (loader.isdownloading ()) {//is downloading Loader.setpause ();} else if (Loader.ispause ()) {//Pause loader.reset (); this.startdownload (name, URL, false);}} else {startdownload (name, URL, false);}}}

Package Com.wpy.multithreadeddownload.util;import Java.io.file;import Java.io.inputstream;import Java.io.randomaccessfile;import Java.net.httpurlconnection;import Java.net.url;import Java.util.ArrayList;import Java.util.list;import Android.content.context;import Android.os.handler;import Android.os.Message;import Android.util.log;import Android.widget.toast;import Com.wpy.multithreadeddownload.dao.sqlitedao;import Com.wpy.multithreadeddownload.entity.downloadinfo;import com.wpy.multithreadeddownload.entity.downloaderinfo;/*  * * * Project name: Multithreadeddownload Class Name: Downloader class Description: Downloader Creator: Wpy created: 2014-10-11 * Morning 9:24:01 * */public class Downloader {private string filename;//file name private string downloadpath;//private string localpath;//local saved address private int threadcount ;//The number of download threads private int filesize;//The size of the download file private context context;//context private Handler mhandler;//Message Processor private list< downloadinfo> infos;//Store Download information collection//definition three download statuses: Initialize, download, pause private static final int INIT = 1;private staticfinal int downloading = 2;private static final int PAUSE = 3;private int state = init;//set to initialize private Sqlitedao dao;/** * Constructor * * @param fileName * file name * @param downloadpath * * @param localPath * Local Storage address * @param threadcount * Number of Threads * @param context * Context * @param mhandler * Message Processor */public Dow Nloader (String fileName, String Downloadpath, String Localpath,int threadcount, Context context, Handler Mhandler) {this. FileName = Filename;this.downloadpath = Downloadpath;this.localpath = Localpath;this.threadcount = ThreadCount; This.context = Context;this.mhandler = Mhandler;dao = new Sqlitedao (context);} /** * Get downloader information. First to determine whether it is the first download, the first time to download the initial operation, and to save the information of the downloader to the database; * If not, read the previously downloaded information (start location, end location, file size, etc.) from the database and return the download information to the downloader. * * @return Downloader information (file size, download completion, downloader ID/) */public downloaderinfo Getdownloaderinfos () {if (Isfirstdownload (Downloadpath) {//First download init (); if (FileSize > 0) {int range = Filesize/threadcount; LOG.E ("TEST&GT;> "," size of each thread downloaded: "+ range"; infos = new arraylist<downloadinfo> (); for (int i = 0; i < threadCount-1; i++) {D Ownloadinfo info = new Downloadinfo (i, I * range, (i + 1) * range-1, 0, Downloadpath); LOG.E ("test>>", "Threads <" + i + "> Downloaded size:" + I * range + "---" + ((i + 1) * range-1)); Infos.add (info);} Downloadinfo info = new Downloadinfo (threadCount-1, (threadCount-1) * range, fileSize-1, 0,downloadpath); LOG.E ("test>>", "Thread <" + (THREADCOUNT-1) + "> Downloaded size:" + (threadCount-1) * range + "---" + (fileSize-1)); inf Os.add (info);//Save downloader information to database Dao.savedownloadinfos (infos);} Create a Downloaderinfo record downloader for specific information return to new Downloaderinfo (fileSize, 0, Downloadpath);} else {//not the first download, get the specific information from the database of the existing Downloadpath's downloader infos = Dao.getdownloadinfos (downloadpath); int size = 0;//file Total size int Completesize = 0;//The total length of the download for (Downloadinfo info:infos) {size = size + (Info.getendpos ()-Info.getstartpos () + 1); compl Etesize = completesize + info.getcompeletesize ();} return new DownloAderinfo (Size, completesize, Downloadpath);}} /** * Initialize the downloader (gets the size of the file to be downloaded; Create a file of the same size locally based on the local address) */private void init () {try {URL url = new URL (downloadpath);//Get a URL by the given HttpURLConnection conn = (httpurlconnection) url.openconnection ();//Get an HTTP connection conn.setconnecttimeout (5 * 1000);// Set the connection timeout to 5 seconds Conn.setrequestmethod ("get");//Set the connection mode to GETLOG.E ("test>>", "get the size of the previous file:" + fileSize); int code = Conn.getresponsecode (); LOG.E ("test>>", "Return code for Network request:" + code);//If HTTP returns a code of 200 or 206 for a successful connection if (conn.getresponsecode () = = 200 | | Conn.getresponsecode () = = 206) {fileSize = Conn.getcontentlength ();//Get File Size log.e ("test>>", "File Size:" + fileSize) if (fileSize <= 0) {toast.maketext (context, "network failure, unable to get file size", Toast.length_short). Show (); File dir = new file (LocalPath), if (!dir.exists ()) {//files do not exist if (Dir.mkdirs ()) {System.out.println ("mkdirs success.");}} File File = new file (LocalPath, fileName); Randomaccessfile accessfile = new Randomaccessfile (file, "RWD"); Accessfile.setlength (fileSize); accessfilE.close ();} Conn.disconnect ();} catch (Exception e) {e.printstacktrace ();}} /** * Start download data */public void Download () {if (null! = Infos) {if (downloading = = state) {return;} state = downloading;//Sets the download status to download for (Downloadinfo Info:infos) {New Downloadthread (Info.getthreadid (), Info.getstartpos (), Info.getendpos (), Info.getcompeletesize (), Info.geturl ()). Start ();}} /** * Project name: Multithreadeddownload Class Name: Downloadthread class Description: An internal class that establishes a download thread creator: Wpy * Created: 2014-10-11 pm 1:08:12 * */privat E class Downloadthread extends Thread {private int threadid;private int startpos;private int endpos;private int Completesi  Ze;private String urlpath;/** * Download Thread class constructor * * @param threadId * thread ID * @param startpos * Start Download node * @param endpos * Stop the download of the node * @param completesize * Download completed progress * @param urlpath * Download Address */publi c downloadthread (int threadId, int startpos, int endpos,int completesize, String urlpath) {This.threadid = THREADID;THIS.S Tartpos = Startpos;this.endpos = endpos;this.completesize = Completesize;this.urlpath = URLPath;} @Overridepublic void Run () {httpurlconnection connection = null; Randomaccessfile Accessfile = Null;inputstream InputStream = null; File File = new file (LocalPath, fileName); try {URL url = new URL (urlpath); connection = (HttpURLConnection) url.openconnect Ion (); Connection.setconnecttimeout (5 *); Connection.setrequestmethod ("GET");//Set the Range field in the HTTP header in the format: range: Bytes x-y//Range: For client-to-server requests, this field specifies the size of a section of the downloaded file and its units. Typical formats such as://range:bytes=0-499 download 第0-499 byte range content connection.setrequestproperty ("range", "bytes=" + (Startpos + completesize ) + "-" + Endpos); Connection.connect (); if (connection.getresponsecode () = = 200| | Connection.getresponsecode () = = 206) {AC Cessfile = new Randomaccessfile (file, "RWD"), Accessfile.seek (startpos + completesize);//setting from which location to write data InputStream = Connection.getinputstream (); byte[] buffer = new Byte[4096];int length = -1;while ((length = inputstream.read (buffer))! =- 1) {//write data accessfile.write (buffer,0, length);//accumulate the downloaded lengths completesize = completesize + length;//Update the information in the data Dao.updatadownloadinfos (ThreadId, Completesize, URLPath);//Use the message to pass the download information to the progress bar, update the progress bar with the message msg = Message.obtain (); msg.what = 1;msg.obj = Urlpath;msg.arg1 = length; Mhandler.sendmessage (msg);//Send Message to Downloadservice//LOG.E ("test>>", "Downloader Current progress:" + completesize);//Pause if ( PAUSE = = state) {return;}}}} catch (Exception e) {e.printstacktrace ();} finally {try {//close the closed thing inputstream.close (); Accessfile.close (); Connection.disconnect ();//Dao.closedb ();} catch (Exception e) {e.printstacktrace ();}}}} /** * Determine if it is the first time to download * * @param downloadpath * * @return true first download false to download */private again the Boolean isfirstdownload ( String Downloadpath) {return Dao.ishasdownloadinfos (Downloadpath);} /** * Determine if download is being downloaded * * @return true is False no */public Boolean isdownloading () {return state = = downloading;} /** * Determines whether to pause * * @return true is False no */public Boolean ispause () {return state = = Pause; /** * Set pause */public void Setpause () {State = PAUSE;} /** * Delete the corresponding downloader information in the database according to URLPath * * @param urlpath * */public void Delete (String urlpath) {dao.delete (URLPath); }/** * Reset Download status */public void Reset () {state = INIT;}}




I'm the source .

Background Multi-task multithreaded breakpoint download

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: