編輯:Android開發實例
簡介
本文建立在 “使用 Eclipse 開發 Android 應用程序” 一文的基礎之上,探究了 Android 的網絡功能。了解如何利用 Android 的網絡選項來實現有趣、有用的東西。Android 平台非常適合 Java™ 開發人員:他們可以使用已有的技能將網絡連接帶到一個移動或 “嵌入式” 平台中。
在本文中,了解用於 Android 應用程序的網絡選項以及基本的 Android 聯網技巧。本文研究一個真實的應用程序,它在結合使用環境監視系統時需要具備聯網功能。這類系統為什麼如此重要?原因之一是:如果您的朋友需要外出幾個星期,在他離開後,他打電話給我,讓我從他家裡找到某樣東西並郵寄給他。我來到他的家裡,發現供暖設備已經被切斷並且水管已經凍裂 — 場面非常混亂。如果備有一個溫度監控系統,那麼就可以避免出現這類事故。本文將探查 Android 在這類監控系統中扮演的角色。
Android 聯網功能
Android 基於 Linux® 內核,包含一組優秀的聯網功能。如果尚未安裝 Android SDK,那麼需要 下載 它才能實踐本文的示例。
表 1 展示了 Android SDK 中一些與網絡有關的包。
表 1. Android SDK 網絡包
包描述java.net提供與聯網有關的類,包括流和數據包(datagram)sockets、Internet 協議和常見 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 interface
import 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 connectivity
import 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 參數,甚至可以在消息被發送並交付後采取操作。這是其他移動平台所不具備的強大特性。
下一節將快速浏覽一個真實的應用程序設計。
環境監控系統
在這個場景中,我們假設您是企業所在的若干辦公場所的資產管理員。管理資產與管理數據中心沒有太大的差別 — 一般情況下都很枯燥,只有出現緊急的情況下工作才會比較有意思。幾天前,一台使用了 10 年的熱水器突然漏水,滲到一個裝滿老式 PC 和培訓手冊的存儲櫃,您必須檢查一下清理情況。幸運的是,您當時沒有外出。如果您在旅途中的話,那麼情形將非常糟糕。此類災難性事故促使我們考慮使用 Android 來幫助監視資產的維護情況。圖 2 展示了此類系統的一個高級方框圖。
圖 2. 監控系統的高級方框圖
此架構是一種比較傳統的方法,使用一個微控制器與一些簡單場景進行交互以收集數據。數據隨後通過一個串行通信協議(比如 RS232 或 RS485)發送到控制器。控制器可以是一個 PC 或類似的機器。隨後可以穿過防火牆通過 Internet 訪問數據。Android 電話(比如 TMobile G1)之間使用的協議可以是 HTTP 或私有協定。
在控制器和配備 Android 的設備之間發送的數據將是表示以下內容的基本數據:
出現漏水
當前溫度
消耗的功率
可能包含一些通用的類似數據和數字值
為什麼需要關注消耗的功率?一個可能的原因就是有些人忘記關閉機器,因此電費單上的數字會一直增長。第二個理由有些復雜:假設您有一台非常大的冰箱,並且電源可能已被關閉。那麼情況就復雜了,而且處理起來也需要很高的代價。或者,空調設備的斷路器出現故障,因此機房無法保持恆定的溫度。
基本的設計看上去是可行的。如果使用的是 Android,那麼可以使用任何移動平台來替換 圖 2 中的 Android。但如果使用配備了 Android 的設備替換微控制器,那應該怎麼做呢?下一節將討論對這個應用程序的擴展以及通過使用 Android 而啟用的特性。
擴展應用程序
本文的第一個架構以一個微控制器為中心。微控制器可分為不同的外形和大小,從 Microchip 的 6 pin “10F” 到添加了外圍設備、pin 和代碼空間的 32 位大型微控制器。如果使用 Android 取代傳統的微控制器放到設備中,會怎麼樣?對於某些應用程序而言,在成本方面是不可取的,但是根據圖 3 的判斷,這種方法也是可行的。
圖 3. 在設備中使用 Android 的可能架構
使用嵌入式的方式部署 Android 為您提供了更加豐富的編程環境。您可以和以前一樣繼續監視濕度、溫度和功率消耗特征,同時還可以觀察到記錄音頻、視頻和振動。您將擁有一個微報警、訪問控制系統,以及一個環節監控工具。由於 Android 已經可以實現聯網,您不需要使用控制器 PC 就可以實現監控並與網絡直接對話。
這種方法還為現場更新軟件提供了額外的好處。假設您希望為監控軟件添加新的特性(或修復 bug)。如果使用傳統的微控制器方法,那麼任務執行起來將十分繁瑣並且代價昂貴,甚至根本不可能實現。而對於 Android 而言,您可以獲得更整潔的部署模型並擁有更好的靈活性。
Android 如今主要運行在移動手機中,但是它已經被移植到 NetBooks 和其他平台上。希望本文為您提供了一些好的思考內容。我現在該去運行我的系統了。您永遠也不會知道下一次熱水器漏水會在什麼時候發生。
結束語
在本文中,我們大體介紹了 Android 的聯網功能。您了解了一些自己可以創建的樣例應用程序,包括與 Web 服務器交互和發送文本消息。您看到了如何將 Android 連接到一個真實的環境監控系統。通過代碼示例,您了解到應該在什麼時候將 Android 擴展到一些特殊應用程序中,比如嵌入式控制器。
請繼續關注我的下一篇文章,它將介紹如何使用基於 Android 的電話構建一個嬰兒監控系統。
本文示例源代碼或素材下載
編緝推薦閱讀以下文章
在手機衛士之前的版本升級的對話框中: 有的用戶暫時不想更新,沒有點擊“稍後再說”,而是選擇點擊回退按鍵,那麼這時候的邏輯應
在Android中使用ImageView顯示圖片的時候發現圖片顯示不正,方向偏了或者倒過來了。 解決這個問題很自然想到的分兩步走: 1、自動識別圖像方向,計算旋轉
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
本文實例講述了Android實現捕獲TextView超鏈接的方法。分享給大家供大家參考,具體如下: 這裡分享一篇捕獲TextView超鏈接的文章,希望對大家有所幫