Android上Java网络资源访问(二)使用HttpURLConnection多线程下载

6 篇文章 0 订阅
5 篇文章 0 订阅

对网络访问不太了解的新手,可以先看一下上一篇文章对URL的简单介绍:Android上Java网络资源访问(一)使用URL类访问

1.简介 

HttpURLConnection继承于URLConnection,可以访问指定网站,HttpURLConnection通过对URLConnection的封装,使开发者在使用的过程中能够更加的方便;

URLConnection类可以使用上篇文章介绍的URL类获取,方法如下:

URLConnection connection = realUrl.openConnection();

URLConnection有多种请求方式:

摘抄如下:

Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的4个操作。到这里,大家应该有个大概的了解了,GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。

具体参考文章:浅谈HTTP中Get与Post的区别
但是虽然URLConnection有多种交互方式,但是我们主要使用GET和POST这两种方式;

GET与POST请求。二者的区别主要在于:
a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
b:) post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。

2. 多线程下载实例

该实例使用android应用开发,编写一个多线程下载的工具类:DownUtil,在一个界面中,一个输入框输入下载文件的url地址,一个输入框设置下载的路径,一个button响应下载,一个进度条显示下载的进度;

具体代码如下:

xml的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.anana.sockettest.DownActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:text="要下载的资源的url:"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="2dp"/>

    <EditText
        android:id="@+id/url"
        android:layout_width="356dp"
        android:layout_height="47dp"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textView"
        android:layout_marginTop="12dp"
        android:text="http://m.down.sandai.net/MobileThunder/Android_5.44.2.1966/thunder-5.44.2.5060-stable-release-OfficialSite_XunLeiProductCenter.apk"
        tools:layout_editor_absoluteX="2dp"
        tools:layout_editor_absoluteY="32dp"/>

    <EditText
        android:id="@+id/target"
        android:layout_width="222dp"
        android:layout_height="25dp"
        android:layout_alignStart="@+id/download"
        android:layout_below="@+id/textView2"
        android:layout_marginTop="25dp"
        android:text="/mnt/sdcard/"
        tools:layout_editor_absoluteX="16dp"
        tools:layout_editor_absoluteY="117dp"
        android:layout_above="@+id/download"/>

    <Button
        android:id="@+id/download"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="19dp"
        android:text="下载"
        tools:layout_editor_absoluteX="16dp"
        tools:layout_editor_absoluteY="138dp"
        android:layout_above="@+id/downbar"
        android:layout_alignParentStart="true"/>

    <ProgressBar
        android:id="@+id/downbar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="270dp"
        android:layout_height="18dp"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        tools:layout_editor_absoluteX="16dp"
        tools:layout_editor_absoluteY="204dp"/>

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/download"
        android:layout_alignStart="@+id/downbar"
        android:layout_below="@+id/url"
        android:layout_marginTop="18dp"
        android:text="目标文件:"/>
</RelativeLayout>
activity主应用代码部分:

package com.anana.sockettest;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;

import com.anana.sockettest.util.DownUtil;

import java.util.Timer;
import java.util.TimerTask;

public class DownActivity extends AppCompatActivity
{

    private EditText url, target;
    private Button download;
    private ProgressBar bar;
    private Handler handler;
    private int mDownStatu;
    private DownUtil downUtil;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down);

        url = (EditText) findViewById(R.id.url);
        target = (EditText) findViewById(R.id.target);
        download = (Button) findViewById(R.id.download);
        bar = (ProgressBar) findViewById(R.id.downbar);

        handler = new Handler()
        {
            @Override
            public void handleMessage(Message msg)
            {
                if (msg.what == 33)
                {
                    System.out.println("mDownStatu:"+mDownStatu);
                    bar.setProgress(mDownStatu);
                }
                super.handleMessage(msg);
            }
        };

        download.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                downUtil = new DownUtil(url.getText().toString(), target.getText().toString(), 5);
                new Thread()
                {
                    @Override
                    public void run()
                    {
                        try
                        {
                            downUtil.download();
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }

                        final Timer timer = new Timer();
                        timer.schedule(new TimerTask()
                        {
                            @Override
                            public void run()
                            {
                                double completeRate = downUtil.getCompleteRate();
                                mDownStatu = (int) (completeRate * 100);
                                handler.sendEmptyMessage(33);
                                if (mDownStatu >= 100)
                                {
                                    timer.cancel();
                                }

                            }
                        }, 0, 1000);
                    }
                }.start();
            }
        });

    }
}

DownUtil类的编写,核心部分:

package com.anana.sockettest.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by wolfboyjiang on 2017/8/31.
 */

public class DownUtil
{
    private String path;
    private String targetFile;
    private int threadnum;
    private int fileSize;
    private DownThread[] threads;

    public DownUtil(String path, String targetFile, int threadnum)
    {
        this.path = path;
        this.targetFile = targetFile;
        this.threadnum = threadnum;
        threads = new DownThread[threadnum];
    }

    public void download() throws Exception
    {
        System.out.println("download start ,url:"+path);
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestMethod("GET");
        //设置通用的请求属性
        conn.setRequestProperty("Accept", "*/*");
        conn.setRequestProperty("Accept-Language", "UTF-8");
        conn.setRequestProperty("Connection", "Keep-Alive");
//        conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT
// 5.1; SV1)");
        fileSize = conn.getContentLength();
        conn.disconnect();
        int currentPartSize = fileSize / threadnum + 1;
        System.out.println("currentPartSize:"+currentPartSize+",currentPartSize:"+currentPartSize);
        RandomAccessFile file = new RandomAccessFile(targetFile, "rw");
        file.setLength(fileSize);
        file.close();
        for (int i = 0; i < threadnum; i++)
        {
            int startPos = i * currentPartSize;
            RandomAccessFile currentPart = new RandomAccessFile(targetFile, "rw");
            currentPart.seek(startPos);
            threads[i] = new DownThread(startPos, currentPartSize, currentPart);
            threads[i].start();

        }
    }

    public double getCompleteRate()
    {
        int sumSize = 0;
        for (int i = 0; i < threadnum; i++)
        {
            sumSize += threads[i].length;
        }
        System.out.println("fileSize:"+fileSize+",sumSize:"+sumSize);
        return sumSize * 1.0 / fileSize;
    }

    private class DownThread extends Thread
    {
        private int startPos = 0;
        private int currentPartSize;
        private RandomAccessFile currentpart;
        public int length = 0;

        public DownThread(int startPos, int currentPartSize, RandomAccessFile currentpart)
        {
            this.startPos = startPos;
            this.currentPartSize = currentPartSize;
            this.currentpart = currentpart;
        }

        @Override
        public void run()
        {
            try
            {
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5000);
                conn.setRequestMethod("GET");
                //设置通用的请求属性
                conn.setRequestProperty("Accept", "*/*");
                conn.setRequestProperty("Accept-Language", "UTF-8");
                conn.setRequestProperty("Connection", "Keep-Alive");

                InputStream in = conn.getInputStream();
                skipFully(in,this.startPos);

                byte[] buffer = new byte[1024];
                int hasRead = 0;
                while (length < currentPartSize && (hasRead = in.read(buffer)) > 0)
                {
                    currentpart.write(buffer,0,hasRead);
                    length += hasRead;
                }
                currentpart.close();
                in.close();

            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }


    }

    public static void skipFully(InputStream in, long bytes) throws IOException
    {
        long remainning = bytes;
        long len = 0;
        while (remainning > 0)
        {
            len = in.skip(remainning);
            remainning -= len;
        }
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值