【Android基础】二、网络编程
2016-05-31 10:59
453 查看
1、从网络中下载图片,使用HttpURLConnection进行访问网络的操作
2.访问网络的操作不能放在主线程中,开一个子线程通过发送消息到UI线程,在UI线程修改界面
3.图片缓存到本地,直接从本地读取
BtmapFactory对象直接从File中解压位图对象,参数为File文件的绝对路径
3.从网络下载文本数据
这里使用字节数组输出流,读取输入流文本数据时,同步把数据写入字节数组输出流,直接通过字节数组输出流构造字符串返回,而不需要写入本地文件
4.使用POST方法提交数据
二、多线程下载
需要两次请求网络
第一次请求网络获得文件长度,并且创建一个RandomAccessFile对象生成空的临时文件,设置临时文件的大小为获取的资源文件的长度,并计算每一个线程下载文件的起始位置和结束位置。
第二次请求网络下载文件。通过Range属性设置线程的请求数据区间,请求部分数据成功的返回码为206,还需要设置写入文件的起始位置raf.seek()
断点续传:创建一个临时文件记录线程的下载进度,再次下载时读取临时文件,修改下载区间
使用到的输入输出流:
RandomAccessFile:可以设置写入的位置
FileOutputStream:直接写入文件中
ByteArrayOutputStream:写入的数据存储在一个字节数组中,转换成字节数组,创建字符串
InputStream:读取数据到一个字节数组中
BufferedReader:按行读取,返回一个String,参数是InputStreamReader(FileInputStream)
2.访问网络的操作不能放在主线程中,开一个子线程通过发送消息到UI线程,在UI线程修改界面
Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case 0: Toast.makeText(ImageActivity.this, "请求失败", Toast.LENGTH_SHORT).show(); break; case 1: ImageView imageView = (ImageView) findViewById(R.id.iv_pic); //把位图对象显示在ImageView imageView.setImageBitmap((Bitmap) msg.obj); break; default: break; } } };
public void download(View v) { new Thread(new Runnable() { @Override public void run() { //1.确定网址 String path = "http://192.168.56.1:8080/pic.jpg"; try { //2.把网址封装成一个URL对象 URL url = new URL(path); //3.获取客户端和服务端的连接对象,此时还没有建立连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //4.对连接对象进行初始化,设置请求方法,连接超时,读取超时 conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //5.发送请求,与服务端建立连接 conn.connect(); //如果响应码为200,说明连接成功 if (conn.getResponseCode() == 200) { //获取服务器响应头中的流,流的数据就是客户端请求的数据 InputStream is = conn.getInputStream(); //使用位图工厂对象从将流里的数据读取出来构造成位图对象 Bitmap bitmap = BitmapFactory.decodeStream(is); Message msg = new Message(); msg.obj = bitmap; msg.what = 1; handler.sendMessage(msg); } else { Message msg = Message.obtain(); msg.what = 0; handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); } } }).start(); }
3.图片缓存到本地,直接从本地读取
BtmapFactory对象直接从File中解压位图对象,参数为File文件的绝对路径
public void download(View v) { //1.确定网址 final String path = "http://192.168.56.1:8080/pic.jpg"; final File file = new File(getCacheDir(), "pic.jpg"); if (file.exists()) { Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); imageView.setImageBitmap(bitmap); } else { new Thread(new Runnable() { @Override public void run() { try { //2.把网址封装成一个URL对象 URL url = new URL(path); //3.获取客户端和服务端的连接对象,此时还没有建立连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //4.对连接对象进行初始化,设置请求方法,连接超时,读取超时 conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //5.发送请求,与服务端建立连接 conn.connect(); //如果响应码为200,说明连接成功 if (conn.getResponseCode() == 200) { //获取服务器响应头中的流,流的数据就是客户端请求的数据 InputStream is = conn.getInputStream(); //使用位图工厂对象从将文件里的数据读取出来构造成位图对象 FileOutputStream fos = new FileOutputStream(file); byte[] bytes = new byte[1024]; int len = 0; if ((len = is.read(bytes)) != -1) { fos.write(bytes,0,len); } fos.close(); Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); Message msg = new Message(); msg.obj = bitmap; msg.what = 1; handler.sendMessage(msg); } else { Message msg = Message.obtain(); msg.what = 0; handler.sendMessage(msg); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } 4000 }
3.从网络下载文本数据
这里使用字节数组输出流,读取输入流文本数据时,同步把数据写入字节数组输出流,直接通过字节数组输出流构造字符串返回,而不需要写入本地文件
public String getTextFromStream(InputStream is){ ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = 0; try { if((len = is.read(b))!=-1){ bos.write(b,0,len); } String text = new String(bos.toByteArray()); return text; } catch (IOException e) { e.printStackTrace(); } return null; }
4.使用POST方法提交数据
String data = ""; //添加POST请求的两行属性 conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); conn.setRequestProperty("Content-Length",data.length() + ""); //设置打开输出流,拿到输出流 conn.setDoOutput(true); OutputStream os = conn.getOutputStream(); //使用输出流往服务器提交数据 os.write(data.getBytes());
二、多线程下载
需要两次请求网络
第一次请求网络获得文件长度,并且创建一个RandomAccessFile对象生成空的临时文件,设置临时文件的大小为获取的资源文件的长度,并计算每一个线程下载文件的起始位置和结束位置。
public void download() { new Thread() { @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); conn.connect(); if (conn.getResponseCode() == 200) { //获得网络请求返回的流的字节长度 int length = conn.getContentLength(); File file = new File(Environment.getExternalStorageDirectory(),"QQ.exe"); //使用随机存文件对象生成临时文件 RandomAccessFile raf = new RandomAccessFile(file, "rwd"); //设置临时文件的大小 raf.setLength(length); //计算出每一个线程应该下载多少字节 int size = length / THREADCOUNT; for (int i = 0; i < THREADCOUNT; i++) { //计算每一个线程下载的起始位置和结束位置 int startIndex = i * size; int endIndex = (i + 1) * size - 1; if (i == THREADCOUNT - 1) { endIndex = length - 1; } new DownloadThread(startIndex, endIndex, i).start(); } } } catch (Exception e) { e.printStackTrace(); } } }.start(); }
第二次请求网络下载文件。通过Range属性设置线程的请求数据区间,请求部分数据成功的返回码为206,还需要设置写入文件的起始位置raf.seek()
断点续传:创建一个临时文件记录线程的下载进度,再次下载时读取临时文件,修改下载区间
class DownloadThread extends Thread { int startIndex; int endIndex; int threadId; public DownloadThread(int startIndex, int endIndex, int threadId) { this.startIndex = startIndex; this.endIndex = endIndex; this.threadId = threadId; } @Override public void run() { try { File progressFile = new File(threadId + ".txt"); if (progressFile.exists()) { FileInputStream fis = new FileInputStream(progressFile); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); startIndex += Integer.parseInt(br.readLine()); } URL url = new URL(MutiThreadActivity.path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); //设置本次请求的数据区间 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); if (conn.getResponseCode() == 206) { InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; int total = 0; File file = new File(Environment.getExternalStorageDirectory(),"QQ.exe"); RandomAccessFile raf = new RandomAccessFile(file, "rwd"); //设置写入文件的开始位置 raf.seek(startIndex); while ((len = is.read(b)) != -1) { raf.write(b, 0, len); total += len; RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd"); progressRaf.write((total + "").getBytes()); progressRaf.close(); } raf.close(); //全部下载完毕后删除临时记录文件 MutiThreadActivity.finishThread++; synchronized (MutiThreadActivity.path) { for (int i = 0; i < MutiThreadActivity.THREADCOUNT; i++) { File f = new File(threadId + ".txt"); f.delete(); } MutiThreadActivity.finishThread = 0; } } } catch (Exception e) { e.printStackTrace(); } } }
使用到的输入输出流:
RandomAccessFile:可以设置写入的位置
FileOutputStream:直接写入文件中
ByteArrayOutputStream:写入的数据存储在一个字节数组中,转换成字节数组,创建字符串
InputStream:读取数据到一个字节数组中
BufferedReader:按行读取,返回一个String,参数是InputStreamReader(FileInputStream)
相关文章推荐
- socket通过http上传下载
- 基于Libevent的HTTP Server
- HTTP状态码
- day⑩:事件驱动网络框架
- 说说http协议中的编码和解码
- 回调函数(http://www.cnblogs.com/this-543273659/archive/2011/07/20/2111815.html)
- 源码解析之--网络层YTKNetwork
- The type org.apache.http.HttpEntityEnclosingRequest cannot be resolved
- Wireshark基础实战视频课程
- [转载]Linux TCP/IP 协议栈源码分析
- HTTP 头部信息和错误码汇总详细解释,必收藏!
- 该伙伴事务管理器已经禁止了它对远程/网络事务的支持
- 以太网和交换机实战应用视频课程
- 以太网和交换机实战应用视频课程
- Web服务器处理HTTP压缩之gzip、deflate压缩
- 使用AFinal框架实现HTTP请求从网络获取数据
- 开源复杂网络分析软件中社团发现算法总结
- HTTPS学习总结
- JAVA SSL HTTPS 链接详解 生成证书
- TOMCAT 6/7 中配置HTTPS