Android网络编程详解

1、网络的基本概念及Http协议

IP地址和端口号java

  • IP地址:网络中的媚态计算机都必须一个惟一的IP地址做为标识,用一组由“.”分隔的十进制数组成
  • 端口号:IP地址只能保证键数据送到指定的计算机,但没法知道交给该主机的哪一个网络程序,所以采用端口号标识计算机上正在运行的进程
  • 每一个被发送的网略数据包都包含端口号,用于将该数据帧交给具备相同端口号的应用程序处理

Java的网络编程由Java.net包中的类进行处理android

  • InetAddress类:描述IP地址

HTTP协议

  • 属于应用层的面向对象的协议,适用于分布式超媒体信息系统git

  • 主要特色github

    一、支持C/S模式编程

    二、简单快速:只需传送请求方法和路径,请求方法经常使用的有:GET、HEAD、POST等数组

    三、灵活:容许传输任意类型的数据对象,用Content-Type进行标记缓存

    四、无链接:限制每次链接只处理一个请求安全

    五、无状态:对事务处理没有记忆功能服务器

  • HTTP的URL的格式:网络

    一、http://host[:port][/path]

    二、http表示要经过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址;port指定一个端口号,为空则使用默认端口80;path指定请求资源的URI

HTTP请求报文

  • 由请求行、请求报头、空行和请求数据4个部分组成

HTTP相应报文

  • 由状态行、消息报头、空行、相应正文组成

常见的状态码

  • 200 OK:客户端请求成功
  • 400 Bad Request:客户端请求有语法错误,不能被服务器所理解
  • 400 Unauthorized:请求未经受权,这个状态码必须和WWW-Authenticate报头域一块儿使用
  • 403 Forbidden:服务器收到请求,可是拒绝提供服务
  • 404 Not Found:服务器没法根据客户端的请求找到资源
  • 500 Internal Server Error:服务器发生不可预期的错误
  • 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常

https请求

  • HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,也就是HTTP的安全版
  • HTTPS=HTTP+SSL/TLS
  • HTTPS的安全基础是SSL

2、Android的网络编程

Android的网络编程

一、HTTP通讯方式

HttpURLConnection

  • Android 2.3以后,HttpURLConnection是Android网络编程的最佳选择,它的API简单,体积较小,压缩和缓存机制有效较少网络访问的流量

HttpClient

  • 开发团队向开发者建议:在Android 2.2版本及如下可使用HttpClient,在2.3以上版本则应该使用HttpURLConnection
  • Android 6.0直接删除了HttpClient类库

二、Socket通讯方式

Android P的http网络请求的问题

Android p要求默认使用加密链接,禁止APP使用任何未加密的链接,所以须要使用TLS传输层安全协议,也就是Https

Android P使用HttpUrlConnection进行http的get请求会出现如下异常

  • W/System.err:java.io.IOException:Cleartext HTTP traffic to **** not permitted

解决方案

  • 推荐:使用Https链接
  • targetSdkVersion降到27级如下版本
  • 更改网络安全配置,此更改与网站有关,有时不能获得相应

更改网络安全配置

在res新增xml目录,建立network_security_config.xml,开启http请求

<network-security-config>
 <base-config cleartextTrafficPermitted="true"/>
 </network-security-config>

在AndroidMainfest.xml中的application标签增长如下属性

  • android:networkSecurityConfig="@xml/network"

Android的Https

自定义X509TrustManager

  • 在使用HttpsURLConnection发起HTTPS请求的时候,提供了一个自定义的X509TrustManager,未实现安全校验逻辑
  • 若是不提供自定义X509TrustManager,代码运行起来可能会报异常

自定义HostnameVerifier

  • 在握手期间,若是URL的主机名和服务器的标识主机名不匹配,则验证机制能够回调此接口的实现程序来肯定是否应该容许此连接

URL类

一、统一资源定位符(URL)是对能够从互联网上获得的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址

二、互联网上的每一个文件都有一个惟一的URL

三、URL类提供了多个构造器用于建立URL对象

四、URL类提供多个方法访问URL对应的资源:

  • URLConnection openConnection():返回一个URLConnection对象,它表示到URL所引用的远程对象的链接
  • InputStream openStream():打开此URL的链接,并返回一个用于读取该URL资源的InputStream

Android URL通讯

一、Android HTTP URL接口的基本操做包括:

  • 建立URL以及HttpURLConnection对象
  • 链接参数设置
  • 链接到服务器
  • 向服务器写数据
  • 从服务器读取数据

二、HttpURLConnection的属性设置

connection.setConnectTimeout(15000);
        connection.setReadTimeout(15000);
        connection.setRequestMethod(method);
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) " +
                "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36");
        connection.setDoInput(true);
        if("POST".equals(method)){
            connection.setDoOutput(true);
        }

三、HttpURLConnection访问HTTP资源的步骤:

(1)根据URL地址建立URL对象

(2)使用URL对象的openConnection()方法获取HttpURLConnection对象

(3)设置链接的属性,包括GET/POST请求方式

(4)输入、输出数据

(5)关闭输入、输出流

(6)在AndroidManifest配置文件中设置访问INTERNET的权限

四、GET方式

// 一、将url字符串转为URL对象
        URL url = new URL(urlPath);
 //            二、得到HttpURLConnection对象
        connection = (HttpURLConnection) url.openConnection();
//            三、设置链接的相关参数
        connection.setRequestMethod("GET");
        connection.setUseCaches(false);
        connection.setConnectTimeout(15000);
        connection.setReadTimeout(15000);
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) " +
                "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36");
        connection.setDoInput(true);

  //            四、配置https的证书
        if ("https".equalsIgnoreCase(url.getProtocol())) {
            ((HttpsURLConnection) connection).setSSLSocketFactory(
                    HttpsUtil.getSSLSocketFactory());
        }
   //            五、进行数据的读取,首先判断响应码是否为200
        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
    //                得到输入流
            is = connection.getInputStream();
    //                包装字节流为字符流
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
   //                读取数据
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
   //                六、关闭资源
            is.close();
            connection.disconnect();
  //                七、返回结果
            return response.toString();

五、POST方式

String body=getParamString(params);
        byte[] data=body.getBytes();

        URL url=new URL(urlPath);

        connection= (HttpsURLConnection) url.openConnection();
        //            三、设置链接的相关参数
        connection.setRequestMethod("POST");
        connection.setUseCaches(false);
        connection.setConnectTimeout(15000);
        connection.setReadTimeout(15000);
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) " +
                "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36");
        connection.setDoInput(true);
        connection.setDoOutput(true);

  //            四、配置https的证书
        if ("https".equalsIgnoreCase(url.getProtocol())) {
            ((HttpsURLConnection) connection).setSSLSocketFactory(
                    HttpsUtil.getSSLSocketFactory());
        }
        connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
        connection.setRequestProperty("Content-Length",String.valueOf(data.length));
        OutputStream os=connection.getOutputStream();
        os.write(data);
        os.flush();

        if(connection.getResponseCode()==HttpURLConnection.HTTP_OK){

           is=connection.getInputStream();
           BufferedReader reader=new BufferedReader(new InputStreamReader(is));
            //                读取数据
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
 //                六、关闭资源
            is.close();
            connection.disconnect();
 //                七、返回结果
            return response.toString();
        }

六、HttpURLConnection使用的注意事项

  • 使用setConnectTimeout()方法设置链接超时,当网络很差使,Android系统会在超时设置时间后收回资源,中断操做
  • 经过getResponseCode()对响应码进行判断,若是返回的相应码为200,则表示链接成功
  • 在对大文件操做时,要将文件写道SDCard上,不要直接写到手机内存上
  • 操做大文件时,要一边从网络上读取,一边往SDCard上写入,减小手机内存的使用
  • 对文件流操做完毕后要及时关闭
  • Android4.0后全部网络通讯的操做都不能在主线程进行,须要使用独立的线程完成

OKHttp

  • 官网:square.github.io/okhttp/

  • 源码:github.com/square/okht…

  • 配置:

    1. OKHttp是Android 2.3及其以上版本,Java要求JDK1.7以上

    2. 添加依赖:

      implementation 'com.squareup.okhttp3:okhttp:4.2.1'
    3. 添加权限:

      <uses-permission android:name="android.permission.INTERNET"/>
  • 特色:

    1. 0KHttp是Android版Http喀户端,很是高效,支持SPDY、链接池、GZIP和HTTP缓存。
    2. 默认状况下,0KHttp会自动处理常见的网络问题,像二次链接、SSL的握手问题。
    3. 若是应用程序集成了0KHttp,Retrofit默认会使用0KHttp处理其余网络层请求。
    4. 从Android4.4开始,HttpURLConnection的底层实现采用了okHttp。
  • OkHttp开发基本思路

    1. 0kHttp的每次网络请求是一个Request,提供Request必要的参数url、header等,基于Request构造出一个Call对象,再调用它的execute( )方法,就能取得WebServer回复的数据。
    2. 若是同步调用,须要在独立的线程中执行,使佣异步调用,则采用回调的方式执行,在内部封装了一个请求队列。
    3. OkHttp依赖另外一个组件okiO完成高性能的I/O操做
    4. 基本用法:新建一个OkHttpClient对象;经过Request.Builder对象新建一个Request对象;经过Request对象构造Call对象,调用enqueue()以异步的方式将call加入调度队列,等待request执行完成;经过Call对象的Callback对象返回执行结果。
    5. 一直等待http请求,直到返回响应,请求期间会阻塞进程,所以不能在Android的主线程执行,须要用Android的多线程方式进行处理,不然会报错。
  • Get同步请求

    1. 当HTTP响应码位于200到300之间时,认为操做是成功的
    2. response.body()返回-个ResponseBody对象,封装了HTTP响应的主体数据,它的string()方法将这些数据转换为字符串,另外一个byteStream()方法则返回一个InputStream流
    3. 注意事项:要独立的线程中执行网络操做;对于超过1MB的响应body,应使用流的方式来处理body。
    4. 通常不适用
  • Get异步请求

    1. 在另外的工做线程中执行http请求,请求时不会阻塞当前的线程,因此能够在Android主线程中使用。
    2. 异步请求须要加入到一个请求队列中,而且要指定回调方法。
  • post异步请求

    1.经过RequestBody构建请求数据

    private void postForm(String url){
    RequestBody formBody = new FormBody.Builder().add("city","南京").build();
     Request request = new Request. Builder().url(url).post(formBody).build();
    mClient.newCall(request).enqueue(new Callback(){
    @Override
    public void onResponse(Call call, Response response) throws IOException {
    final String str = response .body().string();
    Log.d(TAG, str);
    runOnUiThread(new Runnable() {
      @Override
     public void run() {
     textView. setText(str);
    });
    }
    @Override
    public void onFailure(Call call,   IOException e) {
     });
    }
  • 图片加载框架Glide

    1. 添加依赖:

      implementation 'com.github.bumptech.glide:glide:4.10.0'
      annotationProcessor 'com. github.bumptech.glide:compiler:4.10.0'
       //https图片处理
      implementation "com.github.bumptech.glide:okhttp3-integration:4.10.0"
    2. 添加网络权限:

      <uses-permission android: name= "android. permi ssion . INTERNET" />
    3. 使用:

      Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
    4. 加载图片的通常方法:

      Glide.with(Context context).load(String url).into(ImageView imageView);
  • Glide加载https图片

    1. 建立支持https的OkHttpClient对象:

      public static 0kHttpClient handleSSLHandshakeBy0kHttp() {
      return new 0kHttpClient.Builder()
      .connectTimeout(10,TimeUnit. SECONDS)
      .writeTimeout(10,TimeUnit. SECONDS)
      .readTimeout(10,TimeUnit . SECONDS)
       //支持HTTPS请求,跳过证书验i证
      .sslSocketFactory(getSSLSocketFactory(),(X509TrustManager) getTrustManager()[0])
      .hostnameVerifier(new TrustAllHostnameVerifier())
      .build();
      }
    2. 建立继承AppGlidModule类的自定义类,重写registerComponents( )方法:

      @GlideModule
      public class OkHttpGlideModule extends AppGlideModule {
       @Override
       public void registerComponents( @NonNull Context context,
       @NonNull Glide glide,@NonNull Registry registry) {
      OkHttpClient client = HttpsUtil.handl esSLHandshakeByokHttp();
       registry.replace(GlideUrl.class,InputStream.class,
       new 0kHttpUrlLoader.Factory(client));
       }
      }

今年年初我花一个月的时间收录整理了一套知识体系,若是有想法深刻的系统化的去学习的,能够点击传送门,我会把我收录整理的资料都送给你们,帮助你们更快的进阶。

相关文章
相关标签/搜索