网络编程

HTTP协议

我们做android开发的,做的就是程序方面的,用术语说就是应用层,给用户用的东西,那么应用层就需要受到http协议的控制,下面我们看看http协议的主要特点

  • 支持c/s模式
  • 简单快速:只需要传送请求方法和路径,请求方法常用的有:GET、HEAD、POST等
  • 灵活:允许传输任意类型的数据对象,用Content-Type进行标记
  • 无连接: 限制每次连接只处理一个请求
  • 无状态:对书屋处理没有记忆功能

HTTP的URL格式

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

常见的状态码的意思如下

200 OK:客户端请求成功
403 Forbidden:服务器收到请求,但是拒绝提供服务
404 Not Found:服务器无法根据客户端的请求找到资源
500 Internal Server Error:服务器发生不可预期的错误

http网络请求的问题(https是没有问题的)

  • 更改网络安全配置
    • 在res新增xml目录,创建
network_security_config.xml请求
<network-security-config>
    <base-config cleartextTrafficPermitted="true"/>
</network-security-config>
  • 在AndroidManifest.xml中的application标签增加一下属性
android:networkSecurityConfig="@xml/network_security_config">

Android常用的网络编程框架

  • OkHttp(已经代替了HttpURLConnection)
  • 配置
    • OkHttp支持Android2.3及其以上版本,java要求JDK1.7以上
    • 添加依赖:implementation 'com.squareup.okhttp3:okhttp:4.2.1'
    • 添加权限: <uses-permission android:name="android.permission.INTERNET" />

OkHttp开发基本思路

  • OkHttp的每次网络请求是一个Request,提供Request必要的参数url、header等,基于Request构造处一个call对象,再调用它的execute()方法,就能取得web Server回复的数据
  • 如果同步调用,需要在独立的线程中运行,使用异步调用,则采用回调的方式执行,在内部封装了一个请求队列
  • 基本步骤
    • 新建一个OkHttpClient对象
    • 通过Request.Builder对象新建一个Request对象
    • 通过Request对象构造Call对象,调用enqueue()以异步的方式将call加入调度堆列,等待request执行完成
    • 通过Call对象的Callback对象返回执行结果

GET请求

 private void get(String url){
        Request request=new Request.Builder().url(url)
               //设置和添加Header
                .header("user-agent",
                        "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36" +
                                "(KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36")
                .addHeader("Accept","application/json")
                .get()
                .method("GET",null)
                .build();

        //发送请求,并处理回调
        OkHttpClient client=HttpsUtil.handleSSLHandshakeByOkHttp();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {

            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                if(response.isSuccessful()){
                    //获得响应主体的json字符串
                    String json=response.body().string();
                    //使用FastJson库解析json字符串
                    final Ip ip= JSON.parseObject(json,Ip.class);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            //根据返回的code判断过去是否成功
                            if(ip.getCode()!=0){
                                tvResult.setText("未获得数据");

                            }
                            else {
                                //解析数据
                                IpData data=ip.getData();
                                //显示出来的只是放进去的值,别的那么多数据,显示不出来
                                tvResult.setText(data.getIp()+","+data.getArea());
                            }
                        }
                    });
                }
            }
        });
    }

Http Header的读写

  • 当写到请求头的时候,使用header(name,value)可以设置唯一的name、value.如果已经优质,旧的将被移除,然后添加新的
  • 使用addHeader(name、value)可以添加多值(添加,不移除已有的)

post异步请求

  • 通过RequestBody构建请求数据
        FormBody.Builder builder=new FormBody.Builder();
        for (String key:params.keySet()){
        //构建要post到Server的数据
            builder.add(key,params.get(key));
        }
        return builder.build();
    }

post异步请求JSON数据

 public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown;charset=utf-8");
 private void post(String url,Map<String,String> params){
        RequestBody body=setRequestBody(params);
        Request request=new Request.Builder().url(url).post(body)

post方式提交Multipart文件

 public static MediaType MEDIA_TYPE_PNG=MediaType.parse("img/png");
    private void uploadImage(String url,String fileName){
        //1.创建请求主体RequestBody
        RequestBody fileBody=RequestBody.create(new File(fileName),MEDIA_TYPE_PNG);
        RequestBody body=new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("title","头像")
                .addFormDataPart("file",fileName,fileBody)
                .build();
        //2.创建请求
        Request request=new Request.Builder()
                .url(url)
                .post(body)
                .build();

Post异步下载文件

 @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                if(response.isSuccessful()){
                    //1.获取下载文件的后缀名
                    String ext=url.substring(url.lastIndexOf(".")+1);
                    //2.根据当前时间创建文件名,避免重名冲突
                    final String fileName=System.currentTimeMillis()+"."+ext;
                    //3.获得响应字体的字节流
                    InputStream is=response.body().byteStream();
                    //4.将文件写入path目录
                    writeFile(is,path,fileName);
                    //5.在界面上给出提示信息
                    tvResult.post(new Runnable() {
                        @Override
                        public void run() {
                            tvResult.setText(fileName+"下载成功,存放在"+path);
                        }
                    });
                }

图片加载框架Glide

  • 添加依赖:
   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'
  • 添加网络权限
    <uses-permission android:name="android.permission.INTERNET" />
  • 使用
    Glide.with(this).load("http://goo.gl/gegYUd"),into (imgeView);

Glide 加载https图片

 public static OkHttpClient handleSSLHandshakeByOkHttp() {
        X509TrustManager trustManager = (X509TrustManager) getTrustManager()[0];

        return new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                //支持HTTPS请求,跳过证书验证
                .sslSocketFactory(getSSLSocketFactory(), trustManager)
                .hostnameVerifier(new TrustAllHostnameVerifier())
                .build();
    }
  • 创建继承AppGlideModule类的自定义类,重写registerComponents()方法


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 在Android开发中,网络请求是非常常用的,因此我们需要对Android开发的网络请求有大致的了解;包括应...
    weiinter105阅读 5,979评论 0 0
  • iOS网络编程读书笔记 Facade Tester客户端门面模式的实例(被动版本化) 被动版本化,所以硬编码URL...
    melouverrr阅读 5,531评论 3 7
  • OSI七层模型 OSI七层协议模型主要是: 应用层(Application) 表示层(Presentation) ...
    门心叼龙阅读 2,372评论 0 0
  • 我曾有一只闺蜜,暂且唤她米米吧。 【一】 我跟她大一相识,那时我俩同在一个社团,社团每个星期开次例会,我们都是那种...
    皎夜阅读 3,593评论 0 4
  • 结束了十几天的假期,返回上海上班。经历了大半天的折腾,到达上海是晚上十一点,下了车,拖着行李箱上了开往住处的地铁。...
    li李琳阅读 1,573评论 2 1