• 使用HTTP协议访问网络(Android)


      在做项目的过程中需要连接服务器访问数据,还没有接触过Android网络编程方面,参考了《Android第一行代码》,在做的过程中遇到了很多的问题,这里就此记录一下。

    先给出访问网络的代码

    首先:在AndroidManifest.xml文件中进行声明,添加如下代码:

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

    编写网络操作类:

    public class HttpUtil{
    
     public static String sendHttpRequest(String address){
    
      HttpURLConnection connection=null;
      try{
        URL url=new URL(address);
        connection=(HttpURLConnection)url.openConnection();
        MyLog.d(TAG,"point:2");
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(8000);
        connection.setReadTimeout(8000);
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.connect();
        MyLog.d(TAG,"point:3");
        InputStream in=connection.getInputStream();
        MyLog.d(TAG,"point:4");
        BufferedReader reader=new BufferedReader((new InputStreamReader(in)));
        StringBuilder response=new StringBuilder();
        String line;
    
        while((line=reader.readLine())!=null){
            response.append(line);
    
        }
        MyLog.d(TAG,"point:5");
        return response.toString();
    
    }catch(Exception e){
        e.printStackTrace();
        return e.getMessage();
    }finally{
        if(connection!=null){
            connection.disconnect();
        }
    }
    }

    发起HTTP请求:

            String address="http://www.baidu.com";

            String reponse=HttpUtil.sendHttpRequest(address);

    这段代码看似正确,运行的时候会出现错误:java.io.IOException,android.os.NetworkOnMainThreadException

    先来看第一个错误

       java.io.IOException: Cleartext HTTP traffic to www.baidu.com not permitted

        为保证用户数据和设备的安全,Google针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量,未来都不能明码传输,需要使用下一代(Transport Layer Security)传输层安全协议,而 Android Nougat 和 Oreo 则不受影响。
        因此在Android P 使用HttpUrlConnection进行http请求会出现以下异常。

        W/System.err: java.io.IOException: Cleartext HTTP traffic to www.baidu.com not permitted

        使用Okhttp请求则出现:

    java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security policy

     针对这个问题,参考网上的资料,主要有三种解决方法:

           (1)APP改用https请求

                这个比较简单,这里只需要做如下修改:

              

            String address="https://www.baidu.com";
    String response= HttpUtil.sendHttpRequest(address);

            (2)targetSdkVersion降到27以下

                      只需要在build.gradle/app里进行修改即可

            (3)更改网络安全配置

                  这里我就是用的第三种方法,下面来详细说一下步骤。

                 1、在res文件夹下创建一个xml文件夹,然后创建一个network_security_config.xml文件,文件中内容如下:

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


                 2、在AndroidManifest,xml文件下的application标签添加以下属性:

      <application

          ...

          android:networkSecurityConfig="@xml/network_security_config"

          ...

     />

          当然还有可以不是用引用的方法,会方便一点,直接在主配置文件中添加如下:

             

       android:usesCleartextTraffic="true"

          这两个都可以,这个时候App可以访问网络了。

    这里主要参考了博客:https://blog.csdn.net/gengkui9897/article/details/82863966

    解决第二个错误

    主要原因是网络连接不能放在主线程中,这是为了防止进行网络连接主线程被阻塞住。

    在Android4.0以后,会发现,只要是写在主线程(就是Activity)中的HTTP请求,运行时都会报错,这是因为Android在4.0以后为了防止应用的ANR(Aplication Not Response)异常,Android这个设计是为了防止网络请求时间过长而导致界面假死的情况发生。

    有两种解决方案:

    1.可以再Activity的onCreate()方法中加入这样一段代码,适用于网络请求数据量很小的话,如下

         if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);

         }

    2、启动子线程进行网络请求,更推荐使用这种

          new Thread(new Runnable(){

                @Override

                public void run(){

                       //进行网络访问操作

                }).start()

    这里主要参考了博客:https://blog.csdn.net/qq_29477223/article/details/81027716

    书中后面也给出了更简单的方法,使用OkHttp这里我简单放一下代码:

         1、在build.gradle/app中添加依赖

              implementation ("com.squareup.okhttp3:okhttp:3.14.2")

              注:这里OkHttp的版本会有更改,需要到OkHttp在github的官网进行查看,这里我附上网址自行查看:https://github.com/square/okhttp

        2、修改HttpUtil中代码

    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    
    public class HttpUtil {
    
        private static final String TAG = "HttpUtil";
    
        public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
    
            OkHttpClient client=new OkHttpClient();
    
            Request request=new Request.Builder()
                    .url(address)
                    .build();
            client.newCall(request).enqueue(callback);
    
        }
    }

            

        3、调用代码

    String address="http://www.baidu.com";
    HttpUtil.sendOkHttpRequest(address,new okhttp3.Callback(){
    
        @Override
        public void onFailure(Call call, IOException e) {
            //对异常情况进行处理
        }
    
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            //得到服务器返回的具体内容
            String responseData=response.body().string();
            Log.d(TAG,responseData);
        }
    });

    这里使用OkHttp节省了很多代码,并且OkHttp自带的回调接口也节省了我们不少事情。

    到这里App就可以正常进行网络访问并得到返回数据了

    刚开始学习Android的知识,如果上面有什么错误还请大佬们指出来。

    参考资料:

    《Android第一行代码》第二版,郭霖著

    https://blog.csdn.net/gengkui9897/article/details/82863966

    https://blog.csdn.net/qq_29477223/article/details/81027716

    
    
  • 相关阅读:
    Large-Margin Softmax Loss for Convolutional Neural Networks
    Selective Kernel Network
    A Discriminative Feature Learning Approach for Deep Face Recognition
    recurrent model for visual attention
    rethinking imageNet pre-training
    字符串格式化输出
    HeatMap
    Numpy 多维数组简介
    浅谈JVM(下)
    java线程池总结
  • 原文地址:https://www.cnblogs.com/hzauxx/p/10997464.html
Copyright © 2020-2023  润新知