Getting Started with Android: Multithreading breakpoint Download Detail Introduction _android

Source: Internet
Author: User
Tags int size save file sqlite uuid

This case is to implement a multithreaded breakpoint download of a file, that is, after a file has been interrupted by a download, you can continue with the progress download and show progress through the progress bar. That is, in the beginning of the file download, the automatic creation of each thread of the download progress of the local files, download interrupted, re-enter the application click to download, the program check there is no local file exists, if there is, get the local file download progress, continue to download. When the download is complete, the local file is automatically deleted.

First, multithreading breakpoint download Introduction

The so-called multithreaded breakpoint download is to use multithreading download, and can be interrupted, if suddenly the power, restart the phone can continue to download, and do not need to download;

The technology used is: SQLite store the download amount of each thread, HTTP request to get download data;

Second, the introduction of the auxiliary class

To complete a multithreaded breakpoint download we need to write some auxiliary classes in advance:

(1) Dbopenhelper

(2) Fileservice:
-map<integer,integer> getData (String path); Get the download amount of each thread based on the URL
-save (String path, Map<integer, integer> Map); store the corresponding download amount for each thread of the URL, which is called at just the beginning
-update (String path, Map<integer, integer> Map); update the download amount of each thread corresponding to the URL in the database;
-delete (String path), deleting the corresponding data for the URL;

(3) Filedownloader:
-getfilesize (); Get the size of the download file
-download (Downloadprogresslistener listener); Download files and set up listeners

(4) Downloadthread: This class is performed in the download of Filedownloader;

List the secondary classes first:
Dbopenhelper.java

Package service; 
 
Import Android.content.Context; 
Import Android.database.sqlite.SQLiteDatabase; 
Import Android.database.sqlite.SQLiteOpenHelper; 
 
public class Dbopenhelper extends Sqliteopenhelper { 
  private static final String dbname = "download.db"; 
  private static final int VERSION = 1; 
   
  Public Dbopenhelper { 
    Super (context, dbname, NULL, VERSION); 
  } 
   
  @Override public 
  void OnCreate (Sqlitedatabase db) { 
    db.execsql (' CREATE TABLE IF not EXISTS filedownlog (id inte GER primary Key AutoIncrement, Downpath varchar (m), ThreadID Integer, downlength integer); 
 
  @Override public 
  void Onupgrade (sqlitedatabase db, int oldversion, int newversion) { 
    db.execsql ("DROP TABLE IF EXISTS filedownlog "); 
    OnCreate (db); 
  } 
 
 

Fileservice.java

Package service; 
Import Java.util.HashMap; 
 
Import Java.util.Map; 
Import Android.content.Context; 
Import Android.database.Cursor; 
Import Android.database.sqlite.SQLiteDatabase; 
 
  /** * Business Bean */public class Fileservice {private Dbopenhelper openhelper; 
  Public Fileservice {openhelper = new Dbopenhelper (context);  /** * Get the length of the file that each thread has already downloaded * @param path * @return/Public Map<integer, integer> GetData (String 
    Path) {Sqlitedatabase db = Openhelper.getreadabledatabase (); 
    Cursor Cursor = Db.rawquery ("Select ThreadID, downlength from Filedownlog where downpath=?", New String[]{path}); 
    Map<integer, integer> data = new Hashmap<integer, integer> (); 
    while (Cursor.movetonext ()) {data.put (cursor.getint (0), Cursor.getint (1)); 
    } cursor.close (); 
    Db.close (); 
  return data; /** * Save the length of the file that each thread has already downloaded * @param path * @param map * */public void Save (StRing path, Map<integer, integer> Map) {//int threadid, int position Sqlitedatabase db = Openhelper.getwritableda 
    Tabase (); 
    Db.begintransaction (); try{for (Map.entry<integer, integer> entry:map.entrySet ()) {db.execsql (' insert INTO Filedownlog ' (do 
      Wnpath, ThreadID, Downlength) VALUES (?,?,?) ", New Object[]{path, Entry.getkey (), Entry.getvalue ()}); 
    } db.settransactionsuccessful (); 
    }finally{db.endtransaction (); 
  } db.close (); /** * Real-time update of the file length per thread has been downloaded * @param path * @param map/public void update (String path, Map<integ 
    Er, integer> map) {Sqlitedatabase db = Openhelper.getwritabledatabase (); 
    Db.begintransaction (); try{for (Map.entry<integer, integer> entry:map.entrySet ()) {db.execsql ("Update Filedownlog set Dow Nlength=? where downpath=? 
      And threadid=? ", New Object[]{entry.getvalue (), Path, Entry.getkey ()}); 
  }    Db.settransactionsuccessful (); 
    }finally{db.endtransaction (); 
  } db.close (); /** * When the file download is complete, delete the corresponding download record * @param path */public void Delete (String path) {Sqlitedatabase db = op 
    Enhelper.getwritabledatabase (); 
    Db.execsql ("Delete from Filedownlog where downpath=?", New Object[]{path}); 
  Db.close (); 
 } 
   
}

Filedownloader.java

Package net.download; 
Import Java.io.File; 
Import Java.io.RandomAccessFile; 
Import java.net.HttpURLConnection; 
Import Java.net.URL; 
Import Java.util.LinkedHashMap; 
Import Java.util.Map; 
Import Java.util.UUID; 
Import Java.util.concurrent.ConcurrentHashMap; 
Import Java.util.regex.Matcher; 
 
Import Java.util.regex.Pattern; Import service. 
Fileservice; 
Import Android.content.Context; 
Import Android.util.Log; 
        /** * File Downloader * Filedownloader loader = new Filedownloader (context, "Http://browse.babasport.com/ejb3/ActivePort.exe", 
    New File ("D:\\androidsoft\\test"), 2); Loader.getfilesize ()//Get the total size of the file try {loader.download (new Downloadprogresslistener () {public void Ondo 
        wnloadsize (int size) {print ("already downloaded:" + size); 
    }      
      }); 
    catch (Exception e) {e.printstacktrace (); 
  } * * Public class Filedownloader {private static final String TAG = "Filedownloader"; 
  private context; Private FilEService Fileservice; 
  /* Downloaded file length * * Private int downloadsize = 0; 
  /* Original File length * * Private int fileSize = 0; 
  /* Thread Number * * Private downloadthread[] threads; 
  /* Local Save File */private file savefile; 
  * Cache the length of each thread download * * Private Map<integer, integer> data = new Concurrenthashmap<integer, integer> (); 
  * * The length of each thread download/private int block; 
  /* Download Path */private String DownloadURL; 
  /** * Get the number of threads/public int getthreadsize () {return threads.length; 
  /** * Get File Size * @return/public int getfilesize () {return fileSize; /** * Cumulative Download size * @param size */protected synchronized void append (int size) {downloadsize = Siz 
  E /** * Update the location where the specified thread was last downloaded * @param threadId thread ID * @param POS last downloaded location * * * protected synchronized void upd 
    Ate (int threadId, int pos) {this.data.put (threadId, POS); 
  This.fileService.update (This.downloadurl, this.data); 
  /** * Build File Downloader * @param downloadurl Download path * @param filesavedir File Save directory * @param threadnum download thread number/public Filedownloader (Co 
      ntext context, String DownloadURL, File filesavedir, int threadnum) {try {this.context = context; 
      This.downloadurl = DownloadURL; 
      Fileservice = new Fileservice (this.context); 
      URL url = new URL (this.downloadurl); 
      if (!filesavedir.exists ()) filesavedir.mkdirs (); 
      This.threads = new Downloadthread[threadnum]; 
      1. Obtain file size HttpURLConnection conn = (httpurlconnection) url.openconnection (); 
      Conn.setconnecttimeout (5*1000); 
      Conn.setrequestmethod ("get"); Conn.setrequestproperty ("Accept", "Image/gif, Image/jpeg, Image/pjpeg, Image/pjpeg, Application/x-shockwave-flash, Application/xaml+xml, Application/vnd.ms-xpsdocument, APPLICATION/X-MS-XBAP, Application/x-ms-application, 
      Application/vnd.ms-excel, Application/vnd.ms-powerpoint, Application/msword, */* "); Conn.setrequestproperty ("Accept-lanGuage "," ZH-CN ");  
      Conn.setrequestproperty ("Referer", DownloadURL); 
      Conn.setrequestproperty ("Charset", "UTF-8"); Conn.setrequestproperty ("User-agent", "mozilla/4.0" (compatible; MSIE 8.0; Windows NT 5.2; 
      trident/4.0. NET CLR 1.1.4322;. NET CLR 2.0.50727;. NET CLR 3.0.04506.30;. NET CLR 3.0.4506.2152) "); 
      Conn.setrequestproperty ("Connection", "keep-alive"); 
      Conn.connect (); 
      Printresponseheader (conn); if (Conn.getresponsecode () ==200) {this.filesize = Conn.getcontentlength ();//Get file size based on response (This.filesiz 
             
        E <= 0) throw new runtimeexception ("Unkown file Size"); String filename = getfilename (conn);//Get file name This.savefile = new file (filesavedir, filename);//Build Save File Ma P<integer, integer> logdata = Fileservice.getdata (DownloadURL);//Get download record//2. If you have previously downloaded, import records from the database, and continue downloading if (logdata.size () >0) {//If there is a download record for (map.enTry<integer, integer> Entry:logdata.entrySet ()) Data.put (Entry.getkey (), Entry.getvalue ());//Put All threads down  The length of the data contained is put in the information} if (This.data.size () ==this.threads.length) {//below calculates the data length for which the thread has already downloaded for (int i = 0; i < this.threads.length; 
          i++) {this.downloadsize + = This.data.get (i+1); 
        Print ("Length already downloaded" + this.downloadsize); //Calculate the data length downloaded by each thread This.block = (this.filesize% this.threads.length) ==0? 
      This.filesize/this.threads.length:this.filesize/this.threads.length + 1; 
      }else{throw new RuntimeException ("Server no Response"); 
      The catch (Exception e) {print (e.tostring ()); 
    throw new RuntimeException ("Don ' t connection this url"); }/** * Get filename */private string GetFileName (HttpURLConnection conn) {string filename = this.downl 
    Oadurl.substring (This.downloadUrl.lastIndexOf ('/') + 1); if (Filename==null | | "". Equals (fiLename.trim ()) {//If the file name is not obtained for (int i = 0;; i++) {String mine = Conn.getheaderfield (i); 
        if (mine = null) break; if ("Content-disposition". Equals (Conn.getheaderfieldkey (i). toLowerCase ())) {Matcher m = Pattern.compile (". *filen 
          Ame= (. *) "). Matcher (Mine.tolowercase ()); 
        if (M.find ()) return M.group (1); 
  filename = uuid.randomuuid () + ". tmp";//default to take a filename} return filename; /** * Start downloading files * @param listener listening for changes in the number of downloads, if you do not need to know the number of real-time downloads, you can set to NULL * @return downloaded file size * @throws exc Eption */public int download (Downloadprogresslistener listener) throws exception{try {RANDOMACCESSFI 
      Le randout = new Randomaccessfile (this.savefile, "RW"); 
      if (this.filesize>0) randout.setlength (this.filesize); 
      Randout.close (); 
      URL url = new URL (this.downloadurl); If the number of threads is not the same as before, restart the next if (This.data.size ()!= this.threads.length) {this.data.clear (); 
      for (int i = 0; i < this.threads.length i++) {this.data.put (i+1, 0);//Initialize the length of the data that each thread has downloaded is 0} 
        for (int i = 0; i < this.threads.length i++) {//Open thread for download int downlength = This.data.get (i+1); if (Downlength < This.block && this.downloadsize<this.filesize) {//Determine if the thread has finished downloading, or continue downloading THIS.T 
          Hreads[i] = new Downloadthread (this, URL, This.savefile, This.block, This.data.get (i+1), i+1); 
          This.threads[i].setpriority (7); 
        This.threads[i].start (); 
        }else{this.threads[i] = null; 
      } this.fileService.save (This.downloadurl, this.data); 
        Boolean notfinish = true;//Download not complete while (notfinish) {//loop to determine whether all threads have completed downloading Thread.Sleep (900); Notfinish = false;//assumes that all threads download complete for (int i = 0; i < this.threads.length; i++) {if (this.threads[i)! = null &&!this.threads[i].isfinish ()) {//If the thread is found to have not finished downloading noTfinish = true;//Set flag is not complete for download if (this.threads[i].getdownlength () = = 1) {//If download fails, then download again this.thr 
              Eads[i] = new Downloadthread (this, URL, This.savefile, This.block, This.data.get (i+1), i+1); 
              This.threads[i].setpriority (7); 
            This.threads[i].start ();  
      } if (Listener!=null) listener.ondownloadsize (this.downloadsize);//notify currently downloaded data length 
    } fileservice.delete (This.downloadurl); 
      catch (Exception e) {print (e.tostring ()); 
    throw new Exception ("File download Fail"); 
  return this.downloadsize; /** * Get HTTP response Header field * @param http * @return/public static map<string, string> Gethttprespon 
    Seheader (httpurlconnection http) {map<string, string> header = new linkedhashmap<string, string> (); 
      for (int i = 0;; i++) {String mine = Http.getheaderfield (i); 
      if (mine = null) break; Header.Put (Http.getheaderfieldkey (i), mine); 
  return header; 
    /** * Print HTTP header field * @param http/public static void Printresponseheader (HttpURLConnection http) { 
    Map<string, string> Header = Gethttpresponseheader (HTTP);  For (map.entry<string, string> entry:header.entrySet ()) {String key = Entry.getkey ()!=null? Entry.getkey () + 
      ":" : ""; 
    Print (key+ entry.getvalue ()); 
  } private static void print (String msg) {log.i (TAG, msg); 
 } 
}

Downloadthread.java

Package net.download; 
Import Java.io.File; 
Import Java.io.InputStream; 
Import Java.io.RandomAccessFile; 
Import java.net.HttpURLConnection; 
 
Import Java.net.URL; 
 
Import Android.util.Log; 
  public class Downloadthread extends Thread {private static final String TAG = "Downloadthread"; 
  Private File SaveFile; 
  Private URL Downurl; 
  private int block;  
  * * Download start position/private int threadId =-1; 
  private int downlength; 
  Private Boolean finish = false; 
 
  Private Filedownloader Downloader; 
    Public Downloadthread (Filedownloader Downloader, URL Downurl, File savefile, int block, int downlength, int threadId) { 
    This.downurl = Downurl; 
    This.savefile = SaveFile; 
    This.block = Block; 
    This.downloader = Downloader; 
    This.threadid = threadId; 
  This.downlength = Downlength; @Override public void Run () {if (Downlength < block) {//not downloaded to complete try {httpurlconnection h TTP = (httpurlconnection) downurl.openconnectiOn (); 
        Http.setconnecttimeout (5 * 1000); 
        Http.setrequestmethod ("get"); Http.setrequestproperty ("Accept", "Image/gif, Image/jpeg, Image/pjpeg, Image/pjpeg, Application/x-shockwave-flash, Application/xaml+xml, Application/vnd.ms-xpsdocument, APPLICATION/X-MS-XBAP, Application/x-ms-application, 
        Application/vnd.ms-excel, Application/vnd.ms-powerpoint, Application/msword, */* "); 
        Http.setrequestproperty ("Accept-language", "ZH-CN");  
        Http.setrequestproperty ("Referer", downurl.tostring ()); 
        Http.setrequestproperty ("Charset", "UTF-8"); int startpos = block * (threadId-1) + downlength;//start position int endpos = block * threadid-1;//End position HTTP.S  Etrequestproperty ("Range", "bytes=" + startpos + "-" + endpos);/Set the scope of obtaining Entity Data Http.setrequestproperty ("User-agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; trident/4.0. NET CLR 1.1.4322;. NET CLR 2.0.50727;. NET CLR 3.0.04506.30;. NET CLR 3.0.4506.2152;. NET CLR 3.5.30729) "); 
         
        Http.setrequestproperty ("Connection", "keep-alive"); 
        InputStream instream = Http.getinputstream (); 
        byte[] buffer = new byte[1024]; 
        int offset = 0; 
        Print ("Thread" + this.threadid + "Start download from position" + startpos); 
        Randomaccessfile threadfile = new Randomaccessfile (This.savefile, "RWD"); 
        Threadfile.seek (startpos); 
          while (offset = instream.read (buffer, 0, 1024))!=-1) {threadfile.write (buffer, 0, offset); 
          Downlength + = offset; 
          Downloader.update (This.threadid, downlength); 
        Downloader.append (offset); 
        } threadfile.close (); 
        Instream.close (); 
        Print ("Thread" + This.threadid + "Download Finish"); 
      This.finish = true; 
        catch (Exception e) {this.downlength =-1; 
      Print ("Thread" + this.threadid+ ":" + E); }} private static void print (String msg) {Log.I (TAG, msg); 
  /** * Download is complete * @return * * public boolean isfinish () {return finish; 
  /** * Already downloaded content size * @return If the return value is-1, on behalf of download failed/public long getdownlength () {returns downlength; 
 
}} Downloadprogresslistener.java package net.download; 
Download Listener public interface Downloadprogresslistener {public void ondownloadsize (int size); 
 }

Third, the specific code

The effect is as follows:

Implementation code:

Package org.xiazdong.download; 
 
Import Java.io.File; 
Import Net.download.DownloadProgressListener; 
Import Net.download.FileDownloader; 
Import android.app.Activity; 
Import Android.os.Bundle; 
Import android.os.Environment; 
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 Mainactivity extends activity {private Button Downloadbutton; 
  Private EditText Urlpathedittext; 
  Private TextView Percenttextview; 
  Private ProgressBar ProgressBar; 
  Private Handler Handler; Main thread Private class Uihandler extends handler{@Override public void Handlemessage (msg) {int 
      Downloadsize = Msg.getdata (). GetInt ("Downloadsize"); 
      int percent = Msg.getdata (). GETINT ("percent"); Progressbar.setprogreSS (Downloadsize); 
    Percenttextview.settext (percent+ "%"); 
    } private Onclicklistener listener = new Onclicklistener () {Downloadthread thread; 
      Class Downloadthread extends thread{private String URL; 
      Private File Savedir; 
      Private Filedownloader Download; 
        Public downloadthread (String URL, File savedir) {this.url = URL; 
      This.savedir = Savedir; }//child thread @Override public void Run () {download = new Filedownloader (Mainactivity.this,url, S 
        Avedir, 3); Progressbar.setmax (Download.getfilesize ()); 
        Sets the maximum scale try {download.download (Downlistener); 
        catch (Exception e) {e.printstacktrace (); 
      Call private Downloadprogresslistener Downlistener = new Downloadprogresslistener () { @Override public void ondownloadsize (int size) {//realtime trace Download condition int percent = (int) ((double) size )/progressbar.getmax () *100); 
        msg = new Message ();  Msg.what = 1; 
        Set ID System.out.println (percent+ "%"); 
        System.out.println (size+ "K"); 
        Msg.getdata (). Putint ("percent", percent); 
        Msg.getdata (). Putint ("Downloadsize", size); 
         
      Handler.sendmessage (msg); 
     
    } 
    }; @Override public void OnClick (View v) {if (V==downloadbutton) {if (environment.getexternalstoragestate) 
          (). Equals (environment.media_mounted)) {String URL = urlpathedittext.gettext (). toString (); 
          File Savedir = Environment.getexternalstoragedirectory (); 
        Download (url,savedir); 
        } else{Toast.maketext (Mainactivity.this, "SDcard does not exist", toast.length_short). Show (); }} private void Download (String URL, File savedir) {thread = new Downloadthread (url,savedir) 
      ; 
       
    Thread.Start (); 
  } 
  }; @Override public void OnCReate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
    Setcontentview (R.layout.main); 
    Downloadbutton = (Button) Findviewbyid (r.id.download); 
    Urlpathedittext = (edittext) Findviewbyid (R.id.path); 
    Percenttextview = (TextView) Findviewbyid (R.id.textview);  
    ProgressBar = (ProgressBar) Findviewbyid (R.id.progressbar); 
    Downloadbutton.setonclicklistener (listener); 
  Handler = new Uihandler (); 
 } 
}

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.