文章目錄
- OPhone平台開發, 2009-12-01 14:28:28
OPhone平台開發, 2009-12-01 14:28:28 標籤 : 網路連接 應用程式 資料連線
本文主要介紹了OPhone應用程式如何?網路連接的管理。附件提供一段用於開發參考和樣本的程式碼程式庫,封裝了常用的網路請求和資料接受方法,使得普通網路應用程式的開發大大單化,便於網路程式開發人員可以專註於應用邏輯。附件同時提供了一段可以啟動並執行應用程式作為網路開發的範例程式碼。
本文所講述的網路開發方法通用於目前已經發布的兩個版本的OPhone手機,即OPhone
1.0和OPhone 1.5。
OPhone網路連接的存取點管理
OPhone
平台實現了多個應用程式對分組資料複用的功能,不同的應用可以根據自身需要,開啟不同的網路連接,通過這種方式我們可以在不同的OPhone應用中同時進行諸如瀏覽網頁、接受多媒體訊息、發送郵件這樣的網路任務。可以通過OPhone手機的操作來配置網路存取點。從首屏的表徵圖上選擇“配置”“資料連線”來進行配置,配置作為系統資訊被儲存,各個應用程式可以查詢到這些存取點的配置詳情,並選擇使用一個存取點開始網路連接。
在OPhone 1.0和OPhone 1.5下這兩個配置有一些不同。
OPhone 1.0的配置視窗如下。分別是網路存取點的選擇視窗,某個網路存取點的詳細資料編輯。
圖1: OPhone 1.0存取點列表
圖2: OPhone 1.0存取點編輯
OPhone 1.5的配置視窗如下。他比OPhone
1.0多了第一層次的存取點類型列表,每個類型下可以配置多個存取點,某個類型列表下的存取點可以視為一組同樣類型的存取點。這也決定了OPhone
1.5在網路存取點的管理和串連使用上有一些不同。具體見下面的進一步說明。
圖3: OPhone 1.5 存取點分組 圖4: OPhone
1.5存取點列表 圖5: OPhone 1.5存取點配置
OPhone網路連接的過程
描述了OPhone上進行一次網路資料請求的完整處理流程。
過程分為網路連接部分和資料請求接收部分。資料請求部分可以使用Java標準的網路請求,也可以使用系統提供的Apache
HttpClient介面,這些與通用的Java網路開發並沒有太大差異。詳細可以參考OPhone SDN上王衛同學的一篇文章《如何在OPhone平台編寫網路應用》。
網路連接部分用於建立裝置上的網路資料通道,比如GPRS環境下就是建立分組資料(PDP)串連。他是區別於普通Java網路開發的一個最大差別,即在PC啟動並執行模擬器上可以沒有“網路連接部分”,但是如果要想讓你的應用程式在實際的OPhone手機上進行網路資料的請求,則必須瞭解該步相關知識。
在一個移動終端裝置上可能存在多個資料通道,比如可能同時有GPRS,WIFI,USB虛擬網路介面,藍芽虛擬網路介面等多個資料通道,因此手機上可能有多個存取點可供網路應用程式選擇。應用程式可以查詢到這些存取點的配置,並且選擇一個進行網路連接。
OPhone系統上,在應用程式啟動並執行不同時間,可以串連/使用多個不同的存取點,但是在進行網路連接的某一時刻,只允許啟用一個網路連接的資料通道。如果要切換到使用其他網路存取點,必須重新發起一個新的網路連接。
必須注意的是,OPhone 1.0和OPhone
1.5上發起網路連接的方法並不相同。這也一定程度上引起程式移植的問題,增加了網路應用開發的複雜性和工作量。
OPhone
1.5使用android.net.ConnectivityManager類中的startUsingNetworkFeature()方法來啟用網路連接,網路狀態的通知通過一個Intent訊息EVENT_DATA_STATE_CHANGED來傳遞和接受。OPhone
1.0使用android.net.DataConnection類中的openConnection()方法來啟用網路連接,通過setNetworkStatusListener()方法來設定網路狀態的接收介面。
OPhone 1.5比OPhone 1.0的存取點配置上增加了存取點類型(APN
type)的概念,同一種類型的存取點被歸類在一起成為一個存取點的分組。OPhone
1.5發起網路連接時所傳遞的參數是這個存取點類型,串連過程中會嘗試串連該類型存取點分組下所有的存取點,直到網路連接成功。如“圖6: OPhone
1.5存取點列表”所示的網路設定,串連時如果第一個APN串連失敗,在串連操作結束前會嘗試使用第二個APN。而OPhone
1.0所傳遞的串連參數是存取點ID,一個ID僅僅對應一個存取點配置項。
目前在中國移動的GSM網路下常見的網路存取點有為GPRS的不同存取點cmwap,
cmnet,
cmmail等而設定的不同存取點配置項。一般情況下各個存取點都可能成功發起網路連接,但是根據移動網路的運營情況,不同的資料業務在不同的存取點上可能有計費上的差異。
當然還有一些其他的細微差別。比如最常見的cmwap,
cmnet兩個存取點,除了計費差異外,使用cmwap存取點的串連,如果需要讓手機串連到互連網上的伺服器,必須使用HTTP代理,也就是使用cmwap存取點後,應用程式將只能發起標準的HTTP請求。中國移動全網配置的Proxy 伺服器地址是10.0.0.172,連接埠80。另外,如果使用中國移動的cmwap存取點,你必須面對這樣一個問題,一般情況下,當網路連接第一次建立後,HTTP請求發出後第一個內容並不是真實的你需要的內容,而是代替以一個WML編碼的計費提醒頁面。解決辦法是您可能需要分析一下返回的內容,如果不正確,那麼你需要重新發起一次網路請求來擷取真實的網路資料(如果你開發的是一個瀏覽器,你也可以直接顯示收到的WML頁面,讓使用者收到計費提醒,點擊頁面中的連結可以跳過計費提醒)。
OPhone應用程式的網路開發
針對以上描述的OPhone
1.5,OPhone
1.0的各自特點和差異,這裡嘗試使用一個共同的介面封裝來簡化網路應用在不同版本間的移植過程。並且考慮最簡單化這個介面的設計,使的網路調用變得更方便。
1. 首先拷貝需要的兩個協助庫檔案到開發中的測試下面下:
OPhone
1.5下是:dataconnection_helper_v15.jar和dataconnection_helper_httpget.jar;
OPhone
1.0下是dataconnection_helper_v10.jar和dataconnection_helper_httpget.jar。
2. 配置OPhone項目,添加這兩個庫到開發中的Eclipse項目下。如所示:
首先,選擇左側 “Java build Path”,然後選擇右側Tab頁的“Libraries”,然後點擊按鈕“Add External
JARs...”。選擇拷貝過來的jar檔案,然後確認是否添加成功。
繼續配置頁,選擇上面的“Order and
Export”,選中新添加的兩個Jar檔案,允許項目編譯時間同時匯出這兩個jar庫的內容。
3. 在項目代碼中使用Helper庫提供的程式碼程式庫,用於樣本的DataConnectionDemo程式如下:
view plaincopy to clipboardprint?
- // 下面是對應OPhone 1.5引用的庫名稱,
- // 對應於OPhone 1.0請使用oms.dataconnection.helper.v10.*
- import oms.dataconnection.helper.v15.*;
- import oms.dataconnection.helper.httpget.DataHttp;
-
- public class DataConnectionDemo extends Activity {
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- // 初始化存取點查詢協助類的對象
- mQueryApList = new QueryApList(this);
-
- // 擷取各個存取點的標題
- String[] apListTitle = mQueryApList.getApTitle();
-
- // 產生網路連接協助的對象
- mConnectHelper = new ConnectByAp(this);
-
- // 擷取指定序號位置存取點的ID
- final int apId = mQueryApList.getApId(position);
-
- // 建立網路連接的線程
- Runnable runnable = new Runnable() {
- public void run() {
- // 擷取存取點配置的Proxy 伺服器資訊
- String proxyHost = mQueryApList.getApProxy(position);
- int proxyPort = mQueryApList.getApProxyPort(position);
-
- // 串連並設定當前使用的網路介入點
- // 函數一直阻滯,直到網路連接結束,傳回值表示串連的結果是成功還是失敗
- boolean result = mConnectHelper.connect(apId, 10000);
- if (!result)
- return;
-
- // 至此,網路連接成功,下面可以開始Java通用的網路資料的請求和接收
-
- // 但這裡使用了一個自己封裝過的HTTP資料請求類DataHttp來簡化資料接收
- // DataHttp會主動請求gzip或deflate壓縮過的HTTP資料,並且自動解壓接收到的壓縮資料,
- // 並且嘗試支援從HTTP HEADER中讀取內容的字元編碼資訊。
- // 首先,產生網路請求
- DataHttp dataHttp = new DataHttp(requestURL
- , "*/*", "OPhone 1.5 ", proxyHost, proxyPort)
- {
- // 自訂新資料接受到的網路通知,用於資料轉送狀態的擷取
- @Override
- protected void onDataReceived(int len_read, int size, int total) {
- // show data receiving status
- printLog(title, String.format("Received data: %d(%d/%d)"
- , len_read, size, total));
- super.onDataReceived(len_read, size, total);
- }
- };
-
- // 然後,發送請求網路,並接收返回資料
- printLog(title, String.format("Start getting data through: %s, %s, %s:%d"
- , apType, requestURL, proxyHost, proxyPort));
-
- try {
- dataHttp.connect();
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- // 讀取返回資料
- // 調用下面的方法可以實現壓縮編碼的解壓和字元編碼的自動識別
- String page = dataHttp.getResponseString();
- if (page == null)
- printLog(title, "Failed receiving data from: " + requestURL);
- else {
- String strOut = (page.length() <= 200)
- ? page
- : page.substring(0, 195) + " ....";
- printLog(title, String.format("Finished receiving data(%dB) "
- ", page length in char:%d/n%s/n============="
- , dataHttp.body.length, page.length(), strOut));
- }
- } // END of run()
- }; // END defining class Runnable
-
- // 啟動網路連接和資料讀取的線程
- new Thread(runnable).start();
- } // END onCreate()
- } // END defining class DataConnectionDemo
// 下面是對應OPhone 1.5引用的庫名稱, // 對應於OPhone 1.0請使用oms.dataconnection.helper.v10.* import oms.dataconnection.helper.v15.*; import oms.dataconnection.helper.httpget.DataHttp; public class DataConnectionDemo extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 初始化存取點查詢協助類的對象 mQueryApList = new QueryApList(this); // 擷取各個存取點的標題 String[] apListTitle = mQueryApList.getApTitle(); // 產生網路連接協助的對象 mConnectHelper = new ConnectByAp(this); // 擷取指定序號位置存取點的ID final int apId = mQueryApList.getApId(position); // 建立網路連接的線程 Runnable runnable = new Runnable() { public void run() { // 擷取存取點配置的Proxy 伺服器資訊 String proxyHost = mQueryApList.getApProxy(position); int proxyPort = mQueryApList.getApProxyPort(position); // 串連並設定當前使用的網路介入點 // 函數一直阻滯,直到網路連接結束,傳回值表示串連的結果是成功還是失敗 boolean result = mConnectHelper.connect(apId, 10000); if (!result) return; // 至此,網路連接成功,下面可以開始Java通用的網路資料的請求和接收 // 但這裡使用了一個自己封裝過的HTTP資料請求類DataHttp來簡化資料接收 // DataHttp會主動請求gzip或deflate壓縮過的HTTP資料,並且自動解壓接收到的壓縮資料, // 並且嘗試支援從HTTP HEADER中讀取內容的字元編碼資訊。 // 首先,產生網路請求 DataHttp dataHttp = new DataHttp(requestURL , "*/*", "OPhone 1.5 ", proxyHost, proxyPort) { // 自訂新資料接受到的網路通知,用於資料轉送狀態的擷取 @Override protected void onDataReceived(int len_read, int size, int total) { // show data receiving status printLog(title, String.format("Received data: %d(%d/%d)" , len_read, size, total)); super.onDataReceived(len_read, size, total); } }; // 然後,發送請求網路,並接收返回資料 printLog(title, String.format("Start getting data through: %s, %s, %s:%d" , apType, requestURL, proxyHost, proxyPort)); try { dataHttp.connect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 讀取返回資料 // 調用下面的方法可以實現壓縮編碼的解壓和字元編碼的自動識別 String page = dataHttp.getResponseString(); if (page == null) printLog(title, "Failed receiving data from: " + requestURL); else { String strOut = (page.length() <= 200) ? page : page.substring(0, 195) + " ...."; printLog(title, String.format("Finished receiving data(%dB) " ", page length in char:%d/n%s/n=============" , dataHttp.body.length, page.length(), strOut)); } } // END of run() }; // END defining class Runnable // 啟動網路連接和資料讀取的線程 new Thread(runnable).start(); } // END onCreate() } // END defining class DataConnectionDemo
附件參考庫的使用方法
見附件Javadoc文檔。
附件範例程式碼的運行效果
顯示了樣本程式啟動並執行效果。網路連接使用了cmnet存取點,沒有設定HTTP代理。擷取到資料大小是9516位元組,解壓後內容包含字元30649個。網路資料經過6次讀取和等待後完成,由此也可以計算出網路資料的傳輸速度。
顯示了第一次串連cmwap存取點後得到計費提醒頁的內容。使用了代理10.0.0.172:80,此時擷取到的內容長度是488
Byte,內容為WML頁面。
重新使用cmwap存取點擷取資料後,內容成功擷取到,網路接收的檔案是31195位元組。從Demo程式運行時刻的效果可以發現,Demo運行時刻cmwap存取點配置的HTTPProxy 伺服器不支援HTTP內容的壓縮編碼傳輸
,因此傳輸接收的資料量是未傳輸壓縮編碼前的原網頁大小。
原始碼:
bin.zip
DataConnectionDemo.tgz
document-DataConnectionHelper.zip