Android下载方式中,我对自己使用过的三种实现方式进行比较如下:
- 文件流的读写方式下载,连接URL的InputStream一边读数据,一边写到Android的本地存储器文件中。
- 用Android自带的DownloadManager实现下载。
- 用管道的方式来实现下载。
下面先讲一下第一种实现方式:
private void normalDownload(String strUrl){
URL url = null;
HttpURLConnection httpURLConnection = null;
InputStream inputStream = null;
FileOutputStream outputStream = null;
int fileSize = 0;
int curSize =0;
// 文件保存路径
String path = Environment.getExternalStorageDirectory().getPath();
// 文件名
String fileName = strUrl.substring(strUrl.lastIndexOf('/'));
try {
// 设置断点续传的开始位置
url = new URL(strUrl);
httpURLConnection = (HttpURLConnection)url.openConnection();
inputStream = httpURLConnection.getInputStream();
fileSize = inputStream.available();
File outFile = new File(path+fileName);
outputStream = new FileOutputStream(outFile);
byte[] buf = new byte[1024*100];
int read = 0;
//curSize = startPosition;
while(curSize<fileSize) {
read = inputStream.read(buf);
if(read==-1) {
break;
}
outputStream.write(buf,0,read);
curSize+=read;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Download", Toast.LENGTH_LONG).show();
}
});
inputStream.close();
outputStream.close();
httpURLConnection.disconnect();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if(inputStream!=null) {
try {
inputStream.close();
if(outputStream!=null) {
outputStream.close();
}
if(httpURLConnection!=null) {
httpURLConnection.disconnect();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
URL url = null;
HttpURLConnection httpURLConnection = null;
InputStream inputStream = null;
FileOutputStream outputStream = null;
int fileSize = 0;
int curSize =0;
// 文件保存路径
String path = Environment.getExternalStorageDirectory().getPath();
// 文件名
String fileName = strUrl.substring(strUrl.lastIndexOf('/'));
try {
// 设置断点续传的开始位置
url = new URL(strUrl);
httpURLConnection = (HttpURLConnection)url.openConnection();
inputStream = httpURLConnection.getInputStream();
fileSize = inputStream.available();
File outFile = new File(path+fileName);
outputStream = new FileOutputStream(outFile);
byte[] buf = new byte[1024*100];
int read = 0;
//curSize = startPosition;
while(curSize<fileSize) {
read = inputStream.read(buf);
if(read==-1) {
break;
}
outputStream.write(buf,0,read);
curSize+=read;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Download", Toast.LENGTH_LONG).show();
}
});
inputStream.close();
outputStream.close();
httpURLConnection.disconnect();
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if(inputStream!=null) {
try {
inputStream.close();
if(outputStream!=null) {
outputStream.close();
}
if(httpURLConnection!=null) {
httpURLConnection.disconnect();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
在Activity中用它下载要必须单独再启动一个线程,否则因为下载时间过长而出现ANP这种问题。
2.用DownloadManager来实现下载代码如下:
private void managerDownload(String strUrl){
DownloadManager.Request down=new DownloadManager.Request (Uri.parse("http://commondatastorage.googleapis.com/androiddevelopers/shareables/icon_templates-v4.0.zip"));
//设置允许使用的网络类型,这里是移动网络和wifi都可以
down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE|DownloadManager.Request.NETWORK_WIFI);
//禁止发出通知,既后台下载
down.setShowRunningNotification(false);
//不显示下载界面
down.setVisibleInDownloadsUi(false);
//设置下载后文件存放的位置 放到内存卡下面的tt文件夹下面
down.setDestinationInExternalPublicDir("tt", "icon_templates-v4.0.zip");
//将下载请求放入队列
manager.enqueue(down);
//设置允许使用的网络类型,这里是移动网络和wifi都可以
down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE|DownloadManager.Request.NETWORK_WIFI);
//禁止发出通知,既后台下载
down.setShowRunningNotification(false);
//不显示下载界面
down.setVisibleInDownloadsUi(false);
//设置下载后文件存放的位置 放到内存卡下面的tt文件夹下面
down.setDestinationInExternalPublicDir("tt", "icon_templates-v4.0.zip");
//将下载请求放入队列
manager.enqueue(down);
}
在Activity中用它下载不必必须单独再启动一个线程,直接调用此方法就可以了,应为DownloadManager会自己启动一个线程来下载。
3.用管道来实现的代码如下:
两个线程类如下:
public class Reader extends Thread{
private String downloadUrl;
InputStream inputStream = null;
HttpURLConnection httpURLConnection;
public Reader(String downloadUrl) {
super();
this.downloadUrl = downloadUrl;
}
private PipedOutputStream outputStream = new PipedOutputStream(); //首先先创建一个发送对象
public PipedOutputStream getOutputStream() { //得到输出流
return outputStream;
}
@Override
public void run() {
URL url= null;
try {
url = new URL(downloadUrl);
httpURLConnection = (HttpURLConnection)url.openConnection();
inputStream = httpURLConnection.getInputStream();
byte[] buf = new byte[1024];
int read = 0;
while(true) {
read = inputStream.read(buf);
if(read==-1) {
break;
}
outputStream.write(buf,0,read);
// 当调用这个方法的时候会自动去调用onProgressUpdate方法,传递下载进度
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Download Done!", Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
try {
outputStream.close();
inputStream.close();
httpURLConnection.disconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Writer extends Thread{
private PipedInputStream inputStream = new PipedInputStream();// 读取对象
private FileOutputStream outputStream;
private String strUrl;
public Writer(String strUrl) {
super();
this.strUrl = strUrl;
}
public PipedInputStream getInputStream() {
return inputStream;
}
@Override
public void run() {
String path = Environment.getExternalStorageDirectory().getPath();
// 文件名
String fileName = strUrl.substring(strUrl.lastIndexOf('/'));
File outFile = new File(path+fileName);
// 使用java中的RandomAccessFile 对文件进行随机读写操作
byte[] buf = new byte[1024];
try {
outputStream = new FileOutputStream(outFile);
int read = 0;// 接收数据
while(true) {
read = inputStream.read(buf);
if(read==-1) {
break;
}
outputStream.write(buf,0,read);
// 当调用这个方法的时候会自动去调用onProgressUpdate方法,传递下载进度
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
inputStream.close();
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private String downloadUrl;
InputStream inputStream = null;
HttpURLConnection httpURLConnection;
public Reader(String downloadUrl) {
super();
this.downloadUrl = downloadUrl;
}
private PipedOutputStream outputStream = new PipedOutputStream(); //首先先创建一个发送对象
public PipedOutputStream getOutputStream() { //得到输出流
return outputStream;
}
@Override
public void run() {
URL url= null;
try {
url = new URL(downloadUrl);
httpURLConnection = (HttpURLConnection)url.openConnection();
inputStream = httpURLConnection.getInputStream();
byte[] buf = new byte[1024];
int read = 0;
while(true) {
read = inputStream.read(buf);
if(read==-1) {
break;
}
outputStream.write(buf,0,read);
// 当调用这个方法的时候会自动去调用onProgressUpdate方法,传递下载进度
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Download Done!", Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
try {
outputStream.close();
inputStream.close();
httpURLConnection.disconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Writer extends Thread{
private PipedInputStream inputStream = new PipedInputStream();// 读取对象
private FileOutputStream outputStream;
private String strUrl;
public Writer(String strUrl) {
super();
this.strUrl = strUrl;
}
public PipedInputStream getInputStream() {
return inputStream;
}
@Override
public void run() {
String path = Environment.getExternalStorageDirectory().getPath();
// 文件名
String fileName = strUrl.substring(strUrl.lastIndexOf('/'));
File outFile = new File(path+fileName);
// 使用java中的RandomAccessFile 对文件进行随机读写操作
byte[] buf = new byte[1024];
try {
outputStream = new FileOutputStream(outFile);
int read = 0;// 接收数据
while(true) {
read = inputStream.read(buf);
if(read==-1) {
break;
}
outputStream.write(buf,0,read);
// 当调用这个方法的时候会自动去调用onProgressUpdate方法,传递下载进度
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
inputStream.close();
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
管道之间的实现代码如下:
Reader reader = new Reader("http://commondatastorage.googleapis.com/androiddevelopers/shareables/icon_templates-v4.0.zip");
Writer writer = new Writer("http://commondatastorage.googleapis.com/androiddevelopers/shareables/icon_templates-v4.0.zip");
PipedOutputStream outputStream = reader.getOutputStream();
PipedInputStream inputStream = writer.getInputStream();
try {
//两个管道相连接
//inputStream.connect(outputStream); 这2种都可以
outputStream.connect(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
//启动线程
reader.start();
writer.start();
Writer writer = new Writer("http://commondatastorage.googleapis.com/androiddevelopers/shareables/icon_templates-v4.0.zip");
PipedOutputStream outputStream = reader.getOutputStream();
PipedInputStream inputStream = writer.getInputStream();
try {
//两个管道相连接
//inputStream.connect(outputStream); 这2种都可以
outputStream.connect(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
//启动线程
reader.start();
writer.start();
管道的实现实现方式比较复杂,它必须启动两个线程,一个“读”线程,一个“写“线程,各自的功能任务比较分明。
他们之间的各自的优势:
1.普通下载方式比较直接,比较容易理解。
2.DownloadManager下载方式比较简单,并且把现在记录保存到Android自带的Downloads 应用程序中,但是DownloadManager出现在API 9中,就是在API 9及更改版本才可用。
3.管道主要用于线程之间的通信。