对网络访问不太了解的新手,可以先看一下上一篇文章对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;
}
}
}