9 (上)看看精彩的世界--使用網(wǎng)絡(luò)技術(shù)

image.jpg
  • WebView的用法
  • 使用HttpURLConnection
  • 使用OkHttp
  • Pull解析方式

9.1 WebView的用法

WebView控件,借助它我們就可以在自己的應(yīng)用程序里嵌入一個瀏覽器,從而非常輕松地展示各種各樣的網(wǎng)頁。

public class MainActivity extends AppCompatActivity
{

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = (WebView) findViewById(R.id.web_view);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient());
        webView.loadUrl("http://www.baidu.com");
    }
}

調(diào)用WebView的getSettings()方法可以去設(shè)置一些瀏覽器的屬性,調(diào)用了setJavaScriptEnabled()方法來讓WebView支持JavaScript腳本。

我們調(diào)用了WebView的setWebViewClient()方法,并傳入了一個WebViewClient實例。這段代碼的作用是,當需要從一個網(wǎng)頁跳轉(zhuǎn)到另一個網(wǎng)頁時,我們希望目標網(wǎng)頁仍然在當前WebView中顯示,而不是打開系統(tǒng)瀏覽器。

調(diào)用WebView的loadUrl()方法,并將網(wǎng)址傳入,即可展示相應(yīng)網(wǎng)頁的內(nèi)容。

由于本程序使用到了網(wǎng)絡(luò)功能,而訪問網(wǎng)絡(luò)是需要申明權(quán)限的。

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

9.2 使用HTTP協(xié)議訪問網(wǎng)絡(luò)

對于HTTP協(xié)議,它的工作原理非常簡單,就是客服端向服務(wù)器發(fā)出一條HTTP請求,服務(wù)器收到請求之后會返回一些數(shù)據(jù)給客服端,然后客服端再對這些數(shù)據(jù)進行解析和處理就可以了。

使用HttpURLConnection

我們就學習一下現(xiàn)在官方建議使用的HttpURLConnection的用法

首先需要獲取到HttpURLConnection的實例,一般只需new出一個URL對象,并傳入目標的網(wǎng)絡(luò)地址,然后調(diào)用一下openConnection()方法即可。

 URL url = new URL("http://www.baidu.com");
connection = (HttpURLConnection) url.openConnection();

在得到了HttpURLConnection的實例之后,我們可以設(shè)置一下HTTP請求所使用的方法。常用的方法主要有兩個:GET和POSTGET表示希望從服務(wù)器那里獲取數(shù)據(jù),而POST則表示希望提交數(shù)據(jù)給服務(wù)器

connection.setRequestMethod("GET");

接下來就可以進行一些自由的定制了,比如設(shè)置連接超時,讀取超時的毫秒數(shù),以及服務(wù)器希望得到的一些消息頭等。

connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);

之后再調(diào)用getInputStream()方法就可以獲取到服務(wù)器返回的輸入流了,剩下的任務(wù)就是對輸入流進行讀取。

InputStream in = connection.getInputStream();

最后可以調(diào)用disconnect()方法將這個HTTP連接關(guān)閉掉。

connection.disconnect();

整體代碼:

public class MainActivity extends AppCompatActivity implements View.OnClickListener
{

    private TextView responseText;
    private Button sendRequest;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sendRequest = (Button) findViewById(R.id.send_request);
        responseText = (TextView) findViewById(R.id.response_text);
        sendRequest.setOnClickListener(this);

    }

    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
            case R.id.send_request:
                setSendRequestWithHttpURLConnection();
                break;
            default:
                break;
        }
    }

    private void setSendRequestWithHttpURLConnection()
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try
                {
                    URL url = new URL("http://www.baidu.com");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    InputStream in = connection.getInputStream();
                    //下面對獲取到的輸入流進行讀取
                    reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null)
                    {
                        response.append(line);
                    }
                    showResponse(response.toString());
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
                finally
                {
                    if (reader != null)
                    {
                        try
                        {
                            reader.close();
                        } catch (IOException e)
                        {
                            e.printStackTrace();
                        }
                    }
                    if (connection != null)
                    {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    private void showResponse(final String response)
    {
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                //在這里進行UI操作,將結(jié)果顯示到界面上
                responseText.setText(response);
            }
        });
    }
    
}

在Send Request按鈕的點擊事件里調(diào)用了sendRequestWithHttpURLConnection()方法,在這個方法中先是開啟了一個子線程,然后在子線程里使用HttpURLConnection發(fā)出一條HTTP請求,請求的目標地址就是百度的首頁。接著利用BufferedReader對服務(wù)器返回的流進行讀取,并將結(jié)果傳入到了showResponse()方法中。而在showResponse()方法中則是調(diào)用了一個runOnUiThread()方法,然后在這個方法的匿名類參數(shù)中進行操作,將返回的數(shù)據(jù)顯示到界面上。那么這里為什么要用這個runOnUiThread()方法呢?這是因為Android不允許在子線程中進行UI操作的,我們需要通過這個方法將線程切換到主線程,然后再更新UI元素。

如果是想要提交數(shù)據(jù)給服務(wù)器應(yīng)該怎么辦呢?只要將HTTP請求的方法改成POST,并在獲取輸入流之前把要提交的數(shù)據(jù)寫出即可。注意每條數(shù)據(jù)都要以鍵值對的形式存在,數(shù)據(jù)與數(shù)據(jù)之間用"&"符號隔開,比如說我們想要向服務(wù)器提交用戶名和密碼。

connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=admin&password=123456");

9.2 使用OkHttp

在項目中添加OkHttp庫的依賴。

compile 'com.squareup.okhttp3:okhttp:3.6.0'

添加上訴依賴會自動下載兩個庫,一個是OkHttp庫,一個是OKio庫,后者是前者的通信基礎(chǔ)。

OkHttp的具體用法

首先需要創(chuàng)建一個OkHttpClient的實例。

OkHttpClient okHttpClient = new OkHttpClient();

接下來如果想要發(fā)起一條HTTP請求,就需要創(chuàng)建一個Request的對象。

Request request = new Request.Builder()
              .url("http://www.baidu.com")
              .build();

我們可以在最終的build()方法之前連綴很多其他方法來豐富這個Request對象。比如可以通過url()方法來設(shè)置目標的網(wǎng)絡(luò)地址。

之后調(diào)用OkHttpClient的newCall()方法來創(chuàng)建一個Call()對象,并調(diào)用它的execute()方法來發(fā)送請求并獲取服務(wù)器返回的數(shù)據(jù),其中Response對象就是服務(wù)器返回的數(shù)據(jù)了。

Response response = okHttpClient.newCall(request).execute();

String responeData = response.body().string();

如果是發(fā)起一條POST請求會比GET請求稍微復雜一點,我們需要先構(gòu)建出一個RequestBody對象來存放待提交的參數(shù)。

RequestBody requestBody = new FormBody.Builder()
                .add("username","admin")
                .add("password","123456")
                .build();

然后在Request.Builder中調(diào)用一下post()方法,將RequestBody對象傳入。

Request request = new Request.Builder()
            .url("http://www.baidu.com")
            .post(requestBody)
            .build();

接下來就和GET請求一樣了,調(diào)用execute()方法來發(fā)送請求并獲取服務(wù)器返回的數(shù)據(jù)即可。
整體代碼:

private void sendRequestWithOkHttp()
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    OkHttpClient okHttpClient = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url("http://www.baidu.com")
                            .build();
                    Response response = okHttpClient.newCall(request).execute();
                    showResponse(response.body().string());
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }).start();
    }

9.3 解析XML格式文件

安裝Apache軟件,現(xiàn)存入一個XML文件

<apps>
    <app>
        <id>1</id>
        <name>Google Maps</name>
        <version>1.0</version>
    </app>

    <app>
        <id>2</id>
        <name>Chrome</name>
        <version>2.1</version>
    </app>

    <app>
        <id>3</id>
        <name>Google Play</name>
        <version>2.3</version>
    </app>
</apps>

Pull解析方式

Request request = new Request.Builder()
        .url("http://192.168.1.101/get_data.xml")
        .build();

這里將HTTP請求的地址改成了http://192.168.1.101/get_data.xml。192.168.1.101是電腦本機的IP地址。

如果是模擬器的話,http://10.0.2.2/get_data.xml。10.0.2.2對于模擬器來說就是電腦本機的IP地址。

private void parseXMLWithPull(String xmlData) {
        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser xmlPullParser = factory.newPullParser();
            xmlPullParser.setInput(new StringReader(xmlData));
            int eventType = xmlPullParser.getEventType();
            String id = "";
            String name = "";
            String version = "";

            // 獲取pull解析器對應(yīng)事件類型
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String nodeName = xmlPullParser.getName();
                switch (eventType) {
                    //開始解析某個節(jié)點
                    case XmlPullParser.START_TAG: {

                        if ("id".equals(nodeName)) {
                            id = xmlPullParser.nextText();
                        } else if ("name".equals(nodeName)) {
                            name = xmlPullParser.nextText();
                        } else if ("version".equals(nodeName)) {
                            version = xmlPullParser.nextText();
                        }
                        break;
                    }
                    case XmlPullParser.END_TAG: {
                        if ("app".equals(nodeName)) {
                            Log.d(TAG, "id is : "+id);
                            Log.d(TAG, "name is : "+name);
                            Log.d(TAG, "version is : "+version);
                        }
                        break;
                    }
                    default:
                        break;
                }
                eventType = xmlPullParser.next();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

看下parseXMLWithPull()方法,首先要獲取到一個XmlPullParserFactory的實例,并借助這個實例得到XmlPullParser對象,然后調(diào)用XmlPullParsersetInput()方法將服務(wù)器返回的XML數(shù)據(jù)設(shè)置進去就可以開始解析了。

  • eventType: 事件類型
  • START_DOCUMENT: 表示讀到文檔的開始位置,
  • START_TAG:表示讀到文檔中的元素開始位置,如id
  • END_DOCUMENT:表示讀到文檔結(jié)束的位置
  • END_TAG: 表示讀到文檔中的元素結(jié)束位置

通過getEventType()可以得到當前的解析事件,然后在一個while循環(huán)中不斷地進行解析,如果當前的解析事件不等于XmlPullParser.END_DOCUMENT,說明解析工作還沒完成,調(diào)用next()方法后可以獲取下一個解析事件。

while循環(huán)中,我們通過getName()方法得到當前節(jié)點的名字,如果發(fā)現(xiàn)節(jié)點名等于id,nameversion,就調(diào)用nextText()方法來獲取節(jié)點內(nèi)具體的內(nèi)容。

附錄:
使用XmlPullParser解析xml文件
通過XmlPullParser類解析xml

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,230評論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,659評論 19 139
  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 12,457評論 6 13
  • 曾經(jīng)閉口不談的黑歷史會在多年后的無數(shù)個夜里一夜又一夜地襲擊你的睡眠。 那時才明白,躲避不能讓過去成為過去。讓過去成...
    我是胖胖閱讀 325評論 0 0
  • vhjhhuisnwbbjjsjbbdbjsjj
    仇志軒閱讀 235評論 0 5

友情鏈接更多精彩內(nèi)容