WebView的用法
Android提供了一個WebView控件,藉助它我們就可以在自己的應用程序裏嵌入一個瀏覽器,從而非常輕鬆地展示各種各樣的網頁。WebView的用法也是相當簡單,下面我們就通過一個例子來學習一下吧。新建一個WebViewTest項目,然後修改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">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
然後修改MainActivity中的代碼,如下所示:
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends Activity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView=(WebView) findViewById(R.id.web_view);
webView.getSettings().setJavaScriptEnabled(true);//調用了setJavaScriptEnabled()
//方法來讓WebView支持JavaScript腳本
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url); // 根據傳入的參數再去加載新的網頁
return true; // 表示當前WebView可以處理打開新網頁的請求,不用藉助系統瀏覽器
}
});
webView.loadUrl("http://www.baidu.com/");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
***MainActivity中的代碼也很短,首先使用findViewById()方法獲取到了WebView的實例,然後調用WebView的getSettings()方法可以去設置一些瀏覽器的屬性,這裏我們並不去設置過多的屬性,只是調用了setJavaScriptEnabled()方法來讓WebView支持JavaScript腳本。
接下來是非常重要的一個部分,我們調用了WebView的setWebViewClient()方法,並傳入了WebViewClient的匿名類作爲參數,然後重寫了shouldOverrideUrlLoading()方法。這就表明當需要從一個網頁跳轉到另一個網頁時,我們希望目標網頁仍然在當前WebView中顯示,而不是打開系統瀏覽器。
最後一步就非常簡單了,調用WebView的loadUrl()方法,並將網址傳入,即可展示相應網頁的內容,這裏就讓我們看一看百度的首頁是長什麼樣的吧。
另外還需要注意,由於本程序使用到了網絡功能,而訪問網絡是需要聲明權限的,因此我們還得修改AndroidManifest.xml文件,並加入權限聲明,如下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.webviewtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission **android:name="android.permission.INTERNET"/>**
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
2. 使用HTTP協議訪問網絡
它的工作原理特別的簡單,就是客戶端向服務器發出一條HTTP請求,服務器收到請求之後會返回一些數據給客戶端,然後客戶端再對這些數據進行解析和處理就可以了。
2.1 使用HttpURLConnection
在Android上發送HTTP請求的方式一般有兩種,HttpURLConnection和HttpClient,本小節我們先來學習一下HttpURLConnection的用法。
首先需要獲取到HttpURLConnection的實例,一般只需new出一個URL對象,並傳入目標的網絡地址,然後調用一下openConnection()方法即可,如下所示:
URL url = new URL(“http://www.baidu.com“);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
得到了HttpURLConnection的實例之後,我們可以設置一下HTTP請求所使用的方法。常用的方法主要有兩個,GET和POST。GET表示希望從服務器那裏獲取數據,而POST則表示希望提交數據給服務器。寫法如下:
connection.setRequestMethod(“GET”);
接下來就可以進行一些自由的定製了,比如設置連接超時、讀取超時的毫秒數,以及服務器希望得到的一些消息頭等。這部分內容根據自己的實際情況進行編寫,示例寫法如下:
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
之後再調用getInputStream()方法就可以獲取到服務器返回的輸入流了,剩下的任務就是對輸入流進行讀取,如下所示:
InputStream in = connection.getInputStream();
最後可以調用disconnect()方法將這個HTTP連接關閉掉,如下所示:
connection.disconnect();
下面就讓我們通過一個具體的例子來真正體驗一下HttpURLConnection的用法。新建一個NetworkTest項目,首先修改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"
>
<Button
android:id="@+id/send_request"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send Request" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/response"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
藉助ScrollView控件的話就可以允許我們以滾動的形式查看屏幕外的那部分內容。另外,佈局中還放置了一個Button和一個TextView,Button用於發送HTTP請求,TextView用於將服務器返回的數據顯示出來。
接着修改MainActivity中的代碼,如下所示:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
public static final int SHOW_RESPONSE=0;
private Button sendRequest;
private TextView responseText;
private Handler handler=new Handler(){
public void handleMessage(Message msg){
switch (msg.what) {
case SHOW_RESPONSE:
String response=(String) msg.obj;//在這裏進行ui操作,將結果顯示在界面上
responseText.setText(response);
}
}
};
@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);
sendRequest.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onClick(View v) {
if(v.getId()==R.id.send_request){
sendRequestWithHttpURLConnection();
}
}
private void sendRequestWithHttpURLConnection() {
// TODO Auto-generated method stub
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
HttpURLConnection connection=null;
try{
URL url=new URL("http://www.baidu.com");
connection=(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
//設置鏈接超時的時間
//將讀超時設置爲指定的超時值,以毫秒爲單位。用一個非零值指定在建立到資源的連接後從input流讀入時的超時時間。
//如果在數據可讀取之前超時期滿,則會引發一個 java.net.sockettimeoutexception。超時時間爲零表示無窮大超時。
connection.setReadTimeout(8000);
InputStream in=connection.getInputStream();
//下面對獲取到的輸入流進行讀取
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder response=new StringBuilder();
String line;
while((line=reader.readLine())!=null){
response.append(line);
}
Message message=new Message();
message.what=SHOW_RESPONSE;
//將服務器返回的結果存放到Message中
message.obj=response.toString();
handler.sendMessage(message);
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
if(connection!=null){
connection.disconnect();
}
}
}
}).start();
}
}
仍然別忘了要聲明一下網絡權限
現在運行一下程序,並點擊Send Request按鈕,結果如圖2所示:
2.2 使用HttpClient
HttpClient是Apache提供的HTTP網絡訪問接口,從一開始的時候就被引入到了Android API中。它可以完成和HttpURLConnection幾乎一模一樣的效果,但兩者之間的用法卻有較大的差別,那麼我們自然要看一下HttpClient是如何使用的了。
首先你需要知道,HttpClient是一個接口,因此無法創建它的實例,通常情況下都會創建一個DefaultHttpClient的實例,如下所示:
HttpClient httpClient = new DefaultHttpClient();
接下來如果想要發起一條GET請求,就可以創建一個HttpGet對象,並傳入目標的網絡地址,然後調用HttpClient的execute()方法即可:
HttpGet httpGet = new HttpGet(“http://www.baidu.com“);
httpClient.execute(httpGet);
如果是發起一條POST請求會比GET稍微複雜一點,我們需要創建一個HttpPost對象,並傳入目標的網絡地址,如下所示:
HttpPost httpPost = new HttpPost(“http://www.baidu.com“);
然後通過一個NameValuePair集合來存放待提交的參數,並將這個參數集合傳入到一個UrlEncodedFormEntity中,然後調用HttpPost的setEntity()方法將構建好的UrlEncodedFormEntity傳入,如下所示:
List params = new ArrayList();
params.add(new BasicNameValuePair(“username”, “admin”));
params.add(new BasicNameValuePair(“password”, “123456”));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, “utf-8”);
httpPost.setEntity(entity);
接下來的操作就和HttpGet一樣了,調用HttpClient的execute()方法,並將HttpPost對象傳入即可:
httpClient.execute(httpPost);
執行execute()方法之後會返回一個HttpResponse對象,服務器所返回的所有信息就會包含在這裏面。通常情況下我們都會先取出服務器返回的狀態碼,如果等於200就說明請求和響應都成功了,如下所示:
if (httpResponse.getStatusLine().getStatusCode() == 200) {
// 請求和響應都成功了
}
接下來在這個if判斷的內部取出服務返回的具體內容,可以調用getEntity()方法獲取到一個HttpEntity實例,然後再用EntityUtils.toString()這個靜態方法將HttpEntity轉換成字符串即可,如下所示:
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity);
注意如果服務器返回的數據是帶有中文的,直接調用EntityUtils.toString()方法進行轉換會有亂碼的情況出現,這個時候只需要在轉換的時候將字符集指定成utf-8就可以了,如下所示:
String response = EntityUtils.toString(entity, “utf-8”);
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
public static final int SHOW_RESPONSE=0;
private Button sendRequest;
private TextView responseText;
private Handler handler=new Handler(){
public void handleMessage(Message msg){
switch (msg.what) {
case SHOW_RESPONSE:
String response=(String) msg.obj;//在這裏進行ui操作,將結果顯示在界面上
responseText.setText(response);
}
}
};
@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);
sendRequest.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onClick(View v) {
if(v.getId()==R.id.send_request){
sendRequestWithHttpURLConnection();
}
}
private void sendRequestWithHttpURLConnection() {
// TODO Auto-generated method stub
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
HttpURLConnection connection=null;
try{
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
// 請求和響應都成功了
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity, "utf-8");
Message message = new Message();
message.what = SHOW_RESPONSE;
// 將服務器返回的結果存放到Message中
message.obj = response.toString();
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}