Android 下载的三种实现方式(文件流的读写方式下载,用DownloadManager下载,用管道的方式下载)

Android下载方式中,我对自己使用过的三种实现方式进行比较如下:

  1. 文件流的读写方式下载,连接URL的InputStream一边读数据,一边写到Android的本地存储器文件中。
  2. 用Android自带的DownloadManager实现下载。
  3. 用管道的方式来实现下载。

下面先讲一下第一种实现方式:
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                  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);  
}

在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();
}
       }
}
   
    }


管道之间的实现代码如下:
                  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();  

管道的实现实现方式比较复杂,它必须启动两个线程,一个“读”线程,一个“写“线程,各自的功能任务比较分明。






他们之间的各自的优势:
1.普通下载方式比较直接,比较容易理解。
2.DownloadManager下载方式比较简单,并且把现在记录保存到Android自带的Downloads 应用程序中,但是DownloadManager出现在API 9中,就是在API 9及更改版本才可用。
3.管道主要用于线程之间的通信。


你可能感兴趣的:(Android)