Android uses multithreading to implement breakpoints to download _android

Source: Internet
Author: User
Tags message queue response code static class stub

Multi-threaded downloads are a way to speed up downloads by opening multiple threads to perform a task. You can make tasks run faster ... Multi-threaded task downloads are always available. For example, our mobile phone internal application treasure download mechanism. Must be through the use of multithreading created by the downloader. And this download can implement breakpoint download. After the task has been forcibly terminated. The next time you can use the trigger button to complete the breakpoint download ... So how to implement the breakpoint download this is a problem.

The first thing we need to be clear is that the multithreaded downloader downloads the same task by using multiple threads. But this multithreading is not the number of threads, the faster the download speed. When threads increase a lot, the efficiency of individual threads slows down. So the number of threads needs to have a limit. After the landlord to personally test. Multithreading to download the same task, the number of threads 5-8 is more efficient. When the number of threads is more than 10, the efficiency of multiple threads slows down (assuming that the speed is roughly the same).

So in the implementation of multithreading to download the same task when we need to understand the truth. Let's take a look at an additional picture.

This diagram is actually very simple to illustrate the principle of the ... We divide a task into several parts. Then open a number of threads to download the corresponding section on it. So the first problem to solve is how to make their own threads to download their corresponding tasks, not across the line. So let's look at the specific implementation process. First we use ordinary Java code to implement ... Finally, porting Java code to Android is OK.

public class Download {public static int threadcount = 5;
  Number of threads open. public static void Main (string[] args) {//TODO auto-generated method stub String Path = ' http://192.168.199.172
    : 8080/jdk.exe ";
      try {URL url = new URL (path);
      HttpURLConnection conn = (httpurlconnection) url.openconnection ();
      Conn.setrequestmethod ("get");
      Conn.setconnecttimeout (5000);
      
      int status = Conn.getresponsecode ();
      
        if (status = =) {int length = Conn.getcontentlength ();
        
        System.out.println (length); int blocksize = Length/threadcount;
        
        Split the length of the file. for (int threadid=1; threadid<=threadcount;threadid++) {int startIndex = (threadID-1) *blocksize;//
          The method of starting position.   int endindex = threadid*blocksize-1;
           
          The method of ending position.
           /** * If the length of a file cannot divide the number of threads ...
           * Then the end of the last thread download needs to be set at the end of the file.     * */if (ThreadID = threadcount) {   
            Endindex = length;
        System.out.println ("Thread download location:" +startindex+ "---" +endindex);
    (Exception e) {//TODO auto-generated catch block E.printstacktrace ();

 }
  }
}

This only enables you to get the length of the file by connecting to the server. Then go to set the starting and ending positions for each thread download. Here are just the steps to complete. With the starting and ending locations for the download ... We need to open the thread to complete the download ... So we need to define the download process ourselves ...

First we need a clear idea: since it is a breakpoint to download. So if there's a breakpoint, The next time we download it, we need to download it from the original location. Already downloaded location We do not need to download the ... So we need to record every download. Then with the record. Once the file download is complete ... These records need to be cleared away ... So it is easy to write the ideas of these two places.

The definition of the download thread.
    public static class Downloadthread implements runnable{private int threadID;
    private int startIndex;
    private int endindex;
    
    Private String path;
      Public downloadthread (int threadid,int startindex,int endindex,string path) {this.threadid = ThreadID;
      This.startindex = StartIndex;
      This.endindex = Endindex;
      
    This.path = path;
        
        @Override public void Run () {//TODO auto-generated method stub try { Determine if the last download is complete. If you do not download, you need to continue downloading.
        This file records the last download location.
        File tempfile =new file (threadid+ ". txt"); if (tempfile.exists () && tempfile.length () >0) {FileInputStream FIS = new FileInputStream (te
          Mpfile);
          byte buffer[] = new byte[1024];
          int leng = fis.read (buffer); int downlength = Integer.parseint (new String (Buffer,0,leng))//download starting from the last download ...
          Re-draw the location where you started the download.
          StartIndex = Downlength; Fis.cLose ();
        URL url = new URL (path);
        HttpURLConnection conn = (httpurlconnection) url.openconnection ();
        Conn.setrequestmethod ("get");
        Conn.setconnecttimeout (5000);
        
        Conn.setrequestproperty ("Range", "bytes=" +startindex+ "-" +endindex);
        int status = Conn.getresponsecode ();
        206 also indicates a successful server response. if (status = = 206) {//Get the I/O stream returned by the server ...
          Then write the data to the file.
          
          InputStream in = Conn.getinputstream (); File Write start ...
          Use to save files that you currently need to download ...
          Randomaccessfile RAF = new Randomaccessfile ("Jdk.exe", "RWD");
          
          
          Raf.seek (StartIndex);
          int len = 0;
          
          BYTE buf[] =new byte[1024];
          Record the length of the download already ...
          
          int total = 0;
            while (len = In.read (buf))!=-1) {//For recording the information currently downloaded ...
            Randomaccessfile file =new randomaccessfile (threadid+ ". txt", "RWD");
         Total = Len;   File.write ((total+startindex+ ""). GetBytes ());
            File.close ();
            Writes data to a file ...
            
          Raf.write (buf, 0, Len);
          } in.close ();
          
          
        Raf.close ();
      The catch (Exception e) {//TODO auto-generated catch block E.printstacktrace (); }finally{//If all threads have been downloaded. Which is the task accomplished.
        Clear all the original record files.
        Runningthread--;
            if (runningthread==0) {for (int i=1;i<threadcount;i++) {File File = new file (i+ ". txt");
          File.delete ();

 }
        }
      }
    }
  }

This completes the download of the data information of the file. After testing. A 13M file in 5 threads under the action of the same download time is about 12 seconds (network stability in the case of 300k). The wider the bandwidth. Speed will be faster) a single thread downloads for approximately 15 seconds. This is a two-second cut in time. But let us not forget. What if the file is too big? So the landlord kissed a 90M file 5 threads at the same time under the action of almost 1 minutes and 20 seconds. and using one thread for downloading is almost 2 minutes. There's still a lot of time to be shortened.

So depending on the comparison, it's better to use multiple threads for downloading. Although the general application in Android will not be more than 50M. But the game words generally can reach 100-200m about. So using multithreading can also improve the progress and efficiency of downloads. Also, we can open threads by using a thread pool. Finally, these threads are handed to the thread pool to manage.

In a normal Java project, we write the download code. Can be ported to our Android apps. But there are some places to pay attention to. So here's to stress.

Package com.example.mutithread;
Import Java.io.File;
Import Java.io.FileInputStream;
Import Java.io.InputStream;
Import Java.io.RandomAccessFile;
Import java.net.HttpURLConnection;
Import Java.net.URL;
Import Android.os.Bundle;
Import Android.os.Handler;
Import Android.os.Message;
Import android.app.Activity;
Import Android.text.TextUtils;
Import Android.view.Menu;
Import Android.view.View;
Import Android.widget.EditText;
Import Android.widget.ProgressBar;
Import Android.widget.TextView;

Import Android.widget.Toast;
  public class Mainactivity extends activity {private edittext et;
  Private ProgressBar PB;
  public static int threadcount = 5;
  public static int runningthread=5; public int currentprogress=0;
  Current Progress Value ...
  
  
  Private TextView TV; Private Handler Handler = new Handler () {@Override public void handlemessage (message msg) {switch (msg.
        What) {case 1:toast.maketext (Getapplicationcontext (), msg.obj.toString (), 0). Show (); BrEak
      Case 2:break;
      Case 3:tv.settext ("Current Progress:" + (Pb.getprogress () *100)/pb.getmax ());
      Default:break;
  }
    }
  };
    @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
    Setcontentview (R.layout.activity_main);
    ET = (edittext) Findviewbyid (r.id.et);
    PB = (ProgressBar) Findviewbyid (R.ID.PG);
  tv= (TextView) Findviewbyid (r.id.tv);
    public void DownLoad (View v) {Final String path = Et.gettext (). toString (). Trim ();
      if (textutils.isempty (path)) {Toast.maketext (this, "Download path error", Toast.length_long). Show ();
    return;
      New Thread () {//String path = ' Http://192.168.199.172:8080/jdk.exe ';
          public void Run () {try {URL url = new URL (path);
          HttpURLConnection conn = (httpurlconnection) url.openconnection ();
          Conn.setrequestmethod ("get");
          Conn.setconnecttimeout (5000); int status = CONN.GETREsponsecode ();
            if (status = =) {int length = Conn.getcontentlength ();
            SYSTEM.OUT.PRINTLN ("Total length of document" +length);
            
            
            Pb.setmax (length);
            Randomaccessfile RAF = new Randomaccessfile ("/sdcard/setup.exe", "RWD");
            Raf.setlength (length);
            
            
            Raf.close ();
            Open 5 threads to download the current resource ...
            
            int blockSize = Length/threadcount; for (int threadid=1;threadid<=threadcount;threadid++) {int startIndex = (threadID-1) *blocks
              ize;
              
              int endindex = threadid*blocksize-1; 
              if (ThreadID = = threadcount) {endindex = length;
              SYSTEM.OUT.PRINTLN ("Thread" +threadid+ "Download:---" +startindex+ "--->" +endindex);
            New Thread (New Downloadthread (ThreadID, StartIndex, Endindex, Path)). Start ();
          
         }
          } 
        catch (Exception e) {//TODO auto-generated catch block E.printstacktrace ();
      
    }
      };
  }.start ();
   /** * Download Thread ...
    * */public class Downloadthread implements runnable{private int ThreadID;
    private int startIndex;
    private int endindex;
    
    Private String path; Public downloadthread (int threadid,int startindex,int endindex,string path) {this.
      ThreadID = ThreadID;
      This.startindex = StartIndex;
      This.endindex = Endindex;
    This.path = path;
      @Override public void Run () {//TODO auto-generated method stub URL url;
        try {//check for files that have not been downloaded yet ...
        File Tempfile = new file ("/sdcard/" +threadid+ ". txt");
          if (tempfile.exists () && tempfile.length () >0) {FileInputStream FIS = new FileInputStream (tempfile);
          BYTE temp[] =new byte[1024];
          int leng = fis.read (temp); int downlength = Integer.parseInt (New String (Temp,0,leng));
          
          int alreadydown = Downlength-startindex;
          
          Currentprogress + + alreadydown;//record the length of the downloaded file after a breakpoint occurs ...
          StartIndex = Downlength;
        Fis.close ();
        url = new URL (path);
        HttpURLConnection conn = (httpurlconnection) url.openconnection ();
        Conn.setrequestmethod ("get");
        Conn.setrequestproperty ("Range", "bytes=" +startindex+ "-" +endindex);
        
        Conn.setconnecttimeout (5000);
        Get Response code ...
        
        int status =conn.getresponsecode ();
          if (status = = 206) {InputStream in = Conn.getinputstream ();
          
          Randomaccessfile RAF =new Randomaccessfile ("/sdcard/jdk.exe", "RWD");
          File begins writing.
          
          Raf.seek (StartIndex);
          int len = 0;
          
          byte[] buffer =new byte[1024];
          The length of the data that has been downloaded.
          
          
          int total = 0; while (len = in. Read (buffer)!=-1) {//record the length of the current data download ...
            
            Randomaccessfile file = new Randomaccessfile ("/sdcard/" +threadid+ ". txt", "RWD");
            Raf.write (buffer, 0, Len);
            Total = Len;
            SYSTEM.OUT.PRINTLN ("Thread" +threadid+ "total:" +total);
            File.write ((total+startindex+ ""). GetBytes ());
            
            File.close (); Synchronized (mainactivity.this) {currentprogress + = Len;//Get current total progress ...//progressbar progres Sdialog can update the UI directly inside the child thread ...
               Due to the internal source of the special processing. Pb.setprogress (currentprogress);
               Change progress bar progress on the interface. Message msg =message.obtain (); Reuse the previous message.
               Avoid multiple times New ... msg.what = 3;
               
            Handler.sendmessage (msg);
          } raf.close ();
          In.close ();
        System.out.println ("Thread:" +threadid+ "Download Complete");
        }else{System.out.println ("Thread:" +threadid+ "Download Failed"); \ n catch (ExCeption e) {//TODO auto-generated catch block E.printstacktrace ();
        msg = new Message ();
        Msg.what = 1;
        Msg.obj = e;
      Handler.sendmessage (msg);
          
          }finally{synchronized (mainactivity.this) {runningthread--; if (Runningthread = = 0) {for (int i=1;i<=threadcount;i++) {File File = new file ("/sdcard/" +i+).
              TXT ");
            File.delete ();
            Message msg =new message ();
            Msg.what = 2;
            msg.obj = "Download Complete";
          Handler.sendmessage (msg); @Override public boolean Oncreateoptionsmenu (Menu menu) {//INFL Ate the menu;
    This adds items to the action bar if it is present.
    Getmenuinflater (). Inflate (R.menu.main, menu);
  return true;

 }

}

Source code as above. I will not do the optimization thing. For convenience, just put it on. This defines a ProgressBar progress bar. A textview to synchronize the download progress of the progress bar. In Android, we naturally cannot invoke time-consuming operations in the main thread. So these time-consuming operations we use by opening the child thread. However, a child thread is not able to update the UI interface. Therefore, we need to use the handler message mechanism to complete the UI update operation of the main interface.

But in the code above we'll find a problem. The ProgressBar operation was updated inside the child thread ... In fact, ProgressBar and ProgressDialog are two special cases. We can update their properties within the child threads. Let's take a look at the implementation of the source code.

 private synchronized void refreshprogress (int id, int progress, Boolean fromuser) { if (Muithreadid = = Thread.CurrentThread (). GetId ()) {//If the current running thread is the same as the main threads ...
      Then update the progress bar ...
    Dorefreshprogress (ID, Progress, Fromuser, true);
      else {//If the above is not satisfied ... if (mrefreshprogressrunnable = = null) {mrefreshprogressrunnable = new refreshprogressrunnable ();//Then a newly created thread ...
      Then perform the following procedure. Final RefreshData rd = Refreshdata.obtain (ID, progress, fromuser);
      Gets the message in the message queue ...
      Mrefreshdata.add (RD); if (mattached &&!mrefreshisposted) {post (mrefreshprogressrunnable)//////////////mainly this place. The Post method was called ... Sends the currently running thread to the message queue ... Then this thread can run in the UI ...
        So this step is the determining factor.
      Mrefreshisposted = true; }
    }
  }

It is because the internal code calls the Post method. Put the current thread into the message queue ... Then the Looper thread in the UI handles the thread, which means that the thread can be executed in the UI. It is also this factor that causes us to update ProgressBar within the child thread. But we can see if we want to update the TextView. We need to invoke the handler message mechanism to update the UI interface ... So this piece needs to be noticed.
The code hasn't changed much since the transplant, so you can complete a multithreaded Breakpoint downloader in Android.

This is the entire content of this article, I hope to learn more about Android software programming help.

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.