1. 程式人生 > >Android使用HttpURLConnect、HttpClient訪問WebService查詢手機號碼歸屬地

Android使用HttpURLConnect、HttpClient訪問WebService查詢手機號碼歸屬地

本內容適合初學Android網路程式設計、XML解析的童鞋檢視,主要內容已添加註釋,所以只貼程式碼即可。

效果圖:


①訪問網路、解析XML檔案工具類: WebServiceUtil.java 

package com.lee.webservicedemo2.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
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.protocol.HTTP;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

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

/**
 * @author Administrator
 *網路上很多使用SOAP協議的方法,這裡就使用http
 */
public class WebServiceUtil {
    static String path = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo";
    
    /**
     * 使用HttpURLConnection的get方式訪問網路,獲取手機號碼歸屬地資料流
     * By Lee in 2014年9月3日
     * */
    public static String getAddressGet(Context context, String mobileNumber)
            throws IOException {
        //String path = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo";

        path = path + "?mobileCode=" + URLEncoder.encode(mobileNumber, "utf-8")
                + "&userId=";
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");

        Log.v("Lee", "GET conn = " + conn);
        if (conn.getResponseCode() == 200) {
            Log.v("Lee", "Connect Successed!");
            return parserXML(conn.getInputStream());
        } else {
            Log.v("Lee",
                    "Connect failed! + error code: " + conn.getResponseCode());
        }
        return null;
    }

    /**
     * 使用HttpURLConnection的Post方式訪問網路,獲取手機號碼歸屬地資料流
     * By Lee in 2014年9月3日
     * */
    public static String getAddressPost(Context context, String mobileNumber)
            throws IOException {
        //String path = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx/getMobileCodeInfo";
        URL url = new URL(path);
        String content = "mobileCode=" + URLEncoder.encode(mobileNumber, "utf-8")+ "&userID=";
        
        Log.v("Lee", "POST content = " + content);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setUseCaches(false);
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length",
                content.getBytes().length + "");
        conn.connect();
        //one:
//        conn.getOutputStream().write(content.getBytes());
//        conn.getOutputStream().flush();
//        conn.getOutputStream().close();
        //two:
//        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
//        dos.writeBytes(content);
//        dos.flush();
//        dos.close();
        //three:
        PrintWriter printer = new PrintWriter(conn.getOutputStream());
        printer.print(content);
        printer.flush();
        printer.close();
        
        Log.v("Lee", "POST conn = " + conn);
        if (conn.getResponseCode() == 200) {
            Log.v("Lee", "Connect Successed!");
            return parserXML(conn.getInputStream());
        } else {
            Log.v("Lee",
                    "Connect failed! + error code: " + conn.getResponseCode());
        }
        return null;
    }

    /**
     * 使用apache HttpClient的get方式訪問網路,獲取手機號碼歸屬地資料流
     * By Lee in 2014年9月3日
     * 
     * 存在問題:只能查詢一次,之後會出現java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)錯誤,
     * 網上找了,沒有找到解決方法,不知道是哪裡的問題
     * */
    public static String getAddressHttpClientGet(Context context, String mobileNumber) throws Exception{
        HttpClient httpClient = new DefaultHttpClient();
        path = path + "?mobileCode=" + URLEncoder.encode(mobileNumber, "utf-8")
                + "&userId=";
        HttpGet httpGet = new HttpGet(path);
        //httpGet.setHeader("Accept", "Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        //httpGet.setHeader(name, value)
        //System.setProperty("http.keepAlive", "false");
        HttpResponse httpResponse = httpClient.execute(httpGet);
        InputStream inputStream = httpResponse.getEntity().getContent();
        //httpGet.abort();
        if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
            //Log.v("Lee", "HttpClientGet---inputStream = " + inputStream);
            String addr = parserXML(inputStream);
            inputStream.close();
            httpGet.abort();
            return addr;
        }
        return null;
    }
    
    /**
     * 使用apache HttpClient的Post方式訪問網路,獲取手機號碼歸屬地資料流
     * By Lee in 2014年9月3日
     * */
    public static String getAddressHttpClientPost(Context context, String mobileNumber) throws Exception{
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpRequest = new HttpPost(path);
        List<NameValuePair> vars = new ArrayList<NameValuePair>();
        vars.add(new BasicNameValuePair("mobileCode", mobileNumber));
        vars.add(new BasicNameValuePair("userId", ""));
        
        httpRequest.setEntity(new UrlEncodedFormEntity(vars, HTTP.UTF_8));
        HttpResponse httpResponse = httpClient.execute(httpRequest);
        InputStream inputStream = httpResponse.getEntity().getContent();
        //httpGet.abort();
        if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
            //Log.v("Lee", "HttpClientGet---inputStream = " + inputStream);
            String addr = parserXML(inputStream);
            inputStream.close();
            httpRequest.abort();
            return addr;
        }
        return null;
    }
    
    
    /**
     * @param inputStream 傳入的是XML檔案流物件
     * @return
     */
    public static String parserXML(InputStream inputStream) {
        SAXParserFactory saxFactory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = saxFactory.newSAXParser();
            ParserXMLHandler handler = new ParserXMLHandler();
            parser.parse(inputStream, handler);
            return handler.getAddress();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

    /**
     * XML檔案解析
     * Android常用的xml解析方法有DOM、SAX、PULL,這裡其實使用PULL方法更簡易的,
     * 不過為了熟悉一下SAX的解析流程,本例使用了SAX
     * */
    static class ParserXMLHandler extends DefaultHandler {

        private String address;
        private String preTag; //記住前一個節點

        public String getAddress() {
            return address;
        }

        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            // TODO Auto-generated method stub
            if (preTag != null) {
                String content = new String(ch, start, length);
                if ("string".equals(preTag)) {
                    address = content;
                    Log.v("Lee", "content == " + content);
                }
            }
        }

        @Override
        public void endDocument() throws SAXException {
            // TODO Auto-generated method stub
            super.endDocument();
        }

        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            // TODO Auto-generated method stub
            preTag = null;
        }

        @Override
        public void startDocument() throws SAXException {
            // TODO Auto-generated method stub
            super.startDocument();
        }

        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            // TODO Auto-generated method stub
            preTag = localName;
        }

    }
}

主介面程式碼MainActivity.java
package com.lee.webservicedemo2;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;

import com.lee.webservicedemo2.util.WebServiceUtil;

/**
 * 注意新增網路訪問許可權:<uses-permission android:name="android.permission.INTERNET"/>
 * 測試手機系統的環境:Android 4.3
 * 
 * */
public class MainActivity extends Activity {
    private TextView tv_addr;
    Handler handler = null;
    String addr = null;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_addr = ((TextView)findViewById(R.id.tv_location));
        //使用Handler更新UI
        handler = new Handler(){

            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                if(msg.what == 0x100){
                    tv_addr.setText(addr);
                }
            }
            
        };
        
        findViewById(R.id.commit_btn).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                //主執行緒不可訪問網路
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            String mobileName = ((EditText) findViewById(R.id.mobilenumber_edit))
                                    .getText().toString().trim();
                            //至少7位才能查詢
                            if(mobileName.length() < 7){
                                addr = null;
                                handler.sendEmptyMessage(0x100);
                                return;
                            }
                            //String temp = WebServiceUtil.getAddressGet(MainActivity.this, mobileName);//GET method
                            
                            String temp = WebServiceUtil.getAddressHttpClientPost(MainActivity.this, mobileName);//使用不同的網路訪問方式
                            if (temp != null && temp.length() > 0) {
                                addr = temp.substring(temp.indexOf(":") + 1, temp.length()); //此處分隔符是中文:冒號
                            }else{
                                addr = null;
                            }
                            //使用Handler更新UI
                            handler.sendEmptyMessage(0x100);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    }
                }).start();
            }
        });
    }


}

佈局檔案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=".MainActivity" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="請輸入手機號碼:" />

    <EditText 
        android:id="@+id/mobilenumber_edit"
        android:layout_marginTop="4dip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="至少7位號碼"/>
    <Button 
        android:id="@+id/commit_btn"
        android:layout_marginTop="4dip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查詢"/>
    <TextView
        android:id="@+id/tv_location"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>