65.9K
CodeProject 正在变化。 阅读更多。
Home

集成 HTTP 和 HTTPS 连接

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (6投票s)

2012年6月2日

CPOL

2分钟阅读

viewsIcon

48686

downloadIcon

1462

在本文中,我讨论了在 Android 中发起 HTTP 和 HTTPS 请求的过程。

介绍  

在本文中,我讨论了在 Android 中发起 HTTP 和 HTTPS 请求的过程。在移动设备上,大多数应用程序都基于通过 HTTP 或 HTTPS 协议的客户端-服务器通信,因此
对于小型或大型应用程序来说,至关重要的是你的 HTTP 模块遵循完整的面向对象原则,并且与应用程序的其他包分离。

本文的重点在于,只有一个类处理两种类型的请求(HTTP 和 HTTPS)。通常,开发者会使用两个不同的类来处理 HTTP 和 HTTPS,但在这种情况下,我将它们处理在一个类中。开发者需要调用一个类并实现一个监听器来获取响应通知。

背景

涉及的步骤: 

String urlString = “HTTP://www.google.com”;

List<NameValuePair> requestParameter= new
List<NameValuePair>();

NameValuePair namVaulePair = new
NameValuePair(“name”,”ravindra”);

requestParameter .add(namVaulePair);

int reqId = 100;
HTTPHandler handler = new HTTPHandler(urlString, requestParameter,null,reqId);

Handler.addHTTPListenr(‘reference of that class implement HTTPListener’); 
Hdler.sendRequest();

使用代码

这个演示项目包含五个类,分为两个包,一个是 UI 包,你可以在其中输入 URL 并点击请求按钮发送请求。

HTTPHandler:这个类处理 HTTP 请求

HTTPHandler(String urlstring, final List<NameValuePair> requestParameters,final 
  Hashtable<String, String> header, int reqId)

User:首先调用构造函数并传递所需的参数。

urlStirng:HTTP 请求的 URL,例如 ‘HTTP://www.google.com’

requestParameters:如果请求方法类型是 ‘POST’,则用户将参数列表设置为 NameValuePair 形式,否则如果请求方法类型是 ‘GET’,则应为 null。

header:它包含你希望在每个 HTTP 请求中设置的头部。 

reqId:HTTP 请求的唯一标识符。

getReqID():它返回 HTTP 请求中使用的唯一请求 ID。

getURL():返回 HTTP 请求中使用的 URL。

getResponse():返回请求服务器返回的响应。

getResCode():它返回 HTTP 状态行。如果返回 200,则请求成功,否则由于服务器原因或客户端请求无效而失败。

addHTTPListener:添加实现 HTTPListener 类的具体类,并重写 notifyResponse() 方法来处理服务器返回的响应。

sendRequest():此方法执行 HTTP 请求。

HTTPHandler 类代码

package com.brickred.HTTP;
 
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import org.apache.HTTP.HTTPEntity;
import org.apache.HTTP.HTTPResponse;
import org.apache.HTTP.HTTPVersion;
import org.apache.HTTP.NameValuePair;
import org.apache.HTTP.client.ClientProtocolException;
import org.apache.HTTP.client.HTTPClient;
import org.apache.HTTP.client.ResponseHandler;
import org.apache.HTTP.client.entity.UrlEncodedFormEntity;
import org.apache.HTTP.client.methods.HTTPGet;
import org.apache.HTTP.client.methods.HTTPPost;
import org.apache.HTTP.conn.ClientConnectionManager;
import org.apache.HTTP.conn.params.ConnManagerPNames;
import org.apache.HTTP.conn.params.ConnPerRouteBean;
import org.apache.HTTP.conn.scheme.PlainSocketFactory;
import org.apache.HTTP.conn.scheme.Scheme;
import org.apache.HTTP.conn.scheme.SchemeRegistry;
import org.apache.HTTP.entity.StringEntity;
import org.apache.HTTP.impl.client.DefaultHTTPClient;
import org.apache.HTTP.impl.conn.SingleClientConnManager;
import org.apache.HTTP.params.BasicHTTPParams;
import org.apache.HTTP.params.CoreConnectionPNames;
import org.apache.HTTP.params.HTTPParams;
import org.apache.HTTP.params.HTTPProtocolParams;
import org.apache.HTTP.util.EntityUtils;
import android.content.Context;
import android.util.Log;

public class HTTPHandler {
    /**
     * refrence of HTTPListener interface
     */
    HTTPListner HTTPListener;
 
    /**
      * url for example
        HTTP://wwww.google.com
      */
 
    String urlstring = "";
 
    /**
      * past request parameter items
      */
 

    List<NameValuePair> postRequestParameters = null;
    /**
     * HTTP unique reqest id
     */
    int reqId = 0;
    /**
      * hold the HTTP response
      */
 
    String resMessage = "No Response Please check Url or it may be HTTPS certificate issue.";
 
    /**
     * response code
     */

    int resCode = -1;
    Hashtable<String, String> header = null;
 
    /**
      * @param urlstring
      * requested url
      * @param requestParameters
      * list post parameters if get request then null
      * @param header
      * list of header
      * @param reqId
      * url request id
      */
    public HTTPHandler(String urlstring,
                     final List<NameValuePair> requestParameters,
                     final Hashtable<String, String> header, int reqId) {
 
        this.urlstring = urlstring;
        this.postRequestParameters = requestParameters;
        this.reqId = reqId;
        this.header = header;
    }
 
    /**
      * @return reqest id for request
      */
 
    public int getReqId() {
        return reqId;
    }

    /**
      * Return requested url
      * 
      * @return
      */
    public String getURL() {
        return urlstring;
    }

    /**
      * @return the response
      */
 
    public String getResponse() {
       return resMessage;
    }

    /**
      * Return Response Code
      * 
      * @return
      */
 
    public int getResCode() {
        return resCode;
    }
 
    /**
      * @param HTTPListener
      * add the listener for notify the response
      */
 
    public void addHTTPLisner(HTTPListner HTTPListener) {
        this.HTTPListener = HTTPListener;
    }

    /**
      * send the HTTP or HTTPS request
      */
 
    public void sendRequest() {
        // TODO Auto-generated method stub
        try {
            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("HTTP", PlainSocketFactory.getSocketFactory(), 80));
            schemeRegistry.register(new Scheme("HTTPS", new EasySSLSocketFactory(), 443));
            HTTPParams params = new BasicHTTPParams();
 

            params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 50000);
            params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30);
            params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30));
            params.setParameter(HTTPProtocolParams.USE_EXPECT_CONTINUE, false);
            HTTPProtocolParams.setVersion(params, HTTPVersion.HTTP_1_1);
            ClientConnectionManager cm = new SingleClientConnManager(params, schemeRegistry);
             

            HTTPClient HTTPclient = new DefaultHTTPClient(cm, params);
 
            // DefaultHTTPClient HTTPclient = null;
            if (postRequestParameters != null) {// //////// for post request
                          // POST the envelope
 
                HTTPPost HTTPpost = new HTTPPost(urlstring);
 
                if (header != null) {
                    Enumeration enums = header.keys();
                    while (enums.hasMoreElements()) {
                        String key = (String) enums.nextElement();
                        String value = header.get(key);
                        HTTPpost.addHeader(key, value);
                    }
                }
 
                HTTPpost.setEntity(new UrlEncodedFormEntity(postRequestParameters));
                // Response handler
                ResponseHandler<String> reshandler = new ResponseHandler<String>() {
                // invoked when client receives response
                public String handleResponse(HTTPResponse response)

                throws ClientProtocolException, IOException {
                    // get response entity
                    HTTPEntity entity = response.getEntity();
 
                    // get response code
                    resCode = response.getStatusLine().getStatusCode();

                    // read the response as byte array
                    StringBuffer out = new StringBuffer();
 
                    byte[] b = EntityUtils.toByteArray(entity);
                    // write the response byte array to a string buffer
                    out.append(new String(b, 0, b.length));
 
                    return out.toString();
                }
            };
 
            resMessage = HTTPclient.execute(HTTPpost, reshandler);
            // Log.d("", "Response=====" + resMessage);
        }
        else {// ///////// for get Request
            ResponseHandler<String> responsehandler = new ResponseHandler<String>() {
                @Override
                    public String handleResponse(HTTPResponse response)
                        throws ClientProtocolException, IOException {
                            // TODO Auto-generated method stub
                            HTTPEntity entity = response.getEntity();
                            
                            // get response code
                            resCode = response.getStatusLine().getStatusCode();
 
                            // read the response as byte array
                            StringBuffer out = new StringBuffer();
 
                            byte[] b = EntityUtils.toByteArray(entity);
                            // write the response byte array to a string buffer
                            out.append(new String(b, 0, b.length));
 
                            return out.toString();
                        }
                    };
 
                    HTTPGet HTTPget = new HTTPGet(urlstring);
                    resMessage = HTTPclient.execute(HTTPget, responsehandler);
                }

                // close the connection
                HTTPclient.getConnectionManager().shutdown();
            }
            catch (Exception e) {
                Log.i("connection Exeception", e.getMessage());
            }
            finally {
                HTTPListener.notifyHTTPRespons(this);
            }
        }
    }

HTTPListener:此监听器必须实现并重写单个抽象方法 notifyResponse(),以获取 HTTP 请求生成的响应并了解请求的状态。

代码

package com.brickred.HTTP;

/**
 * @author ravindrap
 * HTTPListener is super class of which set the HTTP or  HTTPS request 
 */
 
public interface HTTPListner {
    /**
     * @param HTTP
     * HTTP handler object. when HTTP request is completed then is call in HTTPHandler class
     */

    void notifyHTTPRespons(HTTPHandler HTTP);
}

EasySSlSocketFactory:这个 socket factory 类将创建自签名证书。

package com.testHTTPS;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 * https://apache.ac.cn/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
 
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import org.apache.HTTP.conn.ConnectTimeoutException;
import org.apache.HTTP.conn.scheme.LayeredSocketFactory;
import org.apache.HTTP.conn.scheme.SocketFactory;
import org.apache.HTTP.params.HTTPConnectionParams;
import org.apache.HTTP.params.HTTPParams;

/**
 * This socket factory will create ssl socket that accepts self signed
 * certificate
 * 
 * @author olamy
 * @version $Id:
EasySSLSocketFactory.java 765355 2009-04-15 20:59:07Z evenisse

 *          $
 * @since 1.2.3
 */
 
public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory {

    private SSLContext sslcontext = null; 
    private static SSLContext createEasySSLContext() throws IOException {
        try {
            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
            return context;
        } catch (Exception e) {
             throw new IOException(e.getMessage());
    }
}

private SSLContext getSSLContext() throws IOException {
    if (this.sslcontext == null) {
        this.sslcontext = createEasySSLContext();
    }

    return this.sslcontext;
}

/**
 * @see org.apache.HTTP.conn.scheme.SocketFactory#connectSocket(java.net.Socket,
 *      java.lang.String, int, java.net.InetAddress, int,
 *      org.apache.HTTP.params.HTTPParams)
 */
 
public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort, HTTPParams params)

    throws IOException, UnknownHostException, ConnectTimeoutException {
        int connTimeout = HTTPConnectionParams.getConnectionTimeout(params);
        int soTimeout = HTTPConnectionParams.getSoTimeout(params);
         
        InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
        SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());
 
     if ((localAddress != null) || (localPort > 0)) {
         // we need to bind explicitly
         if (localPort < 0) {
             localPort = 0; // indicates "any"
         }
         InetSocketAddress isa = new InetSocketAddress(localAddress, localPort);
         sslsock.bind(isa);
     }
     sslsock.connect(remoteAddress, connTimeout);
     sslsock.setSoTimeout(soTimeout);
     return sslsock;
}
 
/**
 * @see org.apache.HTTP.conn.scheme.SocketFactory#createSocket()
 */
 
public Socket createSocket() throws IOException {
    return getSSLContext().getSocketFactory().createSocket();
}

/**
 * @see org.apache.HTTP.conn.scheme.SocketFactory#isSecure(java.net.Socket)
 */
 
public boolean isSecure(Socket socket) throws IllegalArgumentException {
    return true;
}

/**
 * @see org.apache.HTTP.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket,
 *      java.lang.String, int, boolean)
 */
 
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
   throws IOException, UnknownHostException {
       return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
 
       //return getSSLContext().getSocketFactory().createSocket();
}

// -------------------------------------------------------------------
// javadoc in org.apache.HTTP.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
// -------------------------------------------------------------------
 
public boolean equals(Object obj) {
    return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class));
}
 
public int hashCode() {
    return EasySSLSocketFactory.class.hashCode();
}
}

Class EasyX509TrustManager code: 

package com.brickred.HTTP;

/* 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * https://apache.ac.cn/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory; 
import javax.net.ssl.X509TrustManager;

/**
 * @author olamy
 * @version $Id:
EasyX509TrustManager.java 765355 2009-04-15 20:59:07Z evenisse $
 * @since 1.2.3
 */

public class EasyX509TrustManager
   implements X509TrustManager
{
    private X509TrustManager standardTrustManager = null;

   /**
    * Constructor for EasyX509TrustManager.
    */
    public EasyX509TrustManager( KeyStore keystore )
        throws NoSuchAlgorithmException, KeyStoreException
        {
            super();
            TrustManagerFactory factory = TrustManagerFactory.getInstance( 
                TrustManagerFactory.getDefaultAlgorithm() );
        
            factory.init( keystore );
            TrustManager[] trustmanagers = factory.getTrustManagers();
 
            if ( trustmanagers.length == 0 )
            {
               throw new NoSuchAlgorithmException( "no trust manager found" );
            }
            this.standardTrustManager = (X509TrustManager) trustmanagers[0];
        }
       /**
        * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
        */
 
       public void checkClientTrusted(X509Certificate[] certificates, String authType )

           throws CertificateException
           {
               standardTrustManager.checkClientTrusted( certificates, authType );
           }
       /**
        * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
        */
        public void checkServerTrusted(X509Certificate[] certificates, String authType )
            throws CertificateException
            {
                if ( ( certificates != null) && ( certificates.length == 1 ) )
                {
                     certificates[0].checkValidity();
                } 
                else
                { 
                    standardTrustManager.checkServerTrusted( certificates, authType );
                }
           }
           /**
            * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
            */
 
           public X509Certificate[] getAcceptedIssuers()
           {
             return this.standardTrustManager.getAcceptedIssuers();
           }
        }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="HTTP://schemas.android.com/apk/res/android"
      package="com.brickred" 
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="4" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name="com.brickred.activity.HTTPConnectionApiActivity"
                  android:label="@string/app_name">
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
        </activity>

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

HTTPConnectionApiActivity.java

package com.brickred.activity;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.brickred.R;
import com.brickred.HTTP.HTTPHandler;
import com.brickred.HTTP.HTTPListner;

public class HTTPConnectionApiActivity extends Activity implements HTTPListner{
    /** Called when the activity is first created. */
Handler handler = null;
TextView textviewResponse;
ProgressDialog progressDialog;
EditText edtTextUrl = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button buttonClickMe = (Button)findViewById(R.id.btnclick);
        textviewResponse= (TextView)findViewById(R.id.txtshow);
        edtTextUrl= (EditText)findViewById(R.id.txturl);
        handler = new Handler();
        progressDialog = new ProgressDialog(this);
        
        buttonClickMe.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Log.i("", msg)
if(edtTextUrl.getText().length() > 0 && edtTextUrl.getText().toString().startsWith("HTTP")){ 
progressDialog.setMessage("Please wait for response ... ");
progressDialog.show();
new Thread(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
HTTPHandler handler = new HTTPHandler(edtTextUrl.getText().toString().trim(),null, null, 123);
handler.addHTTPLisner(HTTPConnectionApiActivity.this);
handler.sendRequest();
}
}).start();
}else{
showAlert("Error", "Please enter valid url", null, "Ok");
}

}
});
}

@Override
public void notifyHTTPRespons(final HTTPHandler HTTP) {
// TODO Auto-generated method stub
progressDialog.cancel();
Log.i("Log", "responce ==  "+HTTP.getResCode());
handler.post(new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
textviewResponse.setText("");
textviewResponse.setText(HTTP.getResponse());
}
});
}
/**
* @param title
* @param Message
* @param NegButton
* @param posButton
*/
private void showAlert(String title,String Message, final String NegButton,
final String posButton) {

AlertDialog.Builder alertBuilder = new Builder(this);
alertBuilder.setTitle(title);
alertBuilder.setMessage(Message);
if (NegButton != null) {
alertBuilder.setNegativeButton(NegButton,
new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub

}
});
}
if (posButton != null) {
alertBuilder.setPositiveButton(posButton,
new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub

}
});
}
AlertDialog alert = alertBuilder.create();
alert.show();

}
}

兴趣点 

本文的一个有趣之处在于,用户无需为 HTTP 和 HTTPS 协议编写不同的代码。用户只需根据自己的需求输入 URL 并发送请求,它就可以在多线程环境中工作。用户可以同时发送多个请求,而无需等待上一个请求完成。 

© . All rights reserved.