android中的HTTP的网络连接中HttpURLConnection方法和java中的HttpURLConnection用法是一致的,参考:
day0812-doGet和doPost
但在6.0之后,舍弃了HttpClient方法。
网络连接不允许在主线程中进行(3.0之前是允许的),所以通常情况我们都利用异步来操作,方式,利用Handler和AsyncTask.
这里我们介绍三种方式来访问网络:
普通URLConnection和HTTP协议访问(http访问包括HttpURLConnection和HttpClient两种)
**<一>使用步骤:
注:在子线程中连接服务器。
URL url = new URL("http://192.168.0.74:8080/myServer/Myserverlet");
URLConnection connection = url.openConnection();
InputStream is = connection.getInputStream();
**<二>范例:
功能:利用URLConnection连接服务器,并将从服务器返回的的数据显示到textview中。
思路:先建立子线程,连接服务器,由于线程中获得的数据需要传给活动,绘制Textview,所以采用异步中的Handler方法主活动接收消息。
1.连接网络:
这里将获得的数据存到buffer缓存中,获得主线程的Handler,并发送。最后别忘了关闭流。
注:这里连接的是自己创建的服务器,但由于用手机模拟器模拟,其本身也是有地址的,所以不能用localhost,要用电脑主机地址。
2.开启线程:
一定不要忘了start线程。
3.创建主活动中的Handler子类:
效果图:
**<一>使用步骤:
HttpURLConnection与URLConnection用法基本相同:
URL url = new URL("http://192.168.0.74:8080/myServer/Myserverlet");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream is = connection.getInputStream();
connection.disconnect();
**<二>更改上面范例:
doGet:
URL url = new URL("http://360.com");
URLConnection connect = (URLConnection) url.openConnection();
// 3.强制造型成httpUrlConnection
HttpURLConnection httpConnection = (HttpURLConnection) connect;
// 4.设置请求方式
httpConnection.setRequestMethod("GET");
httpConnection.setConnectTimeout(3000);// 连接chaoshi
httpConnection.setReadTimeout(3000); // 等待返回时间超时
InputStream is = httpConnection.getInputStream();
下载一般放在后台,即开启服务去进行,且需要开启一个新的线程。
功能:
服务器中有一音乐文件,地址为:http://192.168.0.74:8080/myServer/music/apple.mp3
这里采用单线程去下载,此例使用AsyncTask异步线程的方法,当然也可以使用Handler去开启一个异步线程。
下载文件的线程:
//创建一个线程下载文件,利用AsyncTask
class MyAsyncTask extends AsyncTask<String, Integer, String>{
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
int progress = (int)((values[0]*(100.0))/values[1]);
Log.d("message", values[1]+""+values[0]);
//proBar.setMax(values[1]);//利用比例来调整bar的值,并不用设置setmax。
proBar.setProgress(progress);
}
@Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
try {
URL uri = new URL("http://192.168.0.74:8080/myServer/music/apple.mp3");
URLConnection connection = uri.openConnection();// 建立连接
int length = connection.getContentLength();//获得文件总长度
InputStream is = connection.getInputStream();//获得流
//输出流,写到自己文件中
File file = new File(Environment.getExternalStorageDirectory(),"apple3.mp3");
//判断文件是否存在了
if(!file.exists()){
file.createNewFile();
}
FileOutputStream os = new FileOutputStream(file);
byte[] array = new byte[1024];//写到数组中
int sum = 0;//写入的总长度
int index = is.read(array);
while(index!=-1){
os.write(array, 0, index);
sum+=index;//长度变化
index=is.read(array);
publishProgress(sum,length);//将下载进度和总长度传到onProgressUpdate方法中改吧seekbar
}
os.flush();
os.close();
is.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
};
分析:将下载的进程传到onProgressUpdate方法中进行更新,传过来的参数还有文件的总长度:
进度条进度的设置,设置成百分比:
进度*100.0/总长度
点击事件中开启线程:
读写权限:
注:下载后的文件所存放的位置在输出流的地址文件中,即:
File file = new File(Environment.getExternalStorageDirectory(),"apple3.mp3");
设置了下载到文件在SD卡下:apple.mp3文件中
思路:建立一个线程,专门用于打开连接,并开启其他多个线程进行下载,每个线程分管一段,但往往并不能正好分完,所以最后一个线程可以将剩余的全部下载完。
1)建立线程,打开连接,并开启其他线程进行下载。这里进行的其他操作是,需要将用于下载的线程存储到数组中,用于开启后,每秒得到所有线程的进度总和
new Thread(new Runnable() {
@Override
public void run() {
try {
String urlPath="http://192.168.0.30:8080/MyWebTest/music/aa.mp3";
URL url = new URL(urlPath);
URLConnection connection=url.openConnection();//建立连接
length=connection.getContentLength();//获得文件长度
File file=new File(Environment.getExternalStorageDirectory(),"cc.mp3");//创建写入的路径
if(!file.exists()){
file.createNewFile();
}
MultiThread[] threads=new MultiThread[5];//建立一个数组用于存储5个线程
for (int i=0;i<5;i++){
MultiThread thread=null;//建立5个线程 ,MultiThread类是自定义的线程类****
if(i==4){
thread = new MultiThread(length / 5*4, length , urlPath, file.getAbsolutePath());
}else {
thread = new MultiThread(length / 5 * i, length / 5 * (i + 1)-1, urlPath, file.getAbsolutePath());
}
thread.start();
threads[i]=thread;
}
/*获取各个线程下载的进程的总和,显示到进度条,用于上面存到数组中的线程*/
boolean isFinish=true;
while(isFinish){
int sum=0;
for (MultiThread thread:threads){//获得每个线程中的进程,getSum方法
sum+= thread.getSum();
}
Message msg= handler.obtainMessage();//用handler将获得的进度和传给活动,并显示
msg.what=0x23;
msg.arg1=sum;
handler.sendMessage(msg);
if(sum+10>=length){//为避免死循环,当下载到文件中长度时停止下载
isFinish=false;
}
Thread.sleep(1000);//每休眠1s一获得每个线程的下载进度
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
注:thread = new MultiThread(length / 5 * i, length / 5 * (i + 1)-1, urlPath, file.getAbsolutePath());
由于setRequestProperty是包前包后的,所以这里在传入start和end时,end应该-1.
2)用于下载的线程:这里创建 了5个
public class MultiThread extends Thread{
/*创建构造器,需要传入下载的开始位置,结束位置,要下载的url地址,以及下载到的地址 */
public MultiThread(long start, long end, String url, String filePath) {
this.start = start;
this.end = end;
this.urlPath = url;
this.filePath = filePath;
}
private int sum=0;//用于记录每个线程下载的进度
private long start;
private long end;
private String urlPath;
private String filePath;
public int getSum() {//用于获得该线程的下载进度
return sum;
}
@Override
public void run() {
try {
URL url=new URL(urlPath);
URLConnection connection=url.openConnection();
/*下载指定位置文件*/
connection.setAllowUserInteraction(true);
connection.setRequestProperty("Range", "bytes=" + start + "-"
+ end);
InputStream is= connection.getInputStream();
byte [] array=new byte[1024];
is.read(array);
File file=new File(filePath);
/*下载到指定的位置,即从文件的哪里开始写入*/
RandomAccessFile randomAccessFileile=new RandomAccessFile(file,"rw");
randomAccessFileile.seek(start);
int index=is.read(array);
while (index!=-1){
randomAccessFileile.write(array,0,index);
sum+=index;
index=is.read(array);
}
randomAccessFileile.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
特殊的代码:从指定的开始位置和结束位置进行下载setRequestProperty方法
从指定位置开始写入:RandomAccessFile类
3)活动接收进度值,并显示到进度条中:
效果演示:
注:
1>先打开服务器,否则无法下载其路径下的文件。
2>且路径“http://192.168.0.74:8080/myServer/music/apple.mp3”
myServer:是服务器名称,
music/apple.mp3:music文件夹下的apple.mp3