Android 連網功能
Android 基於 Linux 核心,包含一組優秀的連網功能。如果尚未安裝 Android SDK,那麼需要 下載 它才能實踐本文的樣本。
表 1 展示了 Android SDK 中一些與網路有關的包。
表 1. Android SDK 網路包
| 包 |
描述 |
| java.net |
提供與連網有關的類,包括流和資料包(datagram)sockets、網際網路通訊協定 (IP)和常見 HTTP 處理。該包是一個多功能網路資源。有經驗的 Java 開發人員可以立即使用這個熟悉的包建立應用程式。 |
| java.io |
雖然沒有提供顯式的連網功能,但是仍然非常重要。該包中的類由其他 Java 包中提供的 socket 和串連使用。它們還用於與本地檔案(在與網路進行互動時會經常出現)的互動。 |
| java.nio |
包含表示特定資料類型的緩衝區的類。適合用於兩個基於 Java 語言的端點之間的通訊。 |
| org.apache.* |
表示許多為 HTTP 通訊提供精確控制和功能的包。可以將 Apache 視為流行的開源 Web 服務器。 |
| android.net |
除核心 java.net.* 類以外,包含額外的網路訪問 socket。該包包括 URI 類,後者頻繁用於 Android 應用程式開發,而不僅僅是傳統的連網方面。 |
| android.net.http |
包含處理 SSL 憑證的類。 |
| android.net.wifi |
包含在 Android 平台上管理有關 WiFi(802.11 無線 Ethernet)所有方面的類。並不是所有裝置都配備了 WiFi 功能,特別是 Android 在 Motorola 和 LG 等手機製造商的 “翻蓋手機” 領域獲得了成功。 |
| android.telephony.gsm |
包含用於管理和發送 SMS(文本)訊息的類。一段時間後,可能會引入額外的包來來為非 GSM 網路提供類似的功能,比如 CDMA 或 android.telephony.cdma 等網路。 |
上表並沒有列出所有包,但是可以讓您清楚地意識到該平台的強大功能。下一小節將介紹一些簡單的網路樣本。
簡單的網路樣本
為了示範將 Android 串連到一個網路有多麼簡單,這個樣本將展示如何從 Web 頁面發送文本。可以 下載 本例的原始碼。圖 1 展示了應用程式的實際使用。
圖 1. 從 Web 頁面擷取文本
本節提供了構建應用程式範例所需的代碼。我們將首先查看 UI 部分,然後介紹與網路有關的代碼。
共有三個 UI 元素:
- EditText 讓使用者能夠進入一個 Web 頁面(圖 1 和 清單 2 所示的 http://developer.android.com)。
- 使用一個按鈕告訴程式取回 Web 頁面文本。
- 檢索回資料後,它將顯示在 TextView 中。
清單 1 展示了 main.xml 檔案,這是該應用程式的完整 UI 布局。
清單 1. main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" ><EditText android:layout_height="wrap_content"android:id="@+id/address"android:layout_width="fill_parent"android:text="http://google.com"></EditText><Button android:id="@+id/ButtonGo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="go!" ></Button><TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff" android:textColor="#000000"android:id="@+id/pagetext" /></LinearLayout> |
清單 2 展示了本樣本使用的 Java 代碼。
清單 2. GetWebPage.java
package com.msi.getwebpage;import android.app.Activity;import android.os.Bundle;// used for interacting with user interfaceimport android.widget.Button;import android.widget.TextView;import android.widget.EditText;import android.view.View;// used for passing data import android.os.Handler;import android.os.Message;// used for connectivityimport java.io.BufferedReader;import java.io.InputStreamReader;import java.net.URL;import java.net.URLConnection;public class GetWebPage extends Activity { /** Called when the activity is first created. */ Handler h;@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final EditText eText = (EditText) findViewById(R.id.address); final TextView tView = (TextView) findViewById(R.id.pagetext); this.h = new Handler() { @Override public void handleMessage(Message msg) { // process incoming messages here switch (msg.what) { case 0: tView.append((String) msg.obj); break; } super.handleMessage(msg); } }; final Button button = (Button) findViewById(R.id.ButtonGo); button.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { try{ tView.setText(""); // Perform action on click URL url = new URL(eText.getText().toString()); URLConnection conn = url.openConnection(); // Get the response BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = ""; while ((line = rd.readLine()) != null) { Message lmsg; lmsg = new Message(); lmsg.obj = line; lmsg.what = 0; GetWebPage.this.h.sendMessage(lmsg); } } catch (Exception e){ } } }); }} |
這些代碼可以分解成一些常見的部分。這裡使用一些重要(必需)的匯入語句來恰當地引用 UI、資料傳遞以及應用程式中使用的與網路有關的類。所有與網路相關的代碼出現在 OnClickListener 的 OnClick 方法中。在選擇 圖 1 所示的標籤為 go! 的按鈕之後調用這些代碼。
URL 和 URLConnection 類共同提供與使用者所選的 Web 網站的串連。BufferedReader 的一個執行個體負責從 Web 網站串連中讀取傳入的資料。每讀取一行代碼,文本就被附加到一個 TextView。資料並沒有直接指定給 TextView(但是在本例中可以)。我們引入了一種設計模式,即建立一個訊息對象並將該對象發送到一個處理常式的執行個體。這是更新 UI 的一種比較可取的方法,對可能需要同時運行多個線程的應用程式而言尤其如此。
在樣本中,Android 應用程式與 HTTP Web 服務器進行通訊,比如 Apache 或 Internet Information Server(IIS 位於 Microsoft 伺服器上)。如果應用程式直接與 TCP socket 對話,那麼您將以不同的方式實現應用程式。清單 3 所示的程式碼片段展示了另一種與遠程伺服器互動的方式。這個清單被實現為一個單獨的線程。
清單 3. Daytime 客戶機
public class Requester extends Thread { Socket requestSocket; String message; StringBuilder returnStringBuffer = new StringBuilder(); Message lmsg; int ch; @Override public void run() { try { this.requestSocket = new Socket("remote.servername.com", 13); InputStreamReader isr = new InputStreamReader(this.requestSocket.getInputStream(), "ISO-8859-1"); while ((this.ch = isr.read()) != -1) { this.returnStringBuffer.append((char) this.ch); } this.message = this.returnStringBuffer.toString(); this.lmsg = new Message(); this.lmsg.obj = this.message; this.lmsg.what = 0; h.sendMessage(this.lmsg); this.requestSocket.close(); } catch (Exception ee) { Log.d("sample application", "failed to read data" + ee.getMessage()); } } } |
與前面的樣本類似,上面的代碼使用訊息和處理常式方法來將資料發送給調用者,調用者將更新 UI 並執行後續處理。與 清單 1 不同,這個例子並沒有與 HTTP 伺服器通訊,因此沒有使用 URLConnection 類。相反,使用了較低級的 Socket 類在連接埠 13 開啟與遠程伺服器的基於流的 socket 串連。連接埠 13 是典型的 “Daytime Server” 應用程式。
Daytime Server 接受傳入的 socket 串連並以文本的形式將日期和時間發送給調用 socket。一旦發送完資料,伺服器將關閉 socket。樣本也展示了 InputStreamReader 的使用和一個特定字元編碼。
發送簡訊是您需要使用 Android 完成的另一項任務。清單 4 展示了一個樣本。
清單 4. 發送一條簡訊
void sendMessage(String recipient,String myMessage) { SmsManager sm = SmsManager.getDefault(); sm.sendTextMessage("destination number",null,"hello there",null,null);} |
發送簡訊非常簡單。首先,使用靜態方法 getDefault() 擷取對 SmsManager 的引用。然後調用 sendTextMessage 方法。參數為:
-
接收者的手機號
-
包括區號。
-
服務中心電話號碼
-
使用 null 值表示您同意使用預設服務中心來處理訊息。除了非常特殊的應用程式外,幾乎所有應用程式都對這個參數使用 null 值。
-
訊息的實際內容
-
將訊息長度保持在 160 位元組以內,除非您可以接受將資料分為多個訊息發送。
-
未收到訊息 intent
-
如果訊息被發送或出現了錯誤,那麼將開始一個可選的 intent。如果不需要這類通知,那麼可以為此參數傳遞一個 null 值。(參見 參考資料 瞭解有關 intent 和 Android 基本原理的更多資訊)。
-
收到訊息 intent
-
當收到發送確認後,將開始一個可選的 Intent。如果發送通知不重要的話,那麼可以為這個參數傳遞一個 null 值。
不管是串連到 Web 頁面還是串連到定製 TCP 應用程式,Android 平台都可以立即反應並且能夠提供協助。如 清單 4 所示,發送簡訊非常簡單。通過使用可選的 intent 參數,甚至可以在訊息被發送並交付後採取操作。這是其他移動平台所不具備的強大特性。