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有关比较耗时的操作放到一个子线程里。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章