网络技术之——网络连接URLConnection、单/多线程下载
来源:互联网 发布:js给input添加样式 编辑:程序博客网 时间:2024/06/05 00:49
“网络连接”:
android中的HTTP的网络连接中HttpURLConnection方法和java中的HttpURLConnection用法是一致的,参考:
day0812-doGet和doPost
但在6.0之后,舍弃了HttpClient方法。
1.概述:
网络连接不允许在主线程中进行(3.0之前是允许的),所以通常情况我们都利用异步来操作,方式,利用Handler和AsyncTask.
这里我们介绍三种方式来访问网络:
普通URLConnection和HTTP协议访问(http访问包括HttpURLConnection和HttpClient两种)
2.用法:
URLConnection:
**<一>使用步骤:
注:在子线程中连接服务器。
1)获取URLConnection实例:
URL url = new URL("http://192.168.0.74:8080/myServer/Myserverlet");URLConnection connection = url.openConnection();
2)获得服务器返回的输入流
InputStream is = connection.getInputStream();
3)接下来,就是对数据流进行读取。
4)最后别忘了,联网需要权限的设置:
**<二>范例:
功能:利用URLConnection连接服务器,并将从服务器返回的的数据显示到textview中。
思路:先建立子线程,连接服务器,由于线程中获得的数据需要传给活动,绘制Textview,所以采用异步中的Handler方法主活动接收消息。
1.连接网络:
这里将获得的数据存到buffer缓存中,获得主线程的Handler,并发送。最后别忘了关闭流。
注:这里连接的是自己创建的服务器,但由于用手机模拟器模拟,其本身也是有地址的,所以不能用localhost,要用电脑主机地址。
2.开启线程:
一定不要忘了start线程。
3.创建主活动中的Handler子类:
效果图:
HttpURLConnection:
**<一>使用步骤:
HttpURLConnection与URLConnection用法基本相同:
1)获得实例:
URL url = new URL("http://192.168.0.74:8080/myServer/Myserverlet");HttpURLConnection connection = (HttpURLConnection)url.openConnection();
2)设置HTTP请求的方式(GET和POST)以及其他自由定制:
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);connection.setReadTimeout(8000);
3)获得输入流并进行读取。
InputStream is = connection.getInputStream();
4)最后关闭HTTP连接:
connection.disconnect();
5)权限不要忘了。
**<二>更改上面范例:
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();
“下载文件”:
单线程下载:
1)方法:
下载一般放在后台,即开启服务去进行,且需要开启一个新的线程。
2)范例:单线程下载服务器文件
功能:
服务器中有一音乐文件,地址为: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
- 网络技术之——网络连接URLConnection、单/多线程下载
- 网络连接——文件下载(单线程/多线程)
- URLConnection,单线程下载,多线程下载
- Android 网络连接——URLConnection
- 第三十六天 网络连接、单线程、多线程下载
- 网络编程(2)——连接父类URLConnection
- Android0912<十七>(Android 网络URLConnection)(ing多线程下载)
- Android网络连接----使用URLConnection实现从服务器上下载
- Android第九讲——网络(四) 文件的下载(单线程下载、多线程下载)
- Android网络连接---多线程下载
- android网络之URLconnection
- okhttp与urlconnection连接网络
- 网络连接2 单线程和多线程下载 并更新progressbar
- Android——单、多线程下载
- 使用网络技术—网络图片查看器
- java网络编程:RandomAccessFile, URLConnection和多线程机制实现了Http下载
- android网络应用2——URLConnection
- android网络应用2——URLConnection
- Spring详细教程
- 关于UICollectionViewController
- 基于CCA的图像文本交叉检索
- memcached集群部署
- JExcelApi使用记录
- 网络技术之——网络连接URLConnection、单/多线程下载
- OpenGL中三维物体显示在二维屏幕上显示的变换过程
- android 修改图片的宽高
- delete指针之后应该赋值NULL
- 借做项目的机会开始分享javaee的一些相关知识
- 开启服务和绑定服务
- Memcached与Spring AOP构建分布式数据库前端缓存框架
- UNIX环境高级编程之第8章:进程控制-习题
- 关于ios使用NSLocalizedString本地化