1. 程式人生 > >使用 HTTP 協議訪問網路的兩種方式:HttpURLConnection 和 HttpClient

使用 HTTP 協議訪問網路的兩種方式:HttpURLConnection 和 HttpClient

安卓中進行基於HTTP協議的網路訪問

說明: HttpClient (apache開發)
HttpURLConnection(google在釋出安卓時在Java基礎上修改得到的)

使用HC(HttpClient)/UC(HttpURLConnection)進行網路訪問的基本步驟:
0.申請許可權 INTERNET訪問許可權
1. 任何網路訪問的相關程式碼,必須在工作執行緒中執行!
2. 建立HC/UC物件
3. 聲明發起網路訪問的方式(GET/POST)
4. 進行網路連線
5. 獲得伺服器響應的結果
6. 解析結果,提取需要的內容
7. 解析結果要提交到UI執行緒進行呈現

  • 利用POST方式發起請求,引數要放到請求實體中,並且在請求頭中新增對實體中引數的說明。例如:
新增引數:
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
parameters.add(new BasicNameValuePair("loginname", user.getName()));
parameters.add(new BasicNameValuePair("password", user.getPassword()));
parameters.add(new BasicNameValuePair("realname"
, user.getRealname())); parameters.add(new BasicNameValuePair("email", user.getEmail())); HttpEntity entity = new UrlEncodedFormEntity(parameters); post.setEntity(entity);
新增說明:
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
  • 在HttpClient中設定頭: post.setHeader(key,value);
  • 在HttpURLConnection中設定頭:
    connection.setReqeustProperty(key ,value);

建一個小專案進行說明

1. activity_main.xml 佈局檔案

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.ui.MainActivity" >

    <EditText
        android:id="@+id/et_main_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="請輸入使用者名稱..."
        android:textSize="16sp" />

    <EditText
        android:id="@+id/et_main_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:hint="請輸入密碼..."
        android:inputType="textPassword"
        android:textSize="16sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/et_main_vertifycode"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="3"
            android:hint="請輸入驗證碼..."
            android:textSize="16sp" />

        <ImageView
            android:id="@+id/iv_main_vertifycode"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_launcher" />
    </LinearLayout>

    <View
        android:layout_width="1dp"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="regist"
        android:text="註冊"
        android:textSize="16sp" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="login"
        android:text="登入"
        android:textSize="16sp" />


</LinearLayout>

效果圖:
這裡寫圖片描述

2. 建一個MainActivity 類

package com.example.ui;

import com.example.biz.EmsBiz;
import com.example.listener.OnLoginFinishListener;
import com.example.listener.OnRefreshVertifyCodeListener;
import com.example.web.R;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {
    EditText etName,etPwd,etCode;
    EmsBiz biz;
    ImageView ivImageView;
    String sid;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
        biz=new EmsBiz(this);
        initView();//初始化介面
    }
    private void initView() {
        ivImageView=(ImageView) findViewById(R.id.iv_main_vertifycode);
        //驗證碼的監聽器
        ivImageView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                refresh();//每點選一次驗證碼,就重新整理一次
            }
        });
        etName = (EditText) findViewById(R.id.et_main_name);
        etPwd = (EditText) findViewById(R.id.et_main_password);
      etCode = (EditText) findViewById(R.id.et_main_vertifycode);
    }
    @Override
    protected void onResume() {
        super.onResume();
        //驗證碼的重新整理
        refresh();
    }
    protected void refresh() {
       //為refresh()設定回撥的getVertify方法
       //介面OnRefreshVertifyCodeListener(),並實現介面方法onRefreshFinished
        biz.getVertify(new OnRefreshVertifyCodeListener() {

            @Override
            public void onRefreshFinished(Bitmap bitmap, String sessionId) {
            if(bitmap!=null){
                ivImageView.setImageBitmap(bitmap);                     
            }
            }
        });
    }
    //“註冊”按鈕的onClick,跳轉到“註冊介面”
    public void regist(View v) {        
        Intent intent=new Intent(this,RegistActivity.class);
        startActivity(intent);
    }
    //“登入”按鈕的onClick
    public void login(View v) {
        //應該加入判空
        String loginname = etName.getText().toString();
        String password = etPwd.getText().toString();
        String code = etCode.getText().toString();
        //與上面refresh()一樣,添加回調監聽
        biz.login(loginname,password,code,sid,new OnLoginFinishListener() {

            @Override
            public void OnLoginFinish(String result) {
                if(result!=null){
                    if(result.contains("ok")){
                    //加入Toast提示
                        Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                    }else{
                        Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                        refresh();
                        //如果輸入不正確,將驗證碼和密碼清空
                        etPwd.setText("");
                        etCode.setText("");
                    }
                }else{
                    Toast.makeText(MainActivity.this, "伺服器錯誤", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

3. 建一個OnLoginFinishListener 介面

package com.example.listener;
public interface OnLoginFinishListener {
    void OnLoginFinish(String result);
}

4. 建一個EmsBiz 類

這個類屬於管理層介面了,對於自己做小專案沒有太大意義

package com.example.biz;

import com.example.Utli.EmsUtli;
import com.example.bean.Emp;
import com.example.bean.User;
import com.example.listener.OnAddEmpFinishListener;
import com.example.listener.OnLoginFinishListener;
import com.example.listener.OnRefreshVertifyCodeListener;
import com.example.listener.onRegistFinishListener;

import android.content.Context;
import android.util.Log;

public class EmsBiz {
    private Context context;
    public EmsBiz(Context context) {
        this.context = context;
    }

      //這裡使用兩種方式:HttpClient和HttpURLConnection       
    public void login(String loginname,String password,
String code,String sid,OnLoginFinishListener listener) {
        //EmsUtli.login(loginname,password,code,sid,listener);
        EmsUtli.login2(loginname,password,code,sid,listener);
    }
}

5. 最後再建一個EmsUtli類

package com.example.Utli;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
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.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;

import com.example.bean.Emp;
import com.example.bean.User;
import com.example.bean.ValueObject;
import com.example.listener.OnAddEmpFinishListener;
import com.example.listener.OnLoginFinishListener;
import com.example.listener.OnRefreshVertifyCodeListener;
import com.example.listener.onRegistFinishListener;

public class EmsUtli {
  //使用HttpClient方式
    public static void login(final String loginname, final String password, final String code,final String sid, final OnLoginFinishListener listener) {
        new AsyncTask<Void, Void, String>(){

            @Override
            protected String doInBackground(Void... params) {
                try {
                //HttpClient 是一個介面,因此無法建立它的例項,通常情況下都會建立一個DefaultHttpClient 的例項
                    HttpClient client= new DefaultHttpClient();
                    HttpPost post=new HttpPost("http://172.88.134.136:8080/ems/login.do");
                    //新增一個請求頭,對請求實體中的引數做一個說明
                    //在HttpClient中設定頭:post.setHeader(key,value);
                    post.setHeader("Cookie",sid);
                    post.setHeader("Content-Type","application/x-www-form-urlencoded");
                    //在post中新增請求引數
                    //請求引數會新增在請求實體中
                    List<NameValuePair>parameters = new ArrayList<NameValuePair>();
                    parameters.add(new BasicNameValuePair("loginname", loginname));
                    parameters.add(new BasicNameValuePair("password", password));
                    parameters.add(new BasicNameValuePair("code", code));
                    HttpEntity entity=new UrlEncodedFormEntity(parameters);
                    post.setEntity(entity);
                    HttpResponse resp=client.execute(post);
                    String result=EntityUtils.toString(resp.getEntity());                   
                    return result;              
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
            protected void onPostExecute(String result) {
                listener.OnLoginFinish(result);
            };

        }.execute();
    }

    //HttpURLConnection進行註冊
    public static void login2(final String loginname, final String password, final String code,
            final String sid, final OnLoginFinishListener listener) {
        new Thread(){
            public void run() {
                try {
                    URL url=new URL("http://172.88.134.136:8080/ems/login.do");
                    HttpURLConnection connection=(HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("POST");
                    connection.setDoInput(true);//接收伺服器響應的內容
                    connection.setDoOutput(true);//要向伺服器提交內容
                    //在請求頭中,為請求實體中的內容做說明
                    //在HttpURLConnection中設定頭:connection.setReqeustProperty(key ,value);
                    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                    connection.setRequestProperty("Cookie", sid);
                    connection.connect();
                    OutputStream out=connection.getOutputStream();
                    PrintWriter pw=new PrintWriter(out,true);
                    pw.write(getParams(loginname,password,code));
                    pw.close();
                    //從客戶端獲取伺服器的響應的內容
                    InputStream in=connection.getInputStream();
                    BufferedReader br=new BufferedReader(new InputStreamReader(in));
                    //在這裡我們只有一行,所以這樣寫
                    //若為多行資料,需用:
                    /*StringBuilder sb=new StringBuilder();
                    while ((line=br.readLine())!=null) {
                        sb.append(line);
                    }*/
                    final String result=br.readLine();
                    br.close();
                        //在主執行緒執行
                    new Handler(Looper.getMainLooper()).post(new Runnable() {

                        @Override
                        public void run() {
                            listener.OnLoginFinish(result);
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
        }.start();
    }
   //獲得引數的方法
    protected static String getParams(String loginname, String password,
            String code) {
        Map<String, String> map=new HashMap<String,String>();
        map.put("loginname", loginname);
        map.put("password", password);
        map.put("code", code);
        StringBuilder sb=new StringBuilder();
        for(Entry<String, String> entity:map.entrySet()){
            sb.append(entity.getKey()).append("=").
            append(entity.getValue()).append("&");
        }
        //-1是為了減去最後的“&”字元
        return  sb.substring(0, sb.length()-1);
    }

別忘了在AndroidManifest.xml中註冊

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

在這裡我們選擇了HttpURLConnection執行,將HttpClient進行了註釋,比較推薦使用HttpURLConnection進行HTTP協議訪問網路