集成 HTTP 和 HTTPS 连接






4.33/5 (6投票s)
在本文中,我讨论了在 Android 中发起 HTTP 和 HTTPS 请求的过程。
介绍
在本文中,我讨论了在 Android 中发起 HTTP 和 HTTPS 请求的过程。在移动设备上,大多数应用程序都基于通过 HTTP 或 HTTPS 协议的客户端-服务器通信,因此
对于小型或大型应用程序来说,至关重要的是你的 HTTP 模块遵循完整的面向对象原则,并且与应用程序的其他包分离。
背景
涉及的步骤:
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();
}
}
<?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 并发送请求,它就可以在多线程环境中工作。用户可以同时发送多个请求,而无需等待上一个请求完成。