Android网络编程(四) 之 HttpClient与HttpURLConnection

Android本身提供了Apache 的 HttpClient 和 Java 的HttpURLConnection来进行网络请求通信。它们都支持以流的方式进行网络通信,并且都支持https。

1 HttpClient

HttpClient的优势在于处理一些可能需要用户登录而且具有相应的权限才可访问该页面。例如需要涉及Session、Cookie的处理时,就要使用HttpClient。它的实现类有DefaultHttpClientAndroidHttpClient。它们都拥有非常多的API供开发者调用,但是,在Android 6.0 SDK版本已经将HttpClient类库移除了,如果想继续使用它,可以在相应的module下的build.gradle中加入:

android {
       useLibrary 'org.apache.http.legacy'
}

使用示例:

/**
     * HttpClient的Get请求
     * @param url 请求的URL
     * @return
     */
    public static String httpClientGet(String url) {
        InputStream inStream = null;
        HttpClient httpclient = null;
        try {
            httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(new HttpGet(url));
            inStream = response.getEntity().getContent();

            String result = inputStreamToString(inStream);
            return result;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inStream != null) {
                    inStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            httpclient.getConnectionManager().shutdown();
        }
        return null;
    }

    /**
     * HttpClient的Post请求
     * @param url 请求的URL
     * @param nameValuePairs 请求参数,值的添加如:nameValuePairs.add(new BasicNameValuePair("id", "12345"));
     * @return
     */
    public static String httpClientPost(String url, List<NameValuePair> nameValuePairs) {
        InputStream inStream = null;
        HttpClient httpclient = null;

        try {
            httpclient = new DefaultHttpClient();

            HttpPost httppost = new HttpPost(url);
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs ,"UTF-8"));
            HttpResponse response = httpclient.execute(httppost);
            inStream = response.getEntity().getContent();

            String result = inputStreamToString(inStream);
            return result;

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inStream != null) {
                    inStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            httpclient.getConnectionManager().shutdown();
        }
        return null;
    }

    /**
     * 将InputStream 格式转化为StringBuilder 格式
     * @param is
     * @return
     */
    private static String inputStreamToString(InputStream is) {
        String line = "";
        StringBuilder sb = new StringBuilder();
        try {
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            while ((line = rd.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
// 或
//        Scanner scanner = new Scanner(is).useDelimiter("\\A");
//        return scanner.hasNext() ? scanner.next() : "";
    }

2 HttpURLConnection

如果在一般的网络请求情况下,只是需要简单的网络请求或表单提交请求,HttpURLConnection则是最佳的选择。它的API简单,体积较小。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。

不过你应该也要知道的是在过去Android2.2版本及之前,HttpURLConnection一直存在一些令人太麻烦的bug,比如对一个可读的InputStream调用close()方法时,就有可能导致连接池失败,所以往往那时要都禁用连接池功能。不过,那也是过去的往事了。

在Android2.3版本中也使得该BUG修复。并加入了响应压缩,它会自动在每个发出的请求中加入Accept-Encoding: gzip报头,并处理相应的返回结果;增加了https方面的优化,使用了SNI(Server Name Indication)的方式进行连接,使得多个HTTPS主机可以共享同一个IP地址;增加了若连接失败,会自动去尝试重连机制;在Android 4.0版本中还加入了一些响应的缓存机制等。

正如在Android 6.0版本后官方将HttpClient移除也是建议我们在开中发使用HttpURLConnection,而且目前手机分布来看也不必再去对Android2.3之前的古董手机做适配了。

使用示例:

/**
     * HttpURLConnection的Get请求
     * @param urlStr
     * @return
     */
    public static String httpURLConnectionGet(String urlStr) {
        InputStream inStream = null;

        HttpURLConnection conn = null;
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection)url.openConnection();
//            conn.setConnectTimeout(timeOut);
//            conn.setReadTimeout(readTimeout);
            conn.setRequestMethod("GET");

            if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return null;
            }
            inStream = conn.getInputStream();

            String result = inputStreamToString(inStream);
            return result;

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inStream != null) {
                    inStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return null;
    }

    public static String HttpURLConnectionPost(String urlStr, String params) {
        HttpURLConnection conn = null;
        InputStream inStream = null;
        PrintWriter printWriter = null;
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.setDoOutput(true);                 // 是否输入参数
            //conn.setConnectTimeout(timeOut);      // 连接超时 单位毫秒
            //conn.setReadTimeout(readTimeout);     // 读取超时 单位毫秒
            conn.setUseCaches(false);               // Post 请求不能使用缓存

            // 第1种方式:使用直接输出流的方式(已知输出流的长度):
            // conn.setFixedLengthStreamingMode(输出流的固定长度);

            // 第2种方式:使用直接输出流的方式(未知输出流的长度):
            conn.setChunkedStreamingMode(5);        // 5 为块的大小

            // 第3种方式:本地缓存后一次性输出:
            // 两个函数都不指定

            conn.setRequestMethod("POST");

            // application/x-www-form-urlencoded是表单数据;application/x-javascript是json对象;application/x-javascript text/xml是xml数据
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); 
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Content-Length", String.valueOf(params.length()));

            //PrintWriter 是文本。也就是unicode编码格式的,当然也包括汉字。
            printWriter = new PrintWriter(conn.getOutputStream());
            printWriter.write(params);
            printWriter.flush();

            // OutputStream 接受的是bytes
            // byte[] data = params.getBytes("UTF-8");
            // OutputStream outputStream = conn.getOutputStream();
            // outputStream.write(data);
            // outputStream.flush();

            //DataOutputStream 是OutputStream的一个实用类,写byte,写String都可以
            // DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream());
            // dataOutputStream.writeBytes(params);
            // dataOutputStream.flush();

            if(conn.getResponseCode() == HttpURLConnection.HTTP_OK){
                inStream = new BufferedInputStream(conn.getInputStream());
            } else {
                inStream = new BufferedInputStream(conn.getErrorStream());
            }

            String result = inputStreamToString(inStream);
            return result;

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
            if (printWriter != null) {
                printWriter.close();
            }
            try {
                if (inStream != null) {
                    inStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

 

下载文件示例:

public static boolean downloadZip(Context ctx, String urlStr) {
    InputStream is = null;
    FileOutputStream fos = null;
    boolean bRet = false;
    HttpURLConnection conn = null;
    try {
        File zipFile = getDownloadFile(ctx);  // 例如:/data/data/com.zyx.demo/mydownload/xx.zip
        URL url = new URL(urlStr);
        conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setReadTimeout(5000);
        conn.setConnectTimeout(5000);

        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            return false;
        }

        is = conn.getInputStream();
        fos = new FileOutputStream(zipFile);

        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1) {
            fos.write(buffer, 0, len);
        }
        bRet = true;
    } catch (Exception e) {
    } finally {
        try {
            if (is != null) {
                is.close();
            }
            if (fos != null) {
                fos.close();
            }
            if (conn != null) {
                conn.disconnect();
            }
        } catch (Exception e) {
        }
    }
    return bRet;
}

public static File getDownloadFile(Context ctx) {
    try {
        String dexDir = ctx.getDir("mydownload", Context.MODE_PRIVATE).getAbsolutePath();
        String path = dexDir + File.separator + "xx.zip";
        return new File(path);
    } catch (Exception e) {
    }
    return null;
}

 

发布了106 篇原创文章 · 获赞 37 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/lyz_zyx/article/details/96328449