今天開始android網絡編程,平時作的android整機開發這塊,基本上不大須要接觸android網絡變成這塊知識,仍是得熟悉熟悉。php
本文要講的是使用URLConnection對象和HttpClient組件訪問網絡以及獲取 網頁內容的方法。html
Android對HTTP(超文本傳輸協議)提供了很好的支持,這裏包括兩種接口:java
一、標準Java接口(java.net) ----HttpURLConnection,能夠實現簡單的基於URL請求、響應功能;android
二、Apache接口(org.appache.http)----HttpClient,使用起來更方面更強大。通常來講,用這種接口。不過本文仍是把第一種接口過一下。web
任何一種接口,無外乎四個基本功能:訪問網頁、下載圖片或文件、上傳文件.本文示範的是訪問網頁和下載圖片。HttpURLConnection繼承自URLConnection類,用它能夠發送和接口任何類型和長度的數據,且預先不用知道數據流的長度,能夠設置請求方式get或post、超時時間。apache
先直接上代碼吧:
編程
package com.example.webdatashow; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.DefaultHttpClient; import android.R.string; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener{ private String TAG = "webdatashow"; private Button urlConnection; private Button httpClient; private TextView webDataShow; private String pediyUrl = "http://bbs.pediy.com/forumdisplay.php?f=161"; private static final int MSG_SUCCESS = 0; private static final int MSG_FAILURE = 1; private Handler mHandler = null; private Thread mThread; private Thread httpClientThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.webdata); urlConnection = (Button)findViewById(R.id.urlConnection); httpClient = (Button)findViewById(R.id.httpClient); webDataShow = (TextView)findViewById(R.id.webDataShow); urlConnection.setOnClickListener(this); httpClient.setOnClickListener(this); mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SUCCESS: Toast.makeText(getApplicationContext(), "URLConnection 鏈接成功", Toast.LENGTH_SHORT).show(); webDataShow.setText((String)msg.obj); break; case MSG_FAILURE: Toast.makeText(getApplicationContext(), "URLConnection 鏈接失敗", Toast.LENGTH_SHORT).show(); default: break; } } }; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } @Override public void onClick(View view) { switch (view.getId()) { case R.id.urlConnection: if(mThread == null) { mThread = new Thread(urlConnRunnable); mThread.start(); } break; case R.id.httpClient: if(httpClientThread == null) { httpClientThread = new Thread(httpClientRunnable); httpClientThread.start(); } break; default: break; } } Runnable httpClientRunnable = new Runnable() { @Override public void run() { httpClientWebData(); } }; Runnable urlConnRunnable = new Runnable() { @Override public void run() { try { urlConGetWebData(); } catch (IOException e) { e.printStackTrace(); } } }; private void urlConGetWebData() throws IOException { URL url = new URL(pediyUrl); HttpURLConnection httpConn = (HttpURLConnection)url.openConnection(); if(httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) { Log.d("TAG", "---into-----urlConnection---success--"); InputStreamReader isr = new InputStreamReader(httpConn.getInputStream(), "utf-8"); int i; String content = ""; while((i = isr.read()) != -1) { content = content + (char)i; } mHandler.obtainMessage(MSG_SUCCESS,content).sendToTarget(); isr.close(); httpConn.disconnect(); }else { Log.d("TAG", "---into-----urlConnection---fail--"); } } protected void httpClientWebData() { DefaultHttpClient httpClinet = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(pediyUrl); ResponseHandler<String> responseHandler = new BasicResponseHandler(); try { String content = httpClinet.execute(httpGet, responseHandler); mHandler.obtainMessage(MSG_SUCCESS,content).sendToTarget(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/urlConnection" android:layout_width="fill_parent" android:layout_height="60dip" android:text="urlConnection" /> <Button android:id="@+id/httpClient" android:layout_width="fill_parent" android:layout_height="60dip" android:text="httpClient" /> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/webDataShow" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </ScrollView> </LinearLayout>
作這個須要注意幾點:網絡
1,訪問網絡,記得添加權限
app
<uses-permission android:name="android.permission.INTERNET" />ide
2,使用Http協議錯誤:java.net.MalformedURLException: no protocol:
錯誤緣由就是這是http請求,須要在請求地址上加入 http://協議
3,android.os.NetworkOnMainThreadException
這個異常大概意思是在主線程訪問網絡時出的異常。 Android在4.0以前的版本 支持在主線程中訪問網絡,可是在4.0之後對這部分程序進行了優化,也就是說訪問網絡的代碼不能寫在主線程中了。
4,android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
每一個Android應用程序都運行在一個dalvik虛擬機進程中,進程開始的時候會啓動一個主線程(MainThread),主線程負責處理和ui相關的事件,所以主線程一般又叫UI線程。而因爲Android採用UI單線程模型,因此只能在主線程中對UI元素進行操做。若是在非UI線程直接對UI進行了操做,則會報錯:
CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views
。
Android爲咱們提供了消息循環的機制,咱們能夠利用這個機制來實現線程間的通訊。那麼,咱們就能夠在非UI線程發送消息到UI線程,最終讓Ui線程來進行ui的操做。
對於運算量較大的操做和IO操做,咱們須要新開線程來處理這些繁重的工做,以避免阻塞ui線程
備註:
這兩種方法分別採用HttpClient和URLConnection,好像是HttpClient方式比較穩定,通常都能下載到,可是URLConnection在EDGE網絡下常常下不到數據。