zoukankan      html  css  js  c++  java
  • 关于 Android 网络连接的使用

        到目前从事安卓应用开发的经历中,有使用到和网络连接相关的时候有三处:

    一是电话本客服号码内置时,客服号码信息需要支持在线更新功能,当时有做应用与服务器连接取数据,然后判断是否要更新;

    二是维护下载管理模块的时候,有分析过无法下载的问题时有了解过;

    三是自己开发了一个自动下载谷歌play排名前1000应用的工具时,设计到下载功能;

    想来这三处应该用到的都是Android里面自带的HttpUrlConnection工具类提供的功能,刚刚查了一下,这个还是java自带的。

    https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html

    从网上资料得知,在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。这个是由于各个不同时期两者存在的bug和受重视程度不同有关,历史的车轮滚滚向前,版本迭代更新,目前肯定就是都乐于使用HttpUrlConnection 了。

    HttpURLconnection是基于http协议的,支持get,post,put,delete等各种请求方式,最常用的就是get和post。但是我的代码中没有对此进行声明处理,例如电话本中下载客服号码信息文件的代码如下:

    /**
    * http connection
    *
    * return value: if failed :null
    * succeed : inputstream
    */
    public InputStream getInputStream(String urlStr) throws IOException {
    InputStream is = null;
    URL mUrl = null;
    int mContentLength = 0;
    try {
    mUrl = new URL(urlStr);

    Log.d(TAG,"[getInputStream]urlStr= "+urlStr+" ,url= "+mUrl.toString());

    HttpURLConnection urlConn = (HttpURLConnection) mUrl.openConnection(); // 通过URL获取连接对象,此后没有设置请求方式是否为get还是post,默认就是get
    Log.d(TAG,"[getInputStream] urlConn="+urlConn);
    //set timeout time
    urlConn.setConnectTimeout(10000); //设置连接超时时间
    urlConn.setReadTimeout(10000);//设置读取超时时间
    urlConn.setDoInput(true);// 允许写入,因为我这边是要从服务端获取,所以要输入,这个默认也是true.  而setDoOutput,设置是否要输出,默认false


    is = urlConn.getInputStream(); //没有使用connect连接方法,直接获取数据流了,也没有出现问题,但是注意使用connect之后,就不要再设置参数了
    Log.d(TAG,"[getInputStream] is="+is);
    mContentLength = urlConn.getContentLength();  //如果使用了压缩Accept-Encoding: gzip需要注意这个长度是压缩长度。
    Log.d(TAG,"mContentLength="+mContentLength);

    if(mContentLength <= 0){
    Log.w(TAG,"can not get file size");
    return null;
    }

    } catch (MalformedURLException e) {
    Log.e(TAG,"MalformedURLException");
    e.printStackTrace();
    }
    catch(NetworkOnMainThreadException e){
    Log.d(TAG,"NetworkOnMainThreadException ");
    e.printStackTrace();
    }
    catch(UnknownHostException e){
    Log.d(TAG,"UnknownHostException ");
    e.printStackTrace();
    }
    catch(Exception e){
    Log.d(TAG,"Exception ");
    e.printStackTrace();
    }
    finally{
    Log.d(TAG,"getInputStream over");
    }

    return is;
    }

    ---------------在自动下载谷歌play应用的工具代码中,关于网络连接部分代码如下-----------------

    /*
    * url: download link
    * name: the download apk name in the PC
    * oldName: apk package name
    */
    public static String download(String id ,String url, String name,String oldName){
    URL e = null;
    File file;
    URLConnection uc;
    int mFileSize = -1;
    System.out.println("-----download id="+id+" url="+url+" name="+name+" oldName="+oldName);
    try {
    e = new URL(url);
    uc = e.openConnection();
    uc.addRequestProperty("User-Agent",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");  // 这里主要是设置UA信息,不然有可能是下载不了
    uc.connect();

    file = new File(downpath + name);

    //avoid download the same file again
    if(file.exists()){
    return STATUS_SUCCEED;
    }

    //get the download file size by 'content-length' field
    mFileSize = uc.getContentLength();

    InputStream is = uc.getInputStream();

    System.out.println("download begin to copy stream....");
    long start = System.currentTimeMillis();
    //copy the stream to local storage
    FileUtils.copyInputStreamToFile(is,file);
    long end = System.currentTimeMillis();

    System.out.println("download copy stream over!! spent time: "+(end-start)/1000+" s");
    //record the result
    if(mFileSize != -1){
    //succeed , do nothing
    }else{
    //delete it if failed
    if(file.isFile() && file.exists()) {
    file.delete();
    }

    return STATUS_FAIL;
    }
    System.out.println(name+" "+mFileSize);
    } catch (Exception var) {

    System.out.println(" download Exception");
    var.printStackTrace();

    file = new File(downpath +name);
    if(file.isFile() && file.exists()) {
    file.delete();
    }

    return STATUS_EXCEPTION;
    }

    return STATUS_SUCCEED;
    }

    ----------------关于在维护下载管理模块是对于http网路连接的一点认识-----------------

    Gamil 和 雅虎邮箱在数据流量的情况下不能下载附件问题,当时分析到的是雅虎服务器没有给出Content-length 域的值,导致代码无法判断文件大小而做的一个

    禁止下载的处理;另外在android原生代码里面4.4的逻辑是通过判断Content-length 还有 编码类型来看是否继续下载,5.1版本之后又增加了判断是否为持久连接的逻辑,所以从这一系列问题中可以看出,网络连接里面有很多细节事项参数需要注意:

    1、文件大小 content-length

    2、编码类型 encodetype,分块传输编码(Chunked transfer encoding)可以用来传输大文件,不会告诉content-length大小

    3、连接类型: 持久连接 和 非持久连接 ,HTTP/1.0使用非持久连接,HTTP/1.1默认使用持久连接,事物处理结束后,不关闭TCP连接。

    1)HTTP/1.0 + keep-alive 连接, 即默认为非持久,如果要需要发送请求时增加 Connection:Keep-Alive

    2) HTTP/1.1 + persistent 连接, 即默认为持久连接,如果需要关闭需要在最后一条请求中发送一个Connection:close请求首部

    以上只是我在实际工作中碰到的一些场景知识的总结,实际HTTPUrlConnection的使用场景更多,除了我这边用到的下载文件,还有上传参数,上传文件等,具体可以参考: https://blog.csdn.net/fightingXia/article/details/71775516

    -----------------关于socket  tcp/ip  http 的一点了解--------------------

    socket套接字包含了五个信息:使用协议类型,源地址IP , 源端口, 目标地址IP, 目标地址端口, 是实现TCP/IP协议栈的一种工具,提供接口,方便调用;

    TCP/IP 是传输层的协议,基于网络层IP协议,定义了数据如何传输,里面有三次握手规则来确保TCP连接的建立:

    1、客户端发送SYNC同步状态给服务端, 进入同步发送状态;

    2、服务端收到SYNC同步信号,进行ACK确认+1处理,然后发送SYNC+ACK给客户端,进入同步接受状态;

    3、客服端接受到SYNC+ACK之后,进行确认ACK+1,发送给服务端;

    然后连着进入连接建立状态, 之所以是三次握手是从稳定性和效率两方面来考虑的。

    HTTP协议是应用层协议,即数据如何包装解析呈现给应用,每次请求都需要服务器响应,是一种短连接。

  • 相关阅读:
    让WPF的Popup不总置顶的解决方案
    virtio 驱动的数据结构理解
    关于Linux下面msyql安装后并未设置初始密码,但是登录报错“Access denied for user 'root'@'localhost' (using password: NO)”的解决方案
    gulp初涉
    前后端分离--构建前端Mock Server--windows部署rap
    一些css小用法总结(持续更新~)
    js原生封装自定义滚动条
    ie下面兼容性问题的一些总结
    关于html水平垂直居中的一些总结吧
    C# 正则表达式匹配string字符串中的时间串(yyyyMMdd)
  • 原文地址:https://www.cnblogs.com/yangwubo/p/8857535.html
Copyright © 2011-2022 走看看