Android開發之文件下載

下面是我寫的一個下載兩種不同類型文件的程序案例:

Download.java:
package com.mycompany.download;

import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import java.net.HttpURLConnection;

public class Download extends AppCompatActivity {
    private Button txtButton;
    private Button mp3Button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_download);

        txtButton = (Button)findViewById(R.id.txtButton);
        mp3Button = (Button)findViewById(R.id.mp3Button);

        txtButton.setOnClickListener(new txtButtonListener());
        mp3Button.setOnClickListener(new mp3ButtonListener());
    }
    class txtButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            Thread t = new MyThread1();
            t.start();
        }
    }
    class mp3ButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            Thread t = new MyThread2();
            t.start();
        }
    }

    class MyThread1 extends Thread{
        @Override
        public void run() {
            HttpDownloader httpDownloader = new HttpDownloader();
            String lrc = httpDownloader.download("http://qukufile2.qianqian.com/data2/lrc/2bd596497968b5286228bb8339326d82/261127925/261127925.lrc");
            System.out.println(lrc);
        }
    }
    class MyThread2 extends Thread{
        @Override
        public void run() {
            HttpDownloader httpDownloader = new HttpDownloader();
            int result = httpDownloader.downFile("http://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=http%3A%2F%2Fpic48.nipic.com%2Ffile%2F20140910%2F6365066_112611596403_2.jpg&thumburl=http%3A%2F%2Fimg0.imgtn.bdimg.com%2Fit%2Fu%3D2486202150%2C517659072%26fm%3D21%26gp%3D0.jpg","beauties/","2.jpg");  // 目錄加上"/"方便文件的創建
            System.out.println(result);
        }
    }
}
需要注意的是,如果直接將網絡下載的相關代碼放進OnCreate()方法中,Android Studio會提示主線程負擔過重,並且將會導致下載失敗,出現NetworkOnMainThreadException異常,原因是從Honeycomb SDK(3.0)開始,google不再允許網絡請求(HTTP、Socket)等相關操作直接在Main Thread類中。直接在UI線程進行網絡操作,會阻塞UI、降低用戶體驗。所以,在Honeycomb SDK(3.0)以下的版本,你還可以繼續在Main Thread裏這樣做,在3.0以上,就不行了,建議將和network有關比較耗時的操作放到一個子線程裏。


1.使用HTTP協議下載文件
文件下載步驟
1)創建一個HttpURLConnection對象
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
2)獲得一個InputStream對象
urlConn.getInputStream()
3)訪問網絡的權限
android.permission.INTERNET
2.將下載的文件寫入SDCARD



下載文本文件:(download()方法)
首先創建一個URL對象,將文件下載地址傳給該對象,然後利用url對象的openConnection()方法打開連接,並賦給一個HttpURLConnection對象。接着調用HttpURLConnection對象的getInputStream方法得到InputStream,然後利用IO流(BufferedReader對象和readLine()方法)讀取文件的數據至一個StringBuffer對象,最後將該對象轉換成String類型並返回。
    public String download(String urlStr){
        StringBuffer stringBuffer = new StringBuffer();
        String line;
        BufferedReader bufferedReader = null;
        try{
            // 創建一個URL對象
            url = new URL(urlStr);
            // 創建一個Http連接
            HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
            // 使用IO流讀取數據
            bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
            while ((line = bufferedReader.readLine()) != null){
                stringBuffer.append(line);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                bufferedReader.close();;
            }   catch (Exception e){
                e.printStackTrace();
            }
        }
        return stringBuffer.toString();
    }
注:用該方法下載的TXT文件並沒有保存到內存卡中,要想保存請使用下面的方法。

下載任何類型的文件:(downFile()方法)
    public int downFile(String urlStr, String path, String fileName){
        InputStream inputStream = null;
        try {
            FileUtils fileUtils = new FileUtils();

            if(fileUtils.isFileExist(path + fileName)){
                return 1;
            } else{
                inputStream = getInputStreamFromUrl(urlStr);
                File resultFile = fileUtils.write2SDFromInput(path,fileName,inputStream);
                if(resultFile == null){
                    return -1;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }finally {
            try {
                inputStream.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return 0;
    }

    // 根據URL得到輸入流
    // 該方法是創建URL對象、打開連接、得到InputStream過程的封裝
    public InputStream getInputStreamFromUrl(String urlStr) throws MalformedURLException,IOException{
        url = new URL(urlStr);
        HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
        InputStream inputStream = urlConn.getInputStream();
        return inputStream;
    }
}

以下是工具類:
FileUtils.java:
package com.mycompany.download;

import android.os.Environment;
import android.provider.ContactsContract;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Created by Administrator on 2016/8/14.
 */
public class FileUtils {
    private String SDPATH;

    public String getSDPATH(){
        return SDPATH;
    }

    public FileUtils (){
        // 得到SD卡的目錄
        SDPATH = Environment.getExternalStorageDirectory()  + "/";
    }

    // 在SD卡上創建文件
    public File creatSDFile(String fileName) throws IOException{
        File file = new File(SDPATH + fileName);
        file.createNewFile();
        return file;
    }

    // 在SD卡上創建目錄
    public File creatSDDir(String dirName){
        File dir = new File(SDPATH + dirName);
        dir.mkdir();
        return dir;
    }

    // 判斷SD卡上的文件夾是否存在
    public boolean isFileExist(String fileName){
        File file = new File(SDPATH + fileName);
        return file.exists();
    }

    // 將一個InputStream裏面的數據寫入到SD卡中
    public File write2SDFromInput(String path,String fileName,InputStream input){
        File file = null;
        OutputStream output = null;
        try{
            creatSDDir(path);
            file = creatSDFile(path + fileName);
            // 利用字節流將InputStream中的數據寫入到新建的文件中
            output = new FileOutputStream(file);
            byte[] buffer = new byte[4 * 1024];
            int len;
            while ((len=input.read(buffer))!= -1) {
                output.write(buffer,0,len);
            }
            output.flush();         // 清空緩存
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                output.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return file;
    }
}

HttpDownloader.java:
package com.mycompany.download;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by Administrator on 2016/8/14.
 */
public class HttpDownloader {
    private URL url = null;

    public String download(String urlStr){
        StringBuffer stringBuffer = new StringBuffer();
        String line;
        BufferedReader bufferedReader = null;
        try{
            // 創建一個URL對象
            url = new URL(urlStr);
            // 創建一個Http連接
            HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
            // 使用IO流讀取數據
            bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
            while ((line = bufferedReader.readLine()) != null){
                stringBuffer.append(line);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                bufferedReader.close();;
            }   catch (Exception e){
                e.printStackTrace();
            }
        }
        return stringBuffer.toString();
    }

    // 該函數返回 -1:代表下載文件出錯,0代表下載文件成功,1代表文件已經存在
    public int downFile(String urlStr, String path, String fileName){
        InputStream inputStream = null;
        try {
            FileUtils fileUtils = new FileUtils();

            if(fileUtils.isFileExist(path + fileName)){
                return 1;
            } else{
                inputStream = getInputStreamFromUrl(urlStr);
                File resultFile = fileUtils.write2SDFromInput(path,fileName,inputStream);
                if(resultFile == null){
                    return -1;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }finally {
            try {
                inputStream.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return 0;
    }

    // 根據URL得到輸入流
    // 該方法是創建URL對象、打開連接、得到InputStream過程的封裝
    public InputStream getInputStreamFromUrl(String urlStr) throws MalformedURLException,IOException{
        url = new URL(urlStr);
        HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
        InputStream inputStream = urlConn.getInputStream();
        return inputStream;
    }
}

最後不要忘記在AndroidManifest.java中添加兩個權限:
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

經測試,在API 19的機器上軟件運行正常,在API 23上則運行失敗。原因不詳。


需要注意的是,如果直接將網絡下載的相關代碼放進OnCreate()方法中,Android Studio會提示主線程負擔過重,並且將會導致下載失敗,出現NetworkOnMainThreadException異常,原因是從Honeycomb SDK(3.0)開始,google不再允許網絡請求(HTTP、Socket)等相關操作直接在Main Thread類中。直接在UI線程進行網絡操作,會阻塞UI、降低用戶體驗。所以,在Honeycomb SDK(3.0)以下的版本,你還可以繼續在Main Thread裏這樣做,在3.0以上,就不行了,建議將和network有關比較耗時的操作放到一個子線程裏。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章