android 登录Javaeye(使用HttpURLConnection和HttpClient)

之前在网上看过好多人用java写登录网站,这次正好学习android,自己写实习一个,就拿经常登录的javaeye(现在叫iteye,已经是csdn的了)试一下。

先来分析javaeye登录界面

android 登录Javaeye(使用HttpURLConnection和HttpClient)_第1张图片

查看源文件

          <form action="/login" id="login_form" method="post">            <table border="0" cellspacing="0" cellpadding="0" class="table_1">
              <colgroup><col width="60" /><col /></colgroup>
              <tr>
                <th>账号</th>
                <td>
                  <input class="input_1 required" id="user_name" name="name" placeholder="用户名或邮箱" tabindex="1" type="text" value="" />
                </td>
              </tr>
              <tr>
                <th>密码</th>
                <td>
                  <input class="input_1 required" id="password" name="password" tabindex="2" type="password" value="" /></td>
              </tr>
              <tr>
                <th> </th>
                <td>
                  <input id="auto" name="remember_me" tabindex="3" type="checkbox" value="1" />
                  <label for="auto">下次自动登录</label>
                  <a href="/users/forget">忘记密码?</a>
                </td>
              </tr>
              <tr>
                <th> </th>
                <td><input type="submit" name="button" id="button" value="登 录" class="btn_1 submit" tabindex="4" /></td>
              </tr>
            </table>
          </form>

可以分析出post地址为http://www.iteye.com/login,账号是name、密码是password。

登录以后,使用chrome的开发人员工具(其他浏览器也有相关工具,我就不一一说了)拦截获取响应消息

android 登录Javaeye(使用HttpURLConnection和HttpClient)_第2张图片

可以看出返回的是302地址重定向

android 登录Javaeye(使用HttpURLConnection和HttpClient)_第3张图片

还需要注意的是每次提交时,不能遗漏的cookie即seesion_id ,javaeye用的是_javaeye3_session

接下来是我做的android的例子,使用webview控件,它只负责内容展现,请求响应我分别使用了HttpURLConnection和HttpClient。

不说了,上代码:

主布局main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textViewInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"/>
        
    <WebView
        android:id="@+id/webViewInfo"
        android:layout_width="match_parent"
        android:layout_height="260dp"
        android:layout_below="@+id/textViewInfo"
        android:layout_marginTop="30dp"
        android:layout_alignParentLeft="true" />

	<LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/linearLayout1"
        android:layout_alignParentLeft="true" >
	    <TextView
	        android:id="@+id/textView2"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="使用Java" />
            
	    <Button
	        android:id="@+id/buttonJavaLogin"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	         android:layout_toRightOf="@+id/textView2"
	        android:text="登录ITeye" />
	
	    <Button
	        android:id="@+id/buttonJavaMyMessage"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_toRightOf="@+id/buttonJavaLogin"
	        android:text="ITeye收件箱" />
    </LinearLayout>
    
    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true" >
	    <TextView
	        android:id="@+id/textView1"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="使用Apache" />
            
	    <Button
	        android:id="@+id/buttonApacheLogin"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	         android:layout_toRightOf="@+id/textView1"
	        android:text="登录ITeye" />
	
	    <Button
	        android:id="@+id/buttonApacheMyMessage"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_toRightOf="@+id/buttonApacheLogin"
	        android:text="ITeye收件箱" />
    </LinearLayout>

</RelativeLayout>

登录对话框布局login.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="账号: " />

        <EditText
            android:id="@+id/editTextUsername"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="密码: " />

        <EditText
            android:id="@+id/exitTextPassword"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:inputType="textPassword" />

    </LinearLayout>

</LinearLayout>

AndroidManifest.xml不要忘了加如下代码:

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

主程序代码如下:

package com.zhang.test08_16;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
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.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class Test08_16Activity extends Activity {
	
	private TextView textViewInfo;
	private WebView webViewInfo;
	private Button buttonJavaLogin;
	private Button buttonJavaMyMessage;
	private Button buttonApaceLogin;
	private Button buttonApacheMyMessage;
	
	private View loginView;
	private AlertDialog loginDialog;
	private EditText editTextUserName;
	private EditText editTextPassword;
	
	private String clientType;
	private DefaultHttpClient client;
	private String cookie;
	
	private static final String LOGIN_URL = "http://www.iteye.com/login";
	private static final String MESSAGE_URL = "http://app.iteye.com/messages";
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        textViewInfo = (TextView)findViewById(R.id.textViewInfo);
        webViewInfo = (WebView)findViewById(R.id.webViewInfo);
        buttonJavaLogin = (Button)findViewById(R.id.buttonJavaLogin);
        buttonJavaMyMessage = (Button)findViewById(R.id.buttonJavaMyMessage);
        buttonApaceLogin = (Button)findViewById(R.id.buttonApacheLogin);
        buttonApacheMyMessage = (Button)findViewById(R.id.buttonApacheMyMessage);
        
        LayoutInflater inflater = LayoutInflater.from(this);
        loginView = inflater.inflate(R.layout.login, null);
        editTextUserName = (EditText) loginView.findViewById(R.id.editTextUsername);
        editTextPassword = (EditText) loginView.findViewById(R.id.exitTextPassword);
        loginDialog = getLoginDialog();
        
        buttonJavaLogin.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				clientType = "java";
				loginDialog.show();
			}
		});
        buttonJavaMyMessage.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				showMyMessageJava();
			}
		});
        
        buttonApaceLogin.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				clientType = "apache";
				loginDialog.show();
			}
		});
        buttonApacheMyMessage.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				showMyMessageApache();
			}
		});
    }

    @Override
    protected void onResume() {
        client = new DefaultHttpClient();//client.getCookieStore().getCookies()  session_id
    	HttpParams httpParams = client.getParams();
    	httpParams.setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
    	
    	super.onResume();
    }
    
    @Override
    protected void onPause() {
    	client.getConnectionManager().shutdown();
    	
    	super.onPause();
    }
    
	private AlertDialog getLoginDialog() {
		return new AlertDialog.Builder(Test08_16Activity.this)
			.setTitle("登录")
			.setView(loginView)
			.setPositiveButton("登录", new DialogInterface.OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {
					if (clientType.equals("apache")) {
						loginApache();
					} else if(clientType.equals("java")) {
						loginJava();
					}
				}
			})
			.setNegativeButton("取消", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
				}
			})
			.create();
	}

    private void loginJava() {
    	String username = editTextUserName.getText().toString();
    	String password = editTextPassword.getText().toString();
    	
    	URL url = null;
    	try {
			url = new URL(LOGIN_URL);
		} catch (MalformedURLException e) {
		}
		
		HttpURLConnection urlConnection = null;
    	try {
    		urlConnection = (HttpURLConnection) url.openConnection();
		} catch (IOException e) {
			textViewInfo.setText(e.getMessage());
			return;
		}
		try {
			urlConnection.setRequestMethod("POST");
		} catch (ProtocolException e) {
		}
		urlConnection.setDoOutput(true);
		urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		urlConnection.setRequestProperty("Connection", "keep-alive");
		urlConnection.setInstanceFollowRedirects(false);//
		
		OutputStream out = null;
		try {
			out = new BufferedOutputStream(urlConnection.getOutputStream());//请求
		} catch (IOException e) {
			urlConnection.disconnect();
			textViewInfo.setText(e.getMessage());
			return;
		}
		
		Writer writer = null;
		try {
			writer = new OutputStreamWriter(out,"UTF-8");
		} catch (UnsupportedEncodingException e1) {
		}
		try {
			writer.write("name="+username +"&password="+password);
		} catch (IOException e) {
			urlConnection.disconnect();
			textViewInfo.setText(e.getMessage());
			return;
		} finally{
			try {
				writer.flush();
				writer.close();
			} catch (IOException e) {
			}
		}
		
		getResponseJava(urlConnection);
	}

	private void showMyMessageJava() {
    	URL url = null;
    	try {
			url = new URL(MESSAGE_URL);
		} catch (MalformedURLException e) {
		}
		
		HttpURLConnection urlConnection = null;
    	try {
    		urlConnection = (HttpURLConnection) url.openConnection();
		} catch (IOException e) {
			textViewInfo.setText(e.getMessage());
			return;
		}
		//method  The default value is "GET"
		
		getResponseJava(urlConnection);
	}
    
	//共用HttpClient
	private void loginApache() {
    	String username = editTextUserName.getText().toString();
    	String password = editTextPassword.getText().toString();
    	
    	List<NameValuePair> params = new ArrayList<NameValuePair>(1);
    	params.add(new BasicNameValuePair("name", username));
    	params.add(new BasicNameValuePair("password", password));
    	HttpEntity formEntity = null;
		try {
			formEntity = new UrlEncodedFormEntity(params,HTTP.UTF_8);
		} catch (UnsupportedEncodingException e) {
		}
		
		HttpPost request = new HttpPost(LOGIN_URL);
    	request.setEntity(formEntity);
    	
    	getResponseApache(request);
	}
	
    private void showMyMessageApache() {
    	HttpGet request = new HttpGet(MESSAGE_URL);
    	getResponseApache(request);
	}
    
	private void getResponseJava(HttpURLConnection urlConnection) {
		if(cookie != null) {//session_id
			urlConnection.setRequestProperty("Cookie", cookie);
		}
		
		InputStream in = null;
		try {
			in = new BufferedInputStream(urlConnection.getInputStream());//响应
		} catch (IOException e) {
			urlConnection.disconnect();			
			textViewInfo.setText(e.getMessage());
			return;
		}
		
		cookie = urlConnection.getHeaderField("Set-Cookie");//session_id
		int responseCode = -1;
		try {
			responseCode = urlConnection.getResponseCode();
		} catch (IOException e) {
			urlConnection.disconnect();			
			textViewInfo.setText(e.getMessage());
			return;
		}
		if(responseCode == 301 || responseCode == 302 || responseCode == 307) {//重定向
			String location = urlConnection.getHeaderField("location");
	    	URL url = null;
	    	try {
				url = new URL(location);
			} catch (MalformedURLException e) {
			}
			
			HttpURLConnection urlConnectionRedirect = null;
	    	try {
	    		urlConnectionRedirect = (HttpURLConnection) url.openConnection();
			} catch (IOException e) {
				textViewInfo.setText(e.getMessage());
				return;
			}
			
			getResponseJava(urlConnectionRedirect);
			return;
		}
		
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(in,"UTF-8"));
		} catch (UnsupportedEncodingException e1) {
		}
		StringBuilder result = new StringBuilder();
		String tmp = null;
		try {
			while((tmp = reader.readLine()) != null){
				result.append(tmp);
			}
		} catch (IOException e) {
			textViewInfo.setText(e.getMessage());
			return;
		} finally {
			try {
				reader.close();
				urlConnection.disconnect();
			} catch (IOException e) {
			}
		}
		webViewInfo.loadDataWithBaseURL(null, result.toString(), "text/html", "UTF-8", null);
	}
	
	private void getResponseApache(HttpUriRequest request) {
    	HttpResponse response = null;
    	try {
			response = client.execute(request);//重定向 RedirectStrategy execute while (!done) 
		} catch (ClientProtocolException e) {
			textViewInfo.setText(e.getMessage());
		} catch (IOException e) {
			textViewInfo.setText(e.getMessage());
		}
		
		if (response == null) {
			return;
		}
		
		if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
			textViewInfo.setText("error response" + response.getStatusLine().toString());
			return;
		} 
		
		String result = null;
		try {
			result = EntityUtils.toString(response.getEntity(),"UTF-8");
		} catch (Exception e) {
			textViewInfo.setText("error response" + response.getStatusLine().toString());
			return;
		} 
		webViewInfo.loadDataWithBaseURL(null, result, "text/html", "UTF-8", null);
	}
}

看看运行效果:

主界面:

android 登录Javaeye(使用HttpURLConnection和HttpClient)_第4张图片

点击 使用java登录iteye,弹出登录对话框:

android 登录Javaeye(使用HttpURLConnection和HttpClient)_第5张图片

输入javaeye的账号和密码,点击登录(有点慢,耐心等待),结果如下:

android 登录Javaeye(使用HttpURLConnection和HttpClient)_第6张图片

登录成功了,点击 iteye收件箱(相当于在浏览器里点击收件箱),验证是同一session

android 登录Javaeye(使用HttpURLConnection和HttpClient)_第7张图片

成功,代码没有问题。

使用Apache的方式结果一样,我就不截图了。

做这个例子,我是想了解http协议,httpclient内部实现原理。写的过程中参照如下:

seesion问题:http://hi.baidu.com/%CE%A4%D7%D4%C9%FD/blog/item/e2ce0004f52f2c61030881fa.html

http://helin.iteye.com/blog/257115

302重定向:http://blog.csdn.net/hegch/article/details/1891146

http 417 :http://blog.yes2.me/archives/915

webview乱码:http://hongyang321.iteye.com/blog/1021564

接下来分析一下代码:

先分析java部分,代码和我上篇博客node.js+android http请求响应基本很像,关键的不同

1.解决session的代码:

private String cookie;

if(cookie != null) {//session_id
	urlConnection.setRequestProperty("Cookie", cookie);
}

cookie = urlConnection.getHeaderField("Set-Cookie");//session_id

共享cookie,获取响应前查看是否有cookie,如果有则放在请求头上,获取响应后,拿到cookie存下来。

2.解决重定向的代码:

		if(responseCode == 301 || responseCode == 302 || responseCode == 307) {//重定向
			String location = urlConnection.getHeaderField("location");
	    	URL url = null;
	    	try {
				url = new URL(location);
			} catch (MalformedURLException e) {
			}
			
			HttpURLConnection urlConnectionRedirect = null;
	    	try {
	    		urlConnectionRedirect = (HttpURLConnection) url.openConnection();
			} catch (IOException e) {
				textViewInfo.setText(e.getMessage());
				return;
			}
			
			getResponseJava(urlConnectionRedirect);
			return;
		}
查看响应代码是否需要重定向,如果是读出响应头上的location,发出get请求,递归调用。

再来分析一下httpclient部分:

1.解决407 error

    	HttpParams httpParams = client.getParams();
    	httpParams.setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);

2.解决session

private DefaultHttpClient client;

共用一个client就可以了,cookie存在这client.getCookieStore().getCookies(), 和我们使用一个浏览器,多个标签页共享session原理一样。

3.解决重定向

没有附加任何代码,httpclient内部已经实现,源码主要部分如下:

class AbstractHttpClient
    public final HttpResponse execute(HttpUriRequest request)
        throws IOException, ClientProtocolException {

        return execute(request, (HttpContext) null);
    }
    public final HttpResponse execute(HttpHost target, HttpRequest request,
                                      HttpContext context)

     RequestDirector director = null;
     director = createClientRequestDirector    return new DefaultRequestDirector
     return director.execute(target, request, execContext);

class DefaultRequestDirector 
    public HttpResponse execute(HttpHost target, HttpRequest request,
                                HttpContext context)
           while (!done) {
		RoutedRequest followup = handleResponse(roureq, response, context);
                if (followup == null) {
                    done = true;
                } else {

    protected RoutedRequest handleResponse(RoutedRequest roureq,
                                           HttpResponse response,
                                           HttpContext context)
        if (HttpClientParams.isRedirecting(params) &&
                this.redirectStrategy.isRedirected(request, response, context)) {

class DefaultRedirectStrategy
    public boolean isRedirected(
            final HttpRequest request,
            final HttpResponse response,
            final HttpContext context)

        int statusCode = response.getStatusLine().getStatusCode();
        String method = request.getRequestLine().getMethod();
        Header locationHeader = response.getFirstHeader("location");
        switch (statusCode) {
        case HttpStatus.SC_MOVED_TEMPORARILY:
            return (method.equalsIgnoreCase(HttpGet.METHOD_NAME)
                || method.equalsIgnoreCase(HttpHead.METHOD_NAME)) && locationHeader != null;
        case HttpStatus.SC_MOVED_PERMANENTLY:
        case HttpStatus.SC_TEMPORARY_REDIRECT:
            return method.equalsIgnoreCase(HttpGet.METHOD_NAME)
                || method.equalsIgnoreCase(HttpHead.METHOD_NAME);
        case HttpStatus.SC_SEE_OTHER:
            return true;
        default:
            return false;
        } //end of switch	

处理方法基本和我的一样,除了对象封装意外,它使用的条件循环 while (!done) ,我使用的是条件递归。

ps:使用windows7以后,根据内容找文件很蛋疼,推荐大家使用 UltraFileSearch 官网 http://www.ultrafilesearch.com/,不是广告,只是用了这么多搜索替代工具以后,觉得最好的一个,和大家分享一下

敲了半天怪累的,就说到这了。




你可能感兴趣的:(android,String,ITeye,layout,null,button)