zoukankan      html  css  js  c++  java
  • 安卓网络编程学习(1)——java原生网络编程(1)

    写在前面

    马上要进行第二轮冲刺,考虑到自己的APP在第一轮冲刺的效果不尽人意,有很多网络方面的小BUG,这里就系统学习一下网络编程,了解来龙去脉,以便更好的对项目进行优化处理。

    http协议

    http协议的定义和工作流程

    要进行http请求,首先要知道什么是http协议。http是什么意思?HyperText Transfer Protocol 翻译过来就是超文本传输协议。协议就是约定的意思,内容是Http相关的格式,http协议是基于TCP/IP协议之上的应用层协议。这就涉及到计算机网络的知识了,但奈何我的计算机网络不是很好,就不班门弄斧了。那么http协议是如何工作的呢?如下图:

    客户端发起请求(request)到服务器,服务器响应请求(response)到客户端。我们一直在做的APP其实就是客户端,负责发起请求然后接受内容。类似的,我们的网页也是一个客户端,发起请求然后接收内容。可能这也是为什么现在能够做到写一个web前端就能同时部署到手机端和桌面端的原因吧。

    http协议的常用请求方式

    在之前学习java web的过程中,了解到了get和post这两种最常用的,其实还有put delete head trace options connect,但对于我们做客户端开发,只要了解前面的四种即可了。一般来说,get用于请求数据,post用于提交数据,put用于更新数据,delete用于删除数据。
    关于http其他的知识,之前学习java web时已经基本了解过了,这里就不再过多阐述了。

    使用java的api发起网络请求

    这里我们使用阳光沙滩网站提供的API,可以让你在本地架设一个服务器,类似tomcat.具体的原理我也不大懂.
    clone完之后我们用java -jar启动该jar包即可。


    出现你放API的地址即说明部署成功了。

    事不宜迟,先贴代码:

    new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        URL url = new URL("http://10.0.2.2:9102/get/text");
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.setRequestMethod("GET");
                        connection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
                        connection.setRequestProperty("Accept","*/*");
                        connection.connect();
                        //结果码
                        int responseCode = connection.getResponseCode();
                        if(responseCode==200){
                            Map<String, List<String>> headerFields = connection.getHeaderFields();
                            Set<Map.Entry<String, List<String>>> entries = headerFields.entrySet();
                            for(Map.Entry<String,List<String>> entry:entries){
                                Log.d(TAG,entry.getKey()+"=="+entry.getValue());
                            }
                            InputStream inputStream = connection.getInputStream();
                            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                            String json = bufferedReader.readLine();
                            //Log.d(TAG,"json -->"+json);
                            Gson gson = new Gson();
                            GetTextItem getTextItem = gson.fromJson(json, GetTextItem.class);
                            updateUI(getTextItem);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    

    代码解析

    我们请求数据不能在主线程进行,需要新建一个子线程,但实际开发中不建议如此使用,这里主要为了学习java API
    可以看到,我们首先定义了一个URL,然后把请求地址放进去,新建一个连接并返回成HttpURLConnection类型,通过这个对象来设置请求参数,并用connect()方法来发出请求。
    而后通过返回响应码来确定是否请求成功,若成功则提取数据并用GSON转成相应的json数据,输出。

    注意事项

    要发起网络请求,首先需要在manifest中设置网络权限:

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

    但这样还不够,由于我们的安卓在某个版本后不再支持访问http类型的地址了,想要访问需要进行配置,可以这样设置:

        <application
            android:usesCleartextTraffic="true"
    

    但这样配置过于简略,我们可以设置xml配置文件来进行详细的配置,如:

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
            <base-config cleartextTrafficPermitted="true"/>
    </network-security-config>
    

    然后在manifest中使用:

    android:networkSecurityConfig="@xml/network_security_config"
    

    也要放到application标签中。
    Tips1:如果发现配置好了还是无法使用,请把APP卸载再安装,有奇效哦!
    Tips2:这里使用了Gsonformat来生成bean类,这是一个输入json就可以自动生成bean类的插件,建议百度下载。

    使用java原生API请求图片

    在上面的操作里,我们使用了glide工具包来帮我们处理图片的载入,那我们如何使用java API来实现呢?接下来我们来简单的处理一下:

       new Thread(new Runnable() {
                @Override
                public void run() {
                  try {
                       URL url = new URL("https://cdn.sunofbeaches.com/images/ad/shop-ad.png");
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                       connection.setRequestMethod("GET");
                       connection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9");
                        connection.setRequestProperty("Accept","*/*");
                      connection.connect();
                       int responseCode = connection.getResponseCode();
                      if(responseCode==HttpURLConnection.HTTP_OK){
                           InputStream inputStream = connection.getInputStream();
                          //转成BitMap
                       final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                            //更新UI,要在主线程
                         runOnUiThread(new Runnable() {
                             @Override
                               public void run() {
                                 ImageView imageView = findViewById(R.id.result_image);
                                 imageView.setImageBitmap(bitmap);
                              }
                           });
                      }
                   } catch (Exception e) {
                        e.printStackTrace();
                  }
                    runOnUiThread(new Runnable() {
                       @Override
                       public void run() {                  
     }
                  });
               }
            }).start();
    

    获取到内容后,转成bitmap然后设置到Image即可。但这样的用法并不值得被提倡,因为如果我们的图片过大,甚至会导致我们的APP崩掉,我们要对其进行一定的压缩,压缩到适合我们APP使用的大小。
    下面是一段常见的算法:

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            //拿到图片的大小
            BitmapFactory.decodeResource(getResources(), R.mipmap.test_pic,options);
            ImageView imageView = findViewById(R.id.result_image);
             int outHeight = options.outHeight;
            int outWidth = options.outWidth;
            Log.d(TAG,"outHeight ==>"+outHeight);
            Log.d(TAG,"outWidth ==>"+outWidth);
            //拿控件的尺寸
            int measuredHeight = imageView.getMeasuredHeight();
            int measuredWidth = imageView.getMeasuredWidth();
            //
            Log.d(TAG,"measuredHeight ==>"+measuredHeight);
            Log.d(TAG,"measuredWidth ==>"+measuredWidth);
            options.inSampleSize  =  1;
            //图片的宽度/控件的宽度
            // 图片的高度/控件的高度
            //取两者之间的小值
            if(outHeight > measuredHeight || outWidth > measuredWidth){
                int subHeight = outHeight/measuredHeight;
                int subWidth = outWidth/measuredWidth;
                options.inSampleSize = subHeight > subWidth ?subWidth:subHeight;
            }
            options.inJustDecodeBounds = false;
            Log.d(TAG,"inSampleSize ==>"+options.inSampleSize);
        //根据控件大小,动态地计算sample值
            final Bitmap bigImage = BitmapFactory.decodeResource(getResources(), R.mipmap.test_pic,options);
    
            imageView.setImageBitmap(bigImage);
    

    这里通过计算比例得到一个相对合适的比例值,然后再将这个bitmap设置给image控件。这就是安卓大图片的处理方式了。
    实际开发中,我们都会用开源框架来解决,比如glide,XUtils等等。框架能做的事要更多,但基本的还是离不开这些。

    总结

    主要是简单学习了一下如何使用java原声API来请求(get)数据。为了不让博客太长,把其余一些内容放置到下篇博客了。
    希望学习了之后能够更好的开发我们自己的APP。

  • 相关阅读:
    产品易用性
    优化Compress components with gzip 问题
    转:稳定性测试
    Xray CA证书
    转:获取WEB各阶段响应时间
    测试用例编写注意事项
    用dd把一个空硬盘写满
    转:linux终端命令使用cpu负载到100
    JMeter命令行执行+生成HTML报告
    防F12扒代码:按下F12关闭当前页面
  • 原文地址:https://www.cnblogs.com/wushenjiang/p/12937531.html
Copyright © 2011-2022 走看看