
- 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和POST。GET表示希望從服務(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)用XmlPullParser的setInput()方法將服務(wù)器返回的XML數(shù)據(jù)設(shè)置進去就可以開始解析了。
eventType: 事件類型START_DOCUMENT: 表示讀到文檔的開始位置,START_TAG:表示讀到文檔中的元素開始位置,如idEND_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,name或version,就調(diào)用nextText()方法來獲取節(jié)點內(nèi)具體的內(nèi)容。