HttpClient对于https的支持和配置

来源:互联网 发布:盐城金石计价软件 编辑:程序博客网 时间:2024/06/05 19:00

网上有许多对于https的支持配置,但是对于一些新手而言,显然不够直接拿来复制粘贴然后运行出来,所以今天就将整套代码拿出来与大家分享,希望指正错误和帮我优化代码


public static DefaultHttpClient create(boolean isHttps) throws Exception{        HttpParams params = createHttpParams();        DefaultHttpClient httpClient = null;        if (isHttps) {            // 支持httphttps            KeyStore trustStore = null;            try {                trustStore = KeyStore.getInstance(KeyStore.getDefaultType());                trustStore.load(null, null);                SSLSocketFactory sf = new MySSLSocketFactory(trustStore);            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);            SchemeRegistry schemeRegistry = new SchemeRegistry();            schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));//            schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));                schemeRegistry.register(new Scheme("https", sf, 443));            // ThreadSafeClientConnManager线程安全管理类            ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);            httpClient = new DefaultHttpClient(cm, params);            } catch (Exception e) {            }        } else {            httpClient = new DefaultHttpClient(params);        }        return httpClient;    }
上述代码很明显是获取httpClient的实体,分为支持或者不支持https俩种,简单明了

private static class MySSLSocketFactory extends SSLSocketFactory {    SSLContext sslContext = SSLContext.getInstance("TLS");    public MySSLSocketFactory(KeyStore truststore)            throws NoSuchAlgorithmException, KeyManagementException,            KeyStoreException, UnrecoverableKeyException {        super(truststore);        TrustManager tm = new X509TrustManager() {            public void checkClientTrusted(X509Certificate[] chain, String authType)                    throws CertificateException {            }            public void checkServerTrusted(X509Certificate[] chain, String authType)                    throws CertificateException {            }            public X509Certificate[] getAcceptedIssuers() {                return null;            }        };        sslContext.init(null, new TrustManager[]{tm}, null);    }    @Override    public Socket createSocket(Socket socket, String host, int port, boolean autoClose)            throws IOException, UnknownHostException {        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);    }    @Override    public Socket createSocket() throws IOException {        return sslContext.getSocketFactory().createSocket();    }}private static HttpParams createHttpParams() {    final HttpParams params = new BasicHttpParams();    // 设置是否启用旧连接检查,默认是开启的。关闭这个旧连接检查可以提高一点点性能,但是增加了I/O错误的风险(当服务端关闭连接时)。    // 开启这个选项则在每次使用老的连接之前都会检查连接是否可用,这个耗时大概在15-30ms之间    HttpConnectionParams.setStaleCheckingEnabled(params, false);    HttpConnectionParams.setConnectionTimeout(params, TIMEOUT);// 设置链接超时时间    HttpConnectionParams.setSoTimeout(params, TIMEOUT);// 设置socket超时时间    HttpConnectionParams.setSocketBufferSize(params, SOCKET_BUFFER_SIZE);// 设置缓存大小    HttpConnectionParams.setTcpNoDelay(params, true);// 是否不使用延迟发送(true为不延迟)    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); // 设置协议版本    HttpProtocolParams.setUseExpectContinue(params, true);// 设置异常处理机制    HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);// 设置编码    HttpClientParams.setRedirecting(params, false);// 设置是否采用重定向    ConnManagerParams.setTimeout(params, TIMEOUT);// 设置超时    ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(MAX_CONNECTIONS));// 多线程最大连接数    ConnManagerParams.setMaxTotalConnections(params, 10); // 多线程总连接数    return params;}private static void createHttpClient(DefaultHttpClient httpClient) {    // 添加request的拦截器,添加必要的头信息    httpClient.addRequestInterceptor(new HttpRequestInterceptor() {        public void process(HttpRequest request, HttpContext context) {            if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {                request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);            }        }    });    // 添加response拦截器,预先对response进行一些处理    httpClient.addResponseInterceptor(new HttpResponseInterceptor() {        public void process(HttpResponse response, HttpContext context) {            final HttpEntity entity = response.getEntity();            if (entity == null) {                return;            }            final Header encoding = entity.getContentEncoding();            if (encoding != null) {                for (HeaderElement element : encoding.getElements()) {                    // 如果是以GZIP压缩的数据,利用内部的填充器包装一层Gzip的流                    if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {                        response.setEntity(new InflatingEntity(response.getEntity()));                        break;                    }                }            }        }    });    // 设置重试次数    httpClient.setHttpRequestRetryHandler(new HttpRetry(MAX_RETRIES));}/** * 当服务器返回的数据是以Gzip压缩的过后的数据,填充Response返回的实体数据 (Description),则返回GZIP解压流 */private static class InflatingEntity extends HttpEntityWrapper {    public InflatingEntity(HttpEntity wrapped) {        super(wrapped);    }    @Override    public InputStream getContent() throws IOException {        return new GZIPInputStream(wrappedEntity.getContent());    }    // 因为数据是压缩数据,所以实际长度无法估计,可以返回-1    @Override    public long getContentLength() {        return -1;    }}/** * 自定义的安全套接字协议的实现,目前采用默认的,未使用到 */private static class SSLSocketFactoryEx extends SSLSocketFactory {    // 此类的实例表示安全套接字协议的实现,它充当用于安全套接字工厂或 SSLEngine 的工厂。用可选的一组密钥和信任管理器及安全随机字节源初始化此类。    SSLContext sslContext = SSLContext.getInstance("TLS");    public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {        super(truststore);        // TrustManager负责管理做出信任决定时使用的的信任材料,也负责决定是否接受同位体提供的凭据。        // X509TrustManager此接口的实例管理使用哪一个 X509 证书来验证远端的安全套接字。决定是根据信任的证书授权、证书撤消列表、在线状态检查或其他方式做出的。        TrustManager tm = new X509TrustManager() {            public X509Certificate[] getAcceptedIssuers() {                return null;// 返回受验证同位体信任的认证中心的数组。            }            @Override            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {                // 给出同位体提供的部分或完整的证书链,构建到可信任的根的证书路径,并且返回是否可以确认和信任将其用于基于验证类型的客户端 SSL 验证。            }            @Override            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {                // 给出同位体提供的部分或完整的证书链,构建到可信任的根的证书路径,并且返回是否可以确认和信任将其用于基于验证类型的服务器 SSL 验证。            }        };        sslContext.init(null, new TrustManager[]{tm}, null);    }    @Override    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);    }    @Override    public Socket createSocket() throws IOException {        return sslContext.getSocketFactory().createSocket();    }}
注释已经很清楚了,如有疑问请留言,那么我们如何使用这些看似很费解的代码呢,下面就以下载https开头的URL地址的文件来模拟实战,也就是APK的下载更新,希望对大家有帮助。

首先,我们需要一个UpDateManager,默认使用单例模式。

public static UpDateManager getUpDateManager(Context context, Handler handler, ProgressDialog pBar) {    if (upDateManager == null) {        //防止内部代码        //线程不安全        synchronized (UpDateManager.class) {            if (upDateManager == null) {                upDateManager = new UpDateManager(context, handler, pBar);            }        }    }    return upDateManager;}

handler和pbar是为了告诉主线程显示下载进度
private boolean isStop = true;public boolean isStop() {    return isStop;}public void setIsStop(boolean isStop) {    if (!isStop) {        FileUtils.deleteFile(SDPATH + fileName);    }    this.isStop = isStop;}

阻止下载,并删除为完成下载的文件,
public void downFile(final String url) {        if (pBar != null) {            pBar.show();        }        new Thread() {            public void run() {                try {                    AbstractHttpClient client = HttpClientFactory.create(true);                    HttpGet get = new HttpGet(url);                    HttpResponse response;                    response = client.execute(get);                    HttpEntity entity = response.getEntity();                    long length = entity.getContentLength();                    InputStream is = entity.getContent();                    Log.e("liushun", "length...." + length);//                    FileUtils.writeFile(is, FileUtils.getExternalStoragePath()//                            + ".kg-gold.com" + "Download" + url, false);                    FileOutputStream fileOutputStream = null;                    if (is != null) {//                        FileUtils.writeFile(is, FileUtils.getExternalStoragePath()//                                + ".kg-gold.com" + "Download" + url, false);//                        File file = new File(//                                Environment.getExternalStorageDirectory(),//                                fileName);                        FileUtils.deleteFile(SDPATH + fileName);                        File file = FileUtils.creatSDFile(fileName);                        fileOutputStream = new FileOutputStream(file);                        byte[] buf = new byte[1024];                        int ch = -1;                        long count = 0;                        while ((ch = is.read(buf)) != -1 && isStop) {                            fileOutputStream.write(buf, 0, ch);                            count += ch;                            if (length > 0) {                                if (pBar != null) {                                    downProcess = count * 100 / length + "";                                    Message msg = Message.obtain();                                    msg.obj = downProcess;                                    msg.what = 55;                                    handler.sendMessage(msg);                                }                                Log.e("liushun", "count%..." + downProcess);                            }                        }                    }                    if (isStop) {                        fileOutputStream.flush();                        if (fileOutputStream != null) {                            fileOutputStream.close();                        }                        down();                    }                } catch (ClientProtocolException e) {                    //下载失败                    e.printStackTrace();                } catch (IOException e) {                    //下载失败                    e.printStackTrace();                } catch (Exception e) {                    e.printStackTrace();                }            }        }.start();    }
这是下载的核心代码,
 AbstractHttpClient client = HttpClientFactory.create(true); 是创建支持https的HttpClent
void update() {    Intent intent = new Intent(Intent.ACTION_VIEW);    intent.setDataAndType(Uri.fromFile(new File(Environment                    .getExternalStorageDirectory(), fileName)),            "application/vnd.android.package-archive");    context.startActivity(intent);}
下载完成,然后触发系统的安装流程。



0 0