Android第九讲——网络(四) 文件的下载(单线程下载、多线程下载)

我们学习了连接网络与服务器后不只是仅仅上一些网页,与服务器进行交流。我们还可以从网上下载文件(Download)

文件的下载分为多种:
1.单线程下载
2.多线程下载
3.多线程断点续传

单线程下载

首先我们来看单线程下载:
文件的下载需要时间的,所以文件的Download属于耗时操作,故而不能将它放在UI主线程中,也是需要Handler或者异步线程(AsyncTask)
本次为AsyncTask
1.首先显示连接服务器。
2.通过GetContentLength获取要下载的文件的长度。
3.得到输入流,用来读取文件。
4.创建文件名
5.通过FileOutputStream(file)向创建的文件中写入下载的文件
6.UI主线程调用异步线程

    /**
     * 单线程下载的线程
     */
    class DownLoadSingleTask extends AsyncTask<String,Integer,String>{

        @Override
        protected String doInBackground(String... params) {
            try {
                URL url = new URL("http://192.168.***.**:8080/HTTpTest_Servelet/music/SetMeFree.mp3");
                URLConnection connection = url.openConnection();
                int length =connection.getContentLength();//获取内容的长度
                InputStream is = connection.getInputStream();
                File file = new File(Environment.getExternalStorageDirectory(),"Set Me Free.mp3");//创建文件夹
                if (!file.exists()){
                    file.createNewFile();
                }
                FileOutputStream fos = new FileOutputStream(file);
                byte[] array = new byte[1024];//缓存区,用于缓存读取的数据
                int i = is.read(array);
                int sum = 0;
                while (i!=-1){
                    fos.write(array);
                    sum += i;
                    publishProgress(length,sum);
                    i = is.read(array);
                }
                fos.flush();
                fos.close();
                is.close();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

在UI主线程中调用AsyncTask

            case R.id.button_download_single:
                DownLoadSingleTask task = new DownLoadSingleTask();
                task.execute();
                break;

多线程下载

有时文件较大,用一个线程下载文件时会消耗很多时间,通过多线程能够缩短文件下载的时间。
多线程的工作流程:(三线程的)
多线程下载:用for循环创建多个线程
打开网络连接—>得到数据长度—>长度除以线程数—>写入文件
connection.setRequestProperty(“Range”, “bytes=” + start + “-” + end);//设置头信息的,比如格式,UA等,不设置自然有默认的,一般的请求倒不需要去设置,可以去看看android里的DefaultHttpClient里也有设置头信息的
RandomAccessFile (文件路径,”rw”)
seek(start) 之后再写文件
这里写图片描述
1.主线程调一个线程为了用来连接网络(服务器)
2.单独写一个线程,用来多线程下载。主要有文件地址url,每个线程下载的起始位置start,每个线程下载的末尾位置end,下载后的文件File

/**
 * 多线程下载的线程
 * Created by Went_Gone on 2015/9/12.
 */
public class MulitDownloadThread extends Thread{
    private int start;
    private int end;
    private String urlPath;
    private File file;
    private int sum;

    public int getSum() {
        return sum;
    }

    public MulitDownloadThread( int start, int end, String urlPath, File file) {
        this.start = start;
        this.end = end;
        this.urlPath = urlPath;
        this.file = file;
    }

    @Override
    public void run() {
        try {
            URL url = new URL(urlPath);
            URLConnection connection = url.openConnection();
            connection.setAllowUserInteraction(true);
            connection.setRequestProperty("Range", "bytes=" + start + "-" + end);//设置头信息的,比如格式,UA等,不设置自然有默认的,一般的请求倒不需要去设置,可以去看看android里的DefaultHttpClient里也有设置头信息的
            InputStream is = connection.getInputStream();
            RandomAccessFile raf = new RandomAccessFile(file.getAbsolutePath(),"rw");//随机访问文件的读写,第一个参数是文件的路径
            raf.seek(start);
            byte[] array = new byte[1024];
            int index = is.read(array);
            while (index!=-1){
                raf.write(array,0,index);
                sum+=index;
                index = is.read(array);
            }
            Log.d("Mulit",this.getName()+"  "+sum+"");//用来检验是不是多线程下载
            raf.close();
            is.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在Activity中。

    /**
     * 多线程下载
     */
    private void MulitDownload() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String urlPath = "http://192.168.***.*:8080/HTTpTest_Servelet/music/SetMeFree.mp3";
//                    String urlPath = "http://img1.cache.netease.com/catchpic/6/6C/6C1F6740B3ECD7CC23C9E70B0C04B6C0.jpg";
//                    String urlPath = "http://p.gdown.baidu.com/a7171b404c2b222af1cb5a3eca249e36e4ffb41e33c741e8fee67227b09cfd84cf4d133189ea79f032759a367b6d3dda9658d02aae07f2b8dc82b1c2c1169460e528cbd7742a45f9e7fe69eb61959bf3e9e537b5cb5f221b49366ca7af9d625ec9b0d991e96240723ddbfad0177b32ae8ab3c4903216bf582093102d7e6c0d3e78658f3a92c078ffe4dc7ed9e29a20192eba2f785430ca3b4c7b695578dd010ad7fcc6499ee3cfa2bed4d0ba07edaa1097957a4a96ee7e397976dc6060f9902ee34f85506a484274";
                    URL url = new URL(urlPath);
                    URLConnection connection = url.openConnection();
                    length =connection.getContentLength();//获取内容的长度
                    File file = new File(Environment.getExternalStorageDirectory(),"Set Me Free aa.mp3");
//                    File file = new File(Environment.getExternalStorageDirectory(),"tanyan.jpg");
//                    File file = new File(Environment.getExternalStorageDirectory(),"QQyinyue.apk");
                    if (!file.exists()){
                        file.createNewFile();
                    }
                    MulitDownloadThread[] threads = new MulitDownloadThread[3];//用于管理下载线程
                    for (int i = 0;i<3;i++) {
                        MulitDownloadThread thread = null;
                        if (i==2){
                            thread = new MulitDownloadThread(length / 3 * 2, length, urlPath, file);
                        }else {
                            thread = new MulitDownloadThread(length / 3 * i, length / 3 * (i + 1)-1, urlPath, file);
                        }
                        thread.start();
                        threads[i] = thread;
                    }
                    boolean isFinish = true;
                    int sum = 0;
                    while (isFinish){
                        for (MulitDownloadThread thread:threads) {
                            sum += thread.getSum();
                        }
                        Message msg = handler.obtainMessage();
                        msg.what = MULITE;
                        msg.arg1 = sum;
                        handler.sendMessage(msg);
                        if (sum==length){
                            isFinish = false;
                        }
                        Thread.sleep(200);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

UI主线程中不能使用其他线程控制View,这里用Handler

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MULITE:
                    mProgressBar.setProgress((int) (msg.arg1*100.0/length));
                    break;
            }
        }
    };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android平台上实现多线程下载音乐可以通过以下步骤: 1. 首先,在AndroidManifest.xml文件添加访问网络的权限。 2. 创建一个Service来执行下载任务,这样可以保证在活动销毁或离开前台时下载任务仍然可以继续。 3. 在Service创建线程池,可以使用Java的Executor框架来实现,例如ThreadPoolExecutor。 4. 在要进行下载的Activity,通过按钮点击或其他触发方式来启动Service,并传递音乐下载链接等参数。 5. 在Service的onStartCommand方法,从传递过来的参数获取音乐下载链接,然后根据需求将链接拆分为多个部分。 6. 使用多线程分别下载这些部分,每个线程可以使用Java的URLConnection或HttpClient等工具类库进行网络请求。 7. 下载完成后,将每个部分的数据合并为完整的音乐文件。 8. 在下载过程,可以使用BroadcastReceiver来发送下载进度或状态的广播,然后在Activity注册该广播接收器来更新UI界面。 9. 在下载过程,可以通过判断当前网络状态来控制下载速度,例如在移动数据网络下可限制下载速度,而在WIFI网络下可充分利用带宽。 10. 需要注意的是,下载过程要处理异常情况,例如网络断、服务器异常等,可以使用try-catch块来捕获异常并进行相应的处理。 以上就是Android平台上实现多线程下载音乐的大致步骤,通过合理地利用多线程技术,可以加快下载速度,提升用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值