HttpClient

发送get请求

  • 创建一个客户端对象

    HttpClient client = new DefaultHttpClient();

  • 创建一个get请求对象

    HttpGet hg = new HttpGet(path);

  • 发送get请求,建立连接,返回响应头对象

    HttpResponse hr = hc.execute(hg);

  • 获取状态行对象,获取状态码,如果为200则说明请求成功

    1. if(hr.getStatusLine().getStatusCode() == 200){
    2. //拿到服务器返回的输入流
    3. InputStream is = hr.getEntity().getContent();
    4. String text = Utils.getTextFromStream(is);
    5. }

发送post请求

  1. //创建一个客户端对象
  2. HttpClient client = new DefaultHttpClient();
  3. //创建一个post请求对象
  4. HttpPost hp = new HttpPost(path);
  • 往post对象里放入要提交给服务器的数据

    1. //要提交的数据以键值对的形式存在BasicNameValuePair对象中
    2. List<NameValuePair> parameters = new ArrayList<NameValuePair>();
    3. BasicNameValuePair bnvp = new BasicNameValuePair("name", name);
    4. BasicNameValuePair bnvp2 = new BasicNameValuePair("pass", pass);
    5. parameters.add(bnvp);
    6. parameters.add(bnvp2);
    7. //创建实体对象,指定进行URL编码的码表
    8. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, "utf-8");
    9. //为post请求设置实体
    10. hp.setEntity(entity);

异步HttpClient框架

发送get请求

  1. //创建异步的httpclient对象
  2. AsyncHttpClient ahc = new AsyncHttpClient();
  3. //发送get请求
  4. ahc.get(path, new MyHandler());
  • 注意AsyncHttpResponseHandler两个方法的调用时机

    1. class MyHandler extends AsyncHttpResponseHandler{
    2. //http请求成功,返回码为200,系统回调此方法
    3. @Override
    4. public void onSuccess(int statusCode, Header[] headers,
    5. //responseBody的内容就是服务器返回的数据
    6. byte[] responseBody) {
    7. Toast.makeText(MainActivity.this, new String(responseBody), 0).show();
    8. }
    9. //http请求失败,返回码不为200,系统回调此方法
    10. @Override
    11. public void onFailure(int statusCode, Header[] headers,
    12. byte[] responseBody, Throwable error) {
    13. Toast.makeText(MainActivity.this, "返回码不为200", 0).show();
    14. }
    15. }

发送post请求

  • 使用RequestParams对象封装要携带的数据

    1. //创建异步httpclient对象
    2. AsyncHttpClient ahc = new AsyncHttpClient();
    3. //创建RequestParams封装要携带的数据
    4. RequestParams rp = new RequestParams();
    5. rp.add("name", name);
    6. rp.add("pass", pass);
    7. //发送post请求
    8. ahc.post(path, rp, new MyHandler());

多线程下载

原理:服务器CPU分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服务器资源

确定每条线程下载多少数据

  • 发送http请求至下载地址

    1. String path = "http://192.168.1.102:8080/editplus.exe";
    2. URL url = new URL(path);
    3. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    4. conn.setReadTimeout(5000);
    5. conn.setConnectTimeout(5000);
    6. conn.setRequestMethod("GET");
  • 获取文件总长度,然后创建长度一致的临时文件

    1. if(conn.getResponseCode() == 200){
    2. //获得服务器流中数据的长度
    3. int length = conn.getContentLength();
    4. //创建一个临时文件存储下载的数据
    5. RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rwd");
    6. //设置临时文件的大小
    7. raf.setLength(length);
    8. raf.close();
  • 确定线程下载多少数据

    1. //计算每个线程下载多少数据
    2. int blockSize = length / THREAD_COUNT;

计算每条线程下载数据的开始位置和结束位置

  1. for(int id = 1; id <= 3; id++){
  2. //计算每个线程下载数据的开始位置和结束位置
  3. int startIndex = (id - 1) * blockSize;
  4. int endIndex = id * blockSize - 1;
  5. if(id == THREAD_COUNT){
  6. endIndex = length;
  7. }
  8. //开启线程,按照计算出来的开始结束位置开始下载数据
  9. new DownLoadThread(startIndex, endIndex, id).start();
  10. }

再次发送请求至下载地址,请求开始位置至结束位置的数据

  1. String path = "http://192.168.1.102:8080/editplus.exe";
  2. URL url = new URL(path);
  3. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  4. conn.setReadTimeout(5000);
  5. conn.setConnectTimeout(5000);
  6. conn.setRequestMethod("GET");
  7. //向服务器请求部分数据
  8. conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
  9. conn.connect();
  • 下载请求到的数据,存放至临时文件中

    1. if(conn.getResponseCode() == 206){
    2. InputStream is = conn.getInputStream();
    3. RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rwd");
    4. //指定从哪个位置开始存放数据
    5. raf.seek(startIndex);
    6. byte[] b = new byte[1024];
    7. int len;
    8. while((len = is.read(b)) != -1){
    9. raf.write(b, 0, len);
    10. }
    11. raf.close();
    12. }

带断点续传的多线程下载

  • 定义一个int变量记录每条线程下载的数据总长度,然后加上该线程的下载开始位置,得到的结果就是下次下载时,该线程的开始位置,把得到的结果存入缓存文件

    1. //用来记录当前线程总的下载长度
    2. int total = 0;
    3. while((len = is.read(b)) != -1){
    4. raf.write(b, 0, len);
    5. total += len;
    6. //每次下载都把新的下载位置写入缓存文本文件
    7. RandomAccessFile raf2 = new RandomAccessFile(threadId + ".txt", "rwd");
    8. raf2.write((startIndex + total + "").getBytes());
    9. raf2.close();
    10. }
  • 下次下载开始时,先读取缓存文件中的值,得到的值就是该线程新的开始位置

    1. FileInputStream fis = new FileInputStream(file);
    2. BufferedReader br = new BufferedReader(new InputStreamReader(fis));
    3. String text = br.readLine();
    4. int newStartIndex = Integer.parseInt(text);
    5. //把读到的值作为新的开始位置
    6. startIndex = newStartIndex;
    7. fis.close();
  • 三条线程都下载完毕之后,删除缓存文件

    1. RUNNING_THREAD--;
    2. if(RUNNING_THREAD == 0){
    3. for(int i = 0; i <= 3; i++){
    4. File f = new File(i + ".txt");
    5. f.delete();
    6. }
    7. }

手机版的断点续传多线程下载器

  • 把刚才的代码直接粘贴过来就能用,记得在访问文件时的路径要改成Android的目录,添加访问网络和外部存储的路径

用进度条显示下载进度

  • 拿到下载文件总长度时,设置进度条的最大值

    1. //设置进度条的最大值
    2. pb.setMax(length);
  • 进度条需要显示三条线程的整体下载进度,所以三条线程每下载一次,就要把新下载的长度加入进度条

    • 定义一个int全局变量,记录三条线程的总下载长度

      1. int progress;
    • 刷新进度条

      1. while((len = is.read(b)) != -1){
      2. raf.write(b, 0, len);
      3. //把当前线程本次下载的长度加到进度条里
      4. progress += len;
      5. pb.setProgress(progress);
  • 每次断点下载时,从新的开始位置开始下载,进度条也要从新的位置开始显示,在读取缓存文件获取新的下载开始位置时,也要处理进度条进度

    1. FileInputStream fis = new FileInputStream(file);
    2. BufferedReader br = new BufferedReader(new InputStreamReader(fis));
    3. String text = br.readLine();
    4. int newStartIndex = Integer.parseInt(text);
    5. //新开始位置减去原本的开始位置,得到已经下载的数据长度
    6. int alreadyDownload = newStartIndex - startIndex;
    7. //把已经下载的长度设置入进度条
    8. progress += alreadyDownload;

添加文本框显示百分比进度

  1. tv.setText(progress * 100 / pb.getMax() + "%");

HttpUtils的使用

HttpUtils本身就支持多线程断点续传,使用起来非常的方便

  • 创建HttpUtils对象

    1. HttpUtils http = new HttpUtils();
  • 下载文件

    1. http.download(url, //下载请求的网址
    2. target, //下载的数据保存路径和文件名
    3. true, //是否开启断点续传
    4. true, //如果服务器响应头中包含了文件名,那么下载完毕后自动重命名
    5. new RequestCallBack<File>() {//侦听下载状态
    6. //下载成功此方法调用
    7. @Override
    8. public void onSuccess(ResponseInfo<File> arg0) {
    9. tv.setText("下载成功" + arg0.result.getPath());
    10. }
    11. //下载失败此方法调用,比如文件已经下载、没有网络权限、文件访问不到,方法传入一个字符串参数告知失败原因
    12. @Override
    13. public void onFailure(HttpException arg0, String arg1) {
    14. tv.setText("下载失败" + arg1);
    15. }
    16. //在下载过程中不断的调用,用于刷新进度条
    17. @Override
    18. public void onLoading(long total, long current, boolean isUploading) {
    19. super.onLoading(total, current, isUploading);
    20. //设置进度条总长度
    21. pb.setMax((int) total);
    22. //设置进度条当前进度
    23. pb.setProgress((int) current);
    24. tv_progress.setText(current * 100 / total + "%");
    25. }
    26. });

Android基础总结(五)的更多相关文章

  1. android基础(五)网络数据解析方法

    在网络上传输数据时最常用的方法有两种:XML和JSON,下面就对这两种类型的数据解析进行讲解. 一.XML数据解析 在Android中,常见的XML解析器分别为SAX解析器.DOM解析器和PULL解析 ...

  2. android基础(五)网络编程

    android 的网络编程一般可以分为两种:基于Socket的,基于Http的. 一.socket与Http socket封装了TCP/IP协议,TPC/IP协议是传输层协议,主要解决数据如何在网络中 ...

  3. <Android 基础(五)> MVVM

    介绍 MVVM,Model-View-ViewModel,与上次讲的MVP模式比较的类似,MVP中需要大量的接口文件,而MVVM模式下,View和ViewModel直接关联,使用上比较方便,简化了代码 ...

  4. 安卓Android基础第五天

    使用HttpUrlConnection方式提交到服务器2 Get方式:组拼url地址把数据组拼到url上,有大小限制1kb(浏览器)或4kb(http协议) Post方式:post方式提交安全,没有大 ...

  5. Android基础夯实--重温动画(五)之属性动画 ObjectAnimator详解

    只有一种真正的英雄主义 一.摘要 ObjectAnimator是ValueAnimator的子类,它和ValueAnimator一样,同样具有计算属性值的功能,但对比ValueAnimator,它会更 ...

  6. android基础---->JSON数据的解析

    上篇博客,我们谈到了XML两种常用的解析技术,详细可以参见我的博客(android基础---->XMl数据的解析).网络传输另外一种数据格式JSON就是我们今天要讲的,它是比XML体积更小的数据 ...

  7. 基础4 Android基础

    基础4 Android基础 1. Activity与Fragment的生命周期. Activity生命周期 打开应用 onCreate()->onStart()->onResume 按BA ...

  8. Android开发面试经——2.常见Android基础笔试题

     标签: androidAndroid基础Android面试题Android笔试题 2015-03-12 15:04 3361人阅读 评论(3) 收藏 举报  分类: Android开发(29)  版 ...

  9. Android采访开发——2.通用Android基础笔试题

    注意finddreams博客: http://blog.csdn.net/finddreams/article/details/44219231 正值跳槽的热季.整理一下Android面试中最常考的笔 ...

  10. Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型

    Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...

随机推荐

  1. sessionStorage 和 localStorage 、cookie

    sessionStorage 和 localStorage html5中web storage包括两种储存方式:sessionStorage 和 localStorage sessionStorage ...

  2. asp.net获取数据库的连接字符串

    1.添加引用 using System.Configuration; 2.代码 string strConnectionString=ConfigurationManager.AppSettings[ ...

  3. 深入理解SQL注入绕过WAF和过滤机制

    知己知彼,百战不殆 --孙子兵法 [目录] 0x0 前言 0x1 WAF的常见特征 0x2 绕过WAF的方法 0x3 SQLi Filter的实现及Evasion 0x4 延伸及测试向量示例 0x5 ...

  4. 用Kotlin语言重新编写Plaid APP:经验教训(II)

    原文标题:Converting Plaid to Kotlin: Lessons learned (Part 2) 原文链接:http://antonioleiva.com/plaid-kotlin- ...

  5. ClassNotFoundException超限

    错误日志图 被这弱智的错误吭了半个小时,项目本来好好的,然后因为改版加了很多东西,所以就超限了,一开始总是报下面那图的错,搞的我总以为是retrofit的错,但是好好的框架而且没改过,怎么可能会出错呢 ...

  6. React Native 之 View使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  7. React Native学习笔记之2

    1:如何创建一个react native工程 首先进入到指定文件夹里面,然后在终端执行react-native init ReactNativeProject :其中ReactNativeProjec ...

  8. iOS类中的属性设置背景色(统一)

    unsigned int count; objc_property_t *properties = class_copyPropertyList([self class], &count); ...

  9. Genymotion报Unable to load virtualbox engine错误

  10. block为什么用copy以及如何解决循环引用

    在完成项目期间,不可避免的会使用到block,因为block有着比delegate和notification可读性更高,而且看起来代码也会很简洁.于是在目前的项目中大量的使用block. 之前给大家介 ...