The example of this article describes the development of Android programming to implement multithread Breakpoint renewal Downloader. Share to everyone for your reference, specific as follows:
Using a multithreaded breakpoint to renew the downloader when downloading multiple threads concurrency can occupy more resources on the server side, to speed up the download, the download process to record the number of copies of each thread has been copied, if the download interruption, such as no signal disconnection, low power, and so on, this requires the use of a breakpoint to continue to pass the function, Continue downloading from the record location the next time you start, avoiding duplicate downloads. The database is used here to record the progress of the download.
Effect Chart :
Breakpoint Continuation
1. To record the download progress of each thread during the download process
2. Read the database before the start of each download, query for incomplete records, continue downloading, no more, create new records insert Database
3. Update the download progress in the database after each data is written to the file
4. Delete the download record in the database after the download is complete
Handler transfer data
This is primarily used to record percentages, and each download part of the data tells the main thread to record the time
1. The view created in the main thread can only be modified in the main thread, and other threads can only communicate through the main thread and change view data in the main thread
2. We use handler to handle this requirement
Create handler in main thread, rewrite Handlemessage () method
A new thread sends a message using handler, the main thread receives the message, and executes the Handlemessage () method
Dynamically generate new View
Multi-task downloads can be achieved
1. Create an XML file that will be generated by the view configuration well
2. Get the system services Layoutinflater to generate a new view
Copy Code code as follows:
Layoutinflater Inflater = (layoutinflater) getsystemservice (Layout_inflater_service);
3. Use the inflate (int resource, ViewGroup root) method to generate a new view
4. Call the AddView of a container in the current page and add the newly created view
Example
progress bar Style Download.xml
<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android= "http://schemas.android.com/apk/res/" Android "Android:layout_width=" Fill_parent "android:layout_height=" Wrap_content "> <linearlayout Android : orientation= "Vertical" android:layout_width= "fill_parent" android:layout_height= "Wrap_content" android:layout _weight= "1" > <!--progress bar style defaults to a circular progress bar, the horizontal progress bar needs to configure the Style property,? android:attr/progressbarstylehorizontal--> &L T ProgressBar android:layout_width= "fill_parent" android:layout_height= "20DP" style= "Android:attr/progres"? Sbarstylehorizontal "/> <textview android:layout_width=" wrap_content "android:layout_height=" W Rap_content "android:layout_gravity=" center "android:text=" 0% "/> </LinearLayout> <butto
n android:layout_width= "40DP" android:layout_height= "40DP" android:onclick= "pause" android:text= "| |"
/> </LinearLayout>
Top style Main.xml
<?xml version= "1.0" encoding= "Utf-8"?> "<linearlayout xmlns:android=" http:// Schemas.android.com/apk/res/android "android:orientation=" vertical "android:layout_width=" Fill_parent "Android: layout_height= "Fill_parent" android:id= "@+id/root" > <textview android:layout_width= "fill_parent" Andr oid:layout_height= "wrap_content" android:text= "Please enter the download path"/> <linearlayout android:layout_width= "Fill_pa Rent "android:layout_height=" wrap_content "android:layout_marginbottom=" 30DP "> <edittext andr Oid:id= "@+id/path" android:layout_width= "fill_parent" android:layout_height= "Wrap_content" Android:singl Eline= "true" android:layout_weight= "1"/> <button android:layout_width= "Wrap_content" an droid:layout_height= "wrap_content" android:text= "Download" android:onclick= "Download"/> </linearlayou T> </LinearLayout>
Mainactivity.java
public class Mainactivity extends activity {private Layoutinflater inflater;
Private LinearLayout rootlinearlayout;
Private EditText Pathedittext;
@Override public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
Dynamically generate a new view, obtain the system service Layoutinflater, to generate a new view Inflater = (layoutinflater) getsystemservice (Layout_inflater_service);
Rootlinearlayout = (linearlayout) Findviewbyid (r.id.root);
Pathedittext = (edittext) Findviewbyid (R.id.path);
After the form is created, query the database for unfinished tasks, and if so, create a component such as a progress bar, and continue downloading list<string> List = new Infodao (this). Queryundone ();
for (String path:list) createdownload (path); /** * Download button * @param view */public void Download (view view) {String Path = http://192.168.1.199:8080/
14_web/"+ pathedittext.gettext (). toString ();
Createdownload (path); /** * Dynamic generation of New view * Initialize form data * @param path/private void Createdownload (String pATH) {//Get system services Layoutinflater to generate a new view layoutinflater Inflater = (layoutinflater) getsystemservice (Layout_inflat
Er_service);
LinearLayout linearlayout = (linearlayout) inflater.inflate (r.layout.download, NULL);
LinearLayout childlinearlayout = (linearlayout) linearlayout.getchildat (0);
ProgressBar ProgressBar = (ProgressBar) childlinearlayout.getchildat (0);
TextView TextView = (TextView) childlinearlayout.getchildat (1);
Button button = (button) linearlayout.getchildat (1);
try {button.setonclicklistener (new MyListener (ProgressBar, TextView, Path));
Invokes the addview of a container in the current page, adding the newly created view to Rootlinearlayout.addview (LinearLayout);
catch (Exception e) {e.printstacktrace ();
} Private Final class MyListener implements Onclicklistener {private ProgressBar ProgressBar;
Private TextView TextView;
private int fileLen;
Private Downloader downloader;
private String name; /** * Perform download * @param proGressbar//progress bar * @param textView//percent * @param path//download file path/public MyListener (ProgressBar progress
Bar, TextView TextView, String path) {this.progressbar = ProgressBar;
This.textview = TextView;
Name = Path.substring (Path.lastindexof ("/") + 1);
Downloader = new Downloader (Getapplicationcontext (), handler);
try {downloader.download (path, 3);
catch (Exception e) {e.printstacktrace ();
Toast.maketext (Getapplicationcontext (), "exception occurred during download", 0). Show ();
throw new RuntimeException (e); }//handler Transfer Data private Handler Handler = new Handler () {@Override public void Handlemessage (Me Ssage msg) {switch (msg.what) {case 0://Get the size of the file FileLen = Msg.getdata (). Getin
T ("FileLen");
Set the maximum scale of the progress bar: Setmax () Progressbar.setmax (FileLen);
Break Case 1://get current Download total int done = msG.getdata (). GetInt ("Done");
Percentage of current progress Textview.settext (name + "T" + done * 100/filelen + "%");
The progress bar sets the current progress: setprogress () progressbar.setprogress (done);
if (done = = FileLen) {Toast.maketext (Getapplicationcontext (), name + "Download Complete", 0). Show ();
Exit the progress bar after the download completes Rootlinearlayout.removeview (View) progressbar.getparent (). GetParent ());
} break;
}
}
};
/** * Pause and resume download * * public void OnClick (View v) {Button Pausebutton = (Button) v; if ("| |").
Equals (Pausebutton.gettext ())) {downloader.pause ();
Pausebutton.settext ("▶");
else {downloader.resume ();
Pausebutton.settext ("| |");
}
}
}
}
Downloader.java
public class Downloader {private int done;
Private Infodao DAO;
private int fileLen;
Private Handler Handler;
Private Boolean ispause;
Public Downloader (context context, Handler Handler) {dao = new Infodao (context);
This.handler = handler; /** * Multithreading Download * @param path Download path * @param How many threads thcount need to be opened * @throws Exception/public void download
(String path, int thcount) throws Exception {URL url = new URL (path);
HttpURLConnection conn = (httpurlconnection) url.openconnection ();
Set timeout time conn.setconnecttimeout (3000);
if (conn.getresponsecode () = = FileLen = Conn.getcontentlength ();
String name = path.substring (Path.lastindexof ("/") + 1);
File File = new file (Environment.getexternalstoragedirectory (), name);
Randomaccessfile RAF = new Randomaccessfile (file, "RWS");
Raf.setlength (FileLen);
Raf.close ();
Handler sends a message, the main thread receives the message, gets the length of the data msg = new messages (); Msg.what = 0;
Msg.getdata (). Putint ("FileLen", FileLen);
Handler.sendmessage (msg);
Calculates the number of bytes downloaded per thread int partlen = (FileLen + thCount-1)/thcount;
for (int i = 0; i < thcount i++) new Downloadthread (URL, file, Partlen, i). Start ();
else {throw new illegalargumentexception ("404 Path:" + path);
} Private Final class Downloadthread extends Thread {private URL url;
private file file;
private int Partlen;
private int id;
Public downloadthread (URL url, file file, int partlen, int id) {this.url = URL;
This.file = file;
This.partlen = Partlen;
This.id = ID; /** * Write operation/public void run () {//To determine if there was a last unfinished task info info = dao.query (url.tostring (), ID
);
if (info!= null) {//If there is, read the current thread has downloaded the amount done = = Info.getdone ();
else {//if not, create a new record deposit info = new info (url.tostring (), ID, 0);
Dao.insert (info);
} int start = ID * partlen + info.getdone ();
Start position = + Download int end = (id + 1) * PARTLEN-1;
try {HttpURLConnection conn = (httpurlconnection) url.openconnection ();
Conn.setreadtimeout (3000);
Gets the data at the specified location, range if the range of data is exceeded on the server, and the end of the server data is quasi conn.setrequestproperty ("range", "bytes=" + Start + "-" +);
Randomaccessfile RAF = new Randomaccessfile (file, "RWS");
Raf.seek (start);
Start reading and writing data inputstream in = Conn.getinputstream ();
byte[] buf = new byte[1024 * 10];
int Len;
while (len = In.read (buf))!=-1) {if (ispause) {//Lock this thread with a line lock synchronized (DAO) {
try {dao.wait ();
catch (Interruptedexception e) {e.printstacktrace ();
}} raf.write (buf, 0, Len);
Done by + = Len;
Info.setdone (Info.getdone () + len);
Record the amount of data that each thread has downloaded Dao.update (info);
The new thread sends the message with handler, and the main thread receives the message msg = new messages ();
Msg.what = 1;
Msg.getdata (). Putint ("Done");
Handler.sendmessage (msg);
} in.close ();
Raf.close ();
Delete Download Records Dao.deleteall (Info.getpath (), fileLen);
catch (IOException e) {e.printstacktrace ();
"}}//Pause download public void pause () {ispause = true;
//Continue downloading public void resume () {ispause = false;
Restores all threads synchronized (dao) {Dao.notifyall ();
}
}
}
Dao:
Dbopenhelper:
public class Dbopenhelper extends Sqliteopenhelper {public
dbopenhelper (context) {
Super Download.db ", NULL, 1);
}
@Override public
void OnCreate (Sqlitedatabase db) {
db.execsql ("CREATE TABLE Info" (Path VARCHAR (1024), Thid Integer, done integer, PRIMARY KEY (Path, thid)) ";
}
@Override public
void Onupgrade (sqlitedatabase db, int oldversion, int newversion) {
}
}
Infodao:
public class Infodao {private Dbopenhelper helper;
Public Infodao {helper = new Dbopenhelper (context);
public void Insert (info info) {Sqlitedatabase db = Helper.getwritabledatabase (); Db.execsql ("INSERT into Info" (path, Thid, done) VALUES (?,?,?), new object[] {Info.getpath (), Info.getthid (), Info.getdo
NE ()});
public void Delete (String path, int thid) {Sqlitedatabase db = Helper.getwritabledatabase (); Db.execsql ("DELETE from info WHERE path=?")
And thid=? ", new object[] {path, thid});
public void Update (info info) {Sqlitedatabase db = Helper.getwritabledatabase (); Db.execsql ("UPDATE info SET done=?") WHERE path=?
And thid=? ", new object[] {info.getdone (), Info.getpath (), Info.getthid ()});
Public Info Query (String path, int thid) {Sqlitedatabase db = Helper.getwritabledatabase (); Cursor C = db.rawquery ("Select Path, Thid, done from info WHERE path=?") And thid=? ", new string[] {path, string.valueof(Thid)});
info info = null;
if (C.movetonext ()) info = new info (c.getstring (0), C.getint (1), C.getint (2));
C.close ();
return info;
public void DeleteAll (String path, int len) {Sqlitedatabase db = Helper.getwritabledatabase ();
Cursor C = db.rawquery ("Select SUM (done) from info WHERE path=?", new string[] {path});
if (C.movetonext ()) {int result = C.getint (0);
if (result = = Len) db.execsql ("DELETE from info WHERE path=?", new object[] {path});
} public list<string> Queryundone () {Sqlitedatabase db = Helper.getwritabledatabase ();
Cursor C = db.rawquery ("Select DISTINCT path from info", NULL);
list<string> pathlist = new arraylist<string> ();
while (C.movetonext ()) Pathlist.add (c.getstring (0));
C.close ();
return pathlist;
}
}
I hope this article will help you with your Android programming.