这是我用来在我的 Android 应用程序中从 Internet 下载文件的完整代码。这个想法是在应用程序重新启动/恢复时从中断的地方恢复下载。
package com.example.simpledownloader.task;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.atomic.AtomicLong;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.util.Log;
import com.example.simpledownloader.sharable.NetworkOptions;
import com.example.simpledownloader.sharable.Sharable;
public class Task extends Thread {
private String url = null;
private String name = null;
private AtomicLong contentLength = null;
private AtomicLong bytesWritten = null;
private boolean isReady = true;
private String errCode = new String("OK");
//------------------------------------------------------------------------------
public Task(String name, String url, long contentLength, long bytesWritten){
// Instantiate the variables
// The values here depend on whether the Task was created by TaskDAO
// or by clicking the download button
this.name = name;
this.url = url;
this.contentLength = new AtomicLong(contentLength);
this.bytesWritten = new AtomicLong(bytesWritten);
}
//------------------------------------------------------------------------------
@Override
public void run() {
File f = null;
RandomAccessFile rFile = null;
setReadiness(false);
Sharable.setShouldLook(false);
try {
String[] names = name.split("/");
if(names.length == 0){
// nothing
}else{
name = names[names.length-1];
}
Log.v("TASKPATH", "/sdcard/" + name);
f = new File("/sdcard/",name);
rFile = new RandomAccessFile(f, "rw");
writeToFile(rFile);
} catch (FileNotFoundException e) {
Log.v("TASK", e.getLocalizedMessage());
if(contentLength.get() == 0){ // new download will have content length set to zero
try {
f.createNewFile(); // make a new file
writeToFile(rFile);// start downloading
}catch (IOException e1) {
errCode = e1.getMessage(); // Unable to create file;
Log.v("TASK", "FILE DELETED");
Sharable.setShouldLook(true);
return;
}
}else{
errCode = "Created file has been deleted"; // File was previously created but now is not found.
Log.v("TASK", "FILE DELETED");
Sharable.setShouldLook(true);
return;
}
} catch (IOException e) {
errCode = e.getLocalizedMessage();
Sharable.setShouldLook(true);
Log.v("TASK", e.getLocalizedMessage());
}
}
//------------------------------------------------------------------------------
private void writeToFile(RandomAccessFile file){
NetworkInfo wifi = Sharable.connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo mobile = Sharable.connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
URL u;
HttpURLConnection httpCon = null;
try {
byte[] buffer = new byte[2 * 1024]; // 2 MB buffer
long bytesWritten = 0;
if(contentLength.get() == 0){ // new file ?
u = new URL(url); // make a URL
httpCon = (HttpURLConnection) u.openConnection(); // Get ready to make a connection via HTTP
httpCon.setDoInput(true); // this connection will download data
httpCon.connect(); // make a connection
BufferedInputStream buf = new BufferedInputStream(httpCon.getInputStream()); // get a stream
contentLength.addAndGet(httpCon.getContentLength()); // set content length
while((bytesWritten = buf.read(buffer)) != -1 ){
if(Sharable.networkOption == NetworkOptions.WIFI_ONLY){
if(!wifi.isConnected()){ // check WiFi connectivity
setReadiness(false);
Sharable.setShouldLook(true);
break;
}
}
Log.v("TASK", "Writing at location " + this.bytesWritten.get());
file.write(buffer);
this.bytesWritten.addAndGet(bytesWritten);
String update = "UPDATE tasks SET byteswritten=" + this.bytesWritten.get() +
" ,contentlength=" + this.contentLength.get() +
" WHERE url='" + url + "'";
Sharable.db.execSQL(update); // write data to database
Sharable.handler.post(new Runnable(){
@Override
public void run() {
Sharable.adapter.notifyDataSetChanged(); // update the display
}
});
if(isInterrupted()){
setReadiness(true);
Sharable.setShouldLook(true);
break;
}
}
}else{ // not a new file
file.seek(this.bytesWritten.get()); // seek to proper position
u = new URL(url); // make a URL
httpCon = (HttpURLConnection) u.openConnection(); // Get ready to make a connection via HTTP
httpCon.setDoInput(true); // this connection will download data
httpCon.setRequestProperty("Range:", "bytes="+this.bytesWritten.get()+"-");
httpCon.connect(); // make a connection
if(httpCon.getResponseCode() != HttpURLConnection.HTTP_PARTIAL){ // check if partial download supported
errCode = "206 Not Supported";
setReadiness(false);
Sharable.setShouldLook(true);
return;
}
BufferedInputStream buf = new BufferedInputStream(httpCon.getInputStream()); // get a stream
while((bytesWritten = buf.read(buffer)) != -1 ){ // start downlading
if(Sharable.networkOption == NetworkOptions.WIFI_ONLY){
if(!wifi.isConnected()){ // check WiFi connectivity
setReadiness(false);
Sharable.setShouldLook(true);
if(httpCon != null){
httpCon.disconnect();
}
break;
}
}
Log.v("TASK", "Writing at location " + this.bytesWritten.get());
file.write(buffer);
this.bytesWritten.addAndGet(bytesWritten);
String update = "UPDATE tasks SET byteswritten=" + this.bytesWritten.get() +
" ,contentlength=" + this.contentLength.get() +
" WHERE url='" + url + "'";
Sharable.db.execSQL(update); // write data to database
Sharable.handler.post(new Runnable(){
@Override
public void run() {
Sharable.adapter.notifyDataSetChanged(); // update the display
}
});
if(isInterrupted()){ // check for thread interruption
setReadiness(true);
Sharable.setShouldLook(true);
break;
}
}
}
} catch (MalformedURLException e) {
errCode = e.getMessage();
Log.v("TASK", e.getLocalizedMessage());
} catch (IOException e) {
errCode = e.getLocalizedMessage();
Log.v("TASK", e.getLocalizedMessage());
}catch(Exception e){
errCode = e.getLocalizedMessage();
Log.v("TASK", e.getLocalizedMessage());
}
}
//------------------------------------------------------------------------------
public synchronized float getProgress(){
if(contentLength.get() != -1 && contentLength.get() != 0){
return (bytesWritten.get()*100)/contentLength.get();
}else{
return -1;
}
}
//------------------------------------------------------------------------------
public synchronized boolean getReadiness(){
return isReady;
}
//------------------------------------------------------------------------------
public synchronized void setReadiness(boolean ready){
isReady = ready;
}
//------------------------------------------------------------------------------
public synchronized String getStatus(){
return errCode;
}
//------------------------------------------------------------------------------
public synchronized String getTaskName(){
return name;
}
//------------------------------------------------------------------------------
@Override
public String toString(){
return name;
}
//------------------------------------------------------------------------------
}
然而,问题是部分下载永远不会开始......我不知道为什么。我通常最终没有任何活动或出现206 Not Supported
错误。
您可能感兴趣的其他类是Sharable
包含单例实例的类:
Sharable.java 和Scheduler.java
如何恢复部分下载?