摘 要
有些時候,對于一個企業級移動應用程序,從服務器將信息推向移動設備,并且自動激活一個已安裝的移動應用程序使其進行必要的處理是非常重要的。由短信服務(SMS)作為推信息的協議,使用push注冊機制可以讓使用Mobile Information Device PRofile 2.0的java微小版本應用程序擁有這一特征。
版權聲明:任何獲得Matrix授權的網站,轉載時請務必保留以下作者信息和鏈接
作者:Srijeeb Roy ;magic003(作者的blog:http://blog.matrix.org.cn/page/magic003)
原文:http://www.matrix.org.cn/resource/article/44/44449_Push+JAVA+Mobile.Html
要害字:Push;JAVA;mobile
移動技術日漸流行。Java微小版本,或者叫Java ME(Sun的J2ME平臺的新名字),是最流行的開發移動應用程序的技術之一。使用Java ME,我們可以在使用JVM或KVM的手持設備上運行多種無線應用程序。
Connected Limited Device Configuration (CLDC)被包含在Java ME中,它是面向那些只擁有有限資源,使用KVM的設備。同樣,Mobile Information Device Profile(MIDP)也被包含在Java ME中,這是一個為了在手機上運行應用程序的基于CLDC的profile。運行在移動設備中的應用程序模塊叫做MIDlet,是一個MIDP應用程序。一個MIDlet主要是一組有序運行的類,并且它們由運行在移動設備中的應用程序治理軟件(AMS)所控制。
MIDP的最新版本(2.0)引入了很多新的特征來幫助開發者建立健壯的企業級應用程序。其中一個比較重要的特征就是push注冊機制。在Java ME應用程序中,我們有時候需要從服務器推數據,并在設備上自動啟動一個移動應用程序,而不需要由用戶明確的啟動設備。設想一種情形,當一個針對他/她的名字的工作條款被建立時,用戶必須能自動得到通知,并且必須盡快地對此工作條款做出反應。Java ME的push注冊機制能夠很輕易地將信息推向一個Java ME應用程序,并自動啟動該程序。在這篇文章中,我將向你展示如何將push注冊機制特征添加到你的移動應用程序中。
Push注冊機制的行為可以被描述為如下三個步驟:
1.MIDlet在移動設備中注冊一個連同協議名稱的端口,假如任何信息到達指定的端口,并且使用相同的協議,那么AMS就將它轉交給MIDlet。注冊使用Java ME應用程序描述符(JAD)文件靜態的完成。程序也能使用應用程序內置的API執行動態注冊。
2. 從服務器,信息被發送到特定的移動設備,使用MIDlet應用程序注冊監聽的協議和端口。
3. 在信息被傳遞到移動設備后,AMS調用注冊了監聽此端口和協議的MIDlet應用程序。一旦信息被轉交到MIDlet,那么處理信息就是此應用程序的責任了。典型的,根據信息的信息的內容,一個應用程序會選擇打開一個屏幕,并答應用戶與服務器進行一些事務。
在這篇文章的例子中,為了從服務器推信息,我們將使用一個GSM(移動通信全球系統)調制解調器。圖1較高層次地描述了我們將在此文中實現的場景。
圖1. 從服務器push SMS消息到移動設備的高層場景
在jad文件中,每一個push注冊條目都包含如下信息:MIDlet-Push-<n>: <ConnectionURL>, <MIDletClassName>, <AllowedSender>。
MIDlet-Push-<n>:push注冊屬性名稱。MIDlet套件中可以包含多條push注冊。<n>的數值從1開始,并且對于附加的條目必須使用連續的序數。第一個發現的缺失條目將中止列表。任何剩余的條目都會被忽略。
ConnectionURL:被Connector.open()使用的連接字符串。
MIDletClassName:負責連接的MIDlet。指定的MIDlet必須使用MIDlet-<n>記錄在描述文件或jar文件的manifest中登記過。
AllowedSender:一個指定的過濾器, 它將限制哪些發送者能夠能正當啟動請求的MIDlet。
MIDP 2.0 規范定義了數據報和socket帶內連接的語法。當其他規范為其他連接類型定義push 語義時,它們必須既定義過濾器域期望的語法,又定義連接URL字符串的期望格式。
在jad文件中,一個push注冊的典型例子,使用socket連接,類似于如下:
MIDlet-Push-1: socket://:77, com.sample.Sampleapplication, *.
這個示例描述符條目在77端口處保存一個流套接字,并且答應所有的發送者。
從服務器推信息到移動設別會帶來一些問題:假如我們想發送信息到一個在指定端口注冊了監聽流套接字的特定設備,我們必須知道那個移動電話的無線網絡ip。因為在無線網絡中,很多手機不使用始終連接環境(有時候,提供商不支持設備中網絡中的靜態IP),發送信息到設備是有問題的。假如我們不知道設備的無線IP,我們將不能使用套接字連接從服務器發送信息到設備。
短信服務(SMS)在這種情況下派上了用場。使用SMS,我們指定目標設備的電話號碼;因此在這種情況下,我們不需要知道設備的IP地址。但是,使用SMS作為觸發器同樣會帶來一些問題:因為MIDP2.0規范只定義了針對數據報和套接字帶內連接的語法,而沒有針對SMS連接的,所以不保證所有支持MIDP2.0的設備都能使用SMS作為觸發器來進行push注冊。但無線消息API(WMA1.1)-一個在MIDP上能支持SMS的的可選包-現在得到很多移動設備的支持,所以有更大的可能性,SMS作為push注冊機制的觸發器將得到很多設備的支持。對于這篇文章,我使用Nokia 6600移動電話,它是支持SMS作為push注冊機制的觸發器的。
另外,從服務器發送一條SMS消息到設備不是簡單直接的,因為有很多途徑存在。SMS服務提供商提供API(或者暴露服務URL),通過這些API你能從你的服務器端應用程序發送消息到你指定的移動電話上。但這種方法依靠于SMS服務提供商和它非凡的計劃??蛇x的方式是使用一個GSM調制解調器,這樣你需要使GSM調制解調器與你的服務器端應用程序進行交互。在這篇文章中,我將使用一個開源的產品,SMSLib for Java V1.0(原名jSMSEngine),它能使GSM調制解調器與你的Java服務器端程序進行交互。
另一個在此需要注重的要點是一條簡單的SMS消息將不會激活MIDlet。我們必須發送SMS消息到MIDlet注冊監聽的特定的端口。因此被用來發送SMS消息的軟件(或SMS服務提供商)必須能夠將它發送到設備指定的端口。SMSLib for Java v1.0 支持這一功能。
當我們使用GSM調制解調器方案,我們必須了解GSM調制解調器將在內部使用SIM(訂戶識別模塊)卡來發送SMS消息。SIM卡依靠于某個移動服務提供商。因此每條SMS短信將帶來與從常規GSM移動電話發送消息同樣的花費。正相反,對于一個企業級應用(依靠于服務計劃),通過提供商的SMS網關發送批量SMS消息會被證實更節省開銷。但是,假如應用程序不需要發送大量SMS消息來出發MIDlet,那么GSM調制解調器方案會是有效的開銷,并能從移動服務提供商那里取消非凡的批量SMS服務依靠。
雖然我建議為了近期的產品使用購買一個單獨的GSM調制解調器,但是測試此行為不要求夠買。通常地,很多GSM移動電話模型帶有一個內置的GSM調制解調器。那些移動模型中的任何一個都能夠作為GSM調制解調器,來代替單獨的調制解調器。在這篇文章中,我使用另外一個Nokia 6600移動電話,而不是一個單獨的GSM調制解調器,因為Nokia 6600有一個內置的GSM調制解調器。
現在,讓我們開發一個實例程序,是我們能夠從一個Java服務器端應用程序發送一條SMS消息到一個移動電話的指定端口,并自動啟動移動設備中的一個MIDlet。
使用push注冊特征開發客戶端MIDlet
為了開發客戶端,我們使用Sun Java Wireless Toolkit(原名為J2ME Wireless Toolkit)。我使用版本2.2。這個產品是免費的,可以從Sun的網站下載。為了安裝和運行此工具包,你必須在你的機器上裝有J2SE 1.4.2_02或更新的版本。
我使用windows 2000 Professional 操作系統。
安裝Sun的工具包后,按照如下描述的步驟:
1.從開始菜單打開KToolBar:選擇程序,然后J2ME Wireless Toolkit 2.2,然后KToolbar。將會打開一個應用程序窗口,如圖2所以。
圖2. 打開KToolbar
2.現在,在剛才打開的窗口中點擊新建工程圖標。會打開一個彈出窗口;在那里你可以指定工程名稱和MIDlet類名。在工程名稱中輸入MySamplePushRegistryProject,在MIDlet類名中輸入com.sample.MySamplePushRegistry。
圖3. 新建一個工程
3.在步驟2后,會自動出現另一個彈出窗口,它將答應你設定項目的其他設置。確保你在API 選擇標簽中。在此標簽中,從目標平臺下拉菜單中選擇JTWI(假如還沒有選擇)。同樣確保CLDC 1.0單選按鈕被選中。不要鉤選Mobile Media API多選框(因為不會使用任何跟多媒體有關的API)。請參考圖4。
圖4. 設置API首選項
4.現在進入push注冊標簽。點擊添加按鈕。將會出現一個彈出窗口。在連接URL域中輸入sms://:50001,在類域中輸入com.sample.MySamplePushRegistry,在答應發送者域中輸入*。請參考圖5。
圖5 設置push注冊的屬性
5.在步驟4后,一個條目將會被加入到父窗口中。如圖6所示。
圖6. 設置push注冊的屬性(續)
6.現在進入許可標簽。單擊添加按鈕。從許可樹中選擇javax/microedtion/io/Connector/sms并單擊OK。重復相同 的步驟來添加許可javax/wireless/messaging/sms/receive 和 javax/microedtion/io/PushRegistry。
7.在步驟6后,三項許可將被添加到應用程序中。如圖7所示。
圖7. 添加許可
8.現在進入用戶定義標簽。這里,我們添加用戶定義的變量,這將包含SMS端口。從我們的程序,我們查閱此用戶定義變量來讀取SMS端口。在此標簽中,單擊添加按鈕。打開一個彈出窗口。輸入SMS-Port作為屬性名稱。選擇OK。出現了最初的彈出的窗口。輸入50001作為SMS-Port的值。如圖8所示。
圖8. 添加定制屬性SMS-Port
9.現在,在設置窗口中單擊OK。這個動作將帶回到KToolbar。
10.在步驟9后,假如你觀察由以上步驟產生的jad文件,C:/WTK22/apps/MySamplePushRegistryProject/bin/MySamplePushRegistryProject.jad(假設J2ME Wireless Toolkit 2.2被裝在目錄C:/WTK22中),你會找到在前面步驟中設定的完整配置。所有條目中最重要的一個如下:MIDlet-Push-1: sms://:50001, com.smaple.MySamplePushRegistry, *. 此條目確保你的應用程序監聽50001端口上的SMS消息。
現在,讓我們著眼于MIDlet應用程序的代碼。這里,我僅僅提供MIDlet的一部分代碼片斷。 請看資源來下載在此應用程序中使用的所有代碼。
public class MySamplePushRegistry extends MIDlet
implements CommandListener, Runnable, MessageListener {
//....
public void startApp() {
smsPort = getAppProperty("SMS-Port");
String smsConnection = "sms://:" + smsPort;
if (smsconn == null) {
try {
smsconn = (MessageConnection)
Connector.open(smsConnection);
smsconn.setMessageListener(this);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
display.setCurrent(resumeScreen);
}
public void notifyIncomingMessage(MessageConnection conn) {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
public void run() {
try {
msg = smsconn.receive();
if (msg != null) {
if (msg instanceof TextMessage) {
content.setString(((TextMessage)msg).getPayloadText());
}
display.setCurrent(content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//other methods to follow
}
新聞熱點
疑難解答