BES推送應(yīng)用實(shí)例演示與分析
本文通過一個(gè)實(shí)際的應(yīng)用案例ECL(Emergency Contact List),來介紹經(jīng)典的BlackBerry通過BES(BlackBerry Enterprise Server)數(shù)據(jù)推送的功能,包括了服務(wù)器端和手機(jī)端的源代碼。
主要演示的技術(shù)點(diǎn)包括:
◆服務(wù)端Java程序如何通過調(diào)用BES服務(wù)器推送功能向手機(jī)推送數(shù)據(jù)
◆手機(jī)端Java應(yīng)用如何偵聽并接收數(shù)據(jù)
◆手機(jī)端Java應(yīng)用如何變換圖標(biāo),以提醒用戶有新的數(shù)據(jù)到達(dá)該手機(jī)該代碼實(shí)例可以運(yùn)行在模擬器環(huán)境(MDS模擬器+BlackBerry手機(jī)模擬器),也可以運(yùn)行在真實(shí)的(BES+BlackBerry真機(jī))環(huán)境。本文主要介紹了在模擬器環(huán)境下代碼運(yùn)行的情況。
注:為方便開發(fā)人員學(xué)習(xí)和使用BlackBerrypush技術(shù),黑莓官方網(wǎng)站上提供了一個(gè)樣例程序Emergency Contact List(簡(jiǎn)稱ECL),包括Java/ASP.NET/Domino三種語言版本,支持瀏覽器Push和Java應(yīng)用程序Push。Java版本的程序源代碼和運(yùn)行腳本在網(wǎng)頁www.blackberry.com/go/ecl上面上可以免費(fèi)下載。在本文中,我們將分析Java版本ECL樣例程序。
各語言版本ECL程序的比較:
Database ( s ) Utilized( 數(shù)據(jù)來源 )
|
Server - Side
Technology
|
|
BlackBerry Client
Implementation
|
|
ECL Version
|
Push Inter face
|
|||
|
|
|||
Java ECL
|
Microsoft Excel
|
Java EE
|
命令行
|
Java Application
Browser Application
|
ASP .NET ECL
|
Microsoft Excel
Microsoft Access
Microsof t SQL Server
|
.NET
|
命令行
GUI Windows®
|
Java Application
Browser Application
|
|
|
|
S e rvic e
P ush Acce ss
P rotoc ol (PAP )
|
|
Domino® EC L
|
I BM L otus Note s
|
J a va EE
|
命令行
L otus Note s 界面
|
J a va Applica ti on
B row s e r A ppli ca ti on
|
模擬業(yè)務(wù)場(chǎng)景:
ECL(EmergencyContactList)實(shí)例模擬了以下業(yè)務(wù)場(chǎng)景:
1.用戶BlackBerry手機(jī)端安裝ECLJ2ME客戶端應(yīng)用
2.服務(wù)器端為一個(gè)Excel數(shù)據(jù)表(代表數(shù)據(jù)庫)
3.當(dāng)在Excel表中加入新的數(shù)據(jù)或者修改了數(shù)據(jù)后,服務(wù)器端可以發(fā)起一個(gè)推送,將更新后的Excel表內(nèi)容全部推送到BlackBerry手機(jī)
4.BlackBerry手機(jī)用戶注意到手機(jī)端應(yīng)用圖標(biāo)發(fā)生變化,表明有新數(shù)據(jù)到達(dá)手機(jī),即可在手機(jī)上打開應(yīng)用,查看數(shù)據(jù)
***部分演示環(huán)境配置
這里描述了在一臺(tái)電腦上,如何使用模擬器演示該代碼實(shí)例。需要安裝的軟件包括:
◆BlackBerry Emailand MDS Services Simulators 4.1.4
◆BlackBerry Smartphone Simulators 5.0.0(也可以使用4.5,4.6,4.7等版本,但需要通
過Eclipse修改載入不同SDK,詳細(xì)方法見附錄)
◆Eclipse SDK 3.5.1(可選,V3.4也可以,用于研究代碼用)
◆BlackBerry JDE Plug-infor Eclipse Version:1.1.1.2009 11111641-15
安裝以上軟件在一臺(tái)電腦上,一般采用缺省目錄安裝即可。
解壓縮ECL_Java.zip到c:\ECL_Java目錄下,下面解釋一下主要文件夾內(nèi)容和其作用:
◆Readme.txt:使用說明文檔
◆目錄src:代碼源文件目錄,包括手機(jī)端代碼和服務(wù)器端
◆目錄bin:可執(zhí)行文件目錄,用于實(shí)際演示用
第二部分演示過程
1.啟動(dòng)BlackBerry Emailand MDS Services Simulators 4.1.4

2.啟動(dòng)BlackBerry Smartphone Simulators 5.0.0


3.安裝ECLSample.cod文件到手機(jī)模擬器
模擬器:File=>LoadJavaProgram=>選擇5.0版本的ECLSample.cod

4.在DOS命令行下輸入命令:
C:\ECL_Java\bin\Server>runcatchersimulatoremai.txtxyzlist.xls

運(yùn)行后顯示successful push表示推送成功。
5.手機(jī)端應(yīng)用圖標(biāo)發(fā)生變化,然后進(jìn)入應(yīng)用查看信息

6.修改Excel表內(nèi)容,
到C:\ECL_Java\bin\Server目錄下修改xyzlist.xls文件,如把內(nèi)容修改一下,例如將”John Peng”改成“Petter Liang”
7.在DOS命令行下輸入命令:
C:\ECL_Java\bin\Server>runcatchersimulatoremai.txtxyzlist.xls

8.手機(jī)端應(yīng)用圖標(biāo)發(fā)生變化,然后查看更新后的信息

#p#
第三部分手機(jī)端代碼導(dǎo)入Eclipse
1.打開Eclipse,

2.File–Import,選擇General=>Existing Projects to Workspace





第四部分核心代碼分析
BlackBerryPush架構(gòu)
在分析樣例代碼之前,首先讓我們從整體上了解BlackBerryPush架構(gòu)。
更加詳細(xì)的BlackBerry推送機(jī)制的分析和介紹,請(qǐng)參考黑莓官方網(wǎng)站,以及參考資料“BES服務(wù)器推送機(jī)制分析”。

從示意圖中,我們可以看到,在BlackBerry應(yīng)用平臺(tái)上的數(shù)據(jù)推送從整體上可以分為六步,按時(shí)間順序分別為:
1.應(yīng)用服務(wù)器向MDS/BES服務(wù)器發(fā)送推送請(qǐng)求,該請(qǐng)求為HTTPPOST請(qǐng)求。
2/3:MDS/BES服務(wù)器做必要的權(quán)限和數(shù)據(jù)監(jiān)測(cè),告知應(yīng)用服務(wù)器推送請(qǐng)求是否被接受并將被執(zhí)行。
4:MDS/BES服務(wù)器通過BlackBerryInfrastructure和無線網(wǎng)絡(luò)把數(shù)據(jù)推送到手持設(shè)備端。
5:手持設(shè)備收到數(shù)據(jù)后,向MDS/BES服務(wù)器反饋。
6:MDS/BES服務(wù)器告知應(yīng)用服務(wù)器其推送數(shù)據(jù)是否送達(dá)手持設(shè)備。
ECL系統(tǒng)架構(gòu)
從BlackBerryPush系統(tǒng)架構(gòu)上看,從服務(wù)器端Push數(shù)據(jù)到手機(jī)端,要經(jīng)過多個(gè)服務(wù)器和網(wǎng)絡(luò)甚至無線基站,整個(gè)流程相當(dāng)復(fù)雜。幸運(yùn)的是,從應(yīng)用開發(fā)的角度,程序員可以不考慮Push的復(fù)雜底層實(shí)現(xiàn),而只需簡(jiǎn)單地發(fā)送Push請(qǐng)求并監(jiān)聽Push請(qǐng)求的處理狀態(tài),客戶端監(jiān)聽并接受推送數(shù)據(jù)即可:
1.服務(wù)器程序向MDS/BES服務(wù)器發(fā)送推送請(qǐng)求,所發(fā)送的請(qǐng)求為HTTPPOST
請(qǐng)求。
2.手持設(shè)備上的Java客戶端程序接收push過來的數(shù)據(jù),做出燈光閃爍/振鈴等提示,甚至修改桌面圖標(biāo)提示用戶,用戶打開程序界面查看數(shù)據(jù)。
3.服務(wù)器程序從MDS/BES服務(wù)器獲得推送請(qǐng)求是否完成的狀態(tài)信息。
Java版本ECL服務(wù)器代碼分析
核心代碼說明,Java類列表
Java版本ECL服務(wù)器程序是一個(gè)命令行程序,根據(jù)命令行參數(shù)把指定excel表格中的聯(lián)系人列表contactlist數(shù)據(jù)推送給指定的手機(jī)上。
1.主程序:是eclTimed Update.java,這是一個(gè)包含main()方法的控制程序,根據(jù)不同參數(shù)調(diào)用兩個(gè)Pusher類做Browser Push和Customize Push。
2.核心Push代碼:由Browser Channel Pusher.java/Custom App Pusher.java/Pusher.java三個(gè)類構(gòu)成。
3.服務(wù)器配置信息:MdsProperties.java等四個(gè)類用于讀取配置文本文件,讓ECL服務(wù)器主程序獲得MDS/BES服務(wù)器IP地址端口號(hào)等信息。
4.數(shù)據(jù)訪問:DataReader.java通過JDBC-ODBC接口讀取Excel表單數(shù)據(jù)。
ECL服務(wù)器程序各個(gè)Java類的功能說明列表如下:
根據(jù)參數(shù)構(gòu)造Pusher類(Browser Channel Pusher或者Custom App Pusher)作為整個(gè)服務(wù)器端推送數(shù)據(jù)程序的入口,eclTimed Update.java是一個(gè)標(biāo)準(zhǔn)的J2SE程序。
在main()方法中首先分析***個(gè)參數(shù)。如果參數(shù)值是channel,則構(gòu)造pusher為Browser Channel Pusher類;如果參數(shù)值是catcher,則構(gòu)造pusher為Custom App Pusher類。
- public static void main(String[] args)
- …
- // Process command-line arguments
- if (args. length >= 1) {
- if (args[0].equalsIgnoreCase( "channel" )) {
- // Construct a pusher that sends to a browser channel.
- pusher = new BrowserChannelPusher (); //Browser push 也是一個(gè)很有 趣的話 題
- } else if (args[0].equalsIgnoreCase( "catcher" )) {
- // Construct a pusher that sends to a custom catcher.
- pusher = new CustomAppPusher ();
- }
- }
根據(jù)參數(shù)從文本文件中讀取BlackBerry手機(jī)PIN碼列表
例如從simulatoremail.txt文件中讀取到的PIN碼為黑莓模擬器的PIN碼2100000a。
提示:BlackBerryMDS/BES服務(wù)器支持以手機(jī)PIN碼和email地址識(shí)別要推送的目標(biāo)手機(jī)。在ECL樣例程序中是使用手機(jī)PIN碼。
- if (args.length >= 2) {
- emailListFile = args[1];
- }
- … …
- // Get the list of emails to push to.
- List recipientEmails = getRecipients(emailListFile);
根據(jù)參數(shù)從excel表格文件中讀取ECL聯(lián)系人列表
在這里調(diào)用Data Reader類訪問Excel表,讀取每個(gè)組和每個(gè)人的聯(lián)系方式,并通過pusher.add Contact(dataFields);方法把數(shù)據(jù)傳遞給pusher,***調(diào)用pusher.finished Construction();方法告訴pusher數(shù)據(jù)全部讀取完畢。Pusher會(huì)把所有聯(lián)系人方式構(gòu)造成一個(gè)xml字符串保存起來以備下一步調(diào)用pusher.send To Hand held(curRecipient);進(jìn)行發(fā)送。
- // Fetch the group names from the spreadsheet.
- Vector groupDescription = dataReader.getGroupList();
- // Assemble the data of all contacts (from all groups) that we
- // will push to handhelds.
- for ( int i = 0; i < groupDescription.size(); i++) {
- // Define the current group.
- pusher.beginGroup((String)groupDescription.elementAt(i));
- // Add all its members.
- Vector groupContactList = dataReader.getContactList(
- (String)groupDescription.elementAt(i));
- for ( int j = 0; j < groupContactList.size(); j++) {
- String[] dataFields = dataReader.getContactData(
- (String)groupContactList.elementAt(j));
- pusher.addContact(dataFields);
- }
- }
- // Indicate that we're done building the contacts list. After,
- // the pusher is ready to send the message multiple times.
- pusher.finishedConstruction();
調(diào)用pusher.send To Handheld()推送數(shù)據(jù)到每一部黑莓手機(jī)上面做一個(gè)For循環(huán),多次調(diào)用pusher.send To Handheld(cur Recipient)通過BES/MDS服務(wù)器把數(shù)據(jù)發(fā)送到各個(gè)手機(jī)上面。
- // Push the message we just built to all recipients.
- for ( int i = 0; i < recipientEmails.size(); i++) {
- String curRecipient = (String)recipientEmails.get(i);
- try {
- System. out .print( "Contacting BES for " + curRecipient);
- pusher.sendToHandheld(curRecipient); System. out .println( " - successful push." );
- } catch (Pusher.MDSConnectionException ex) {
- // Unable to connect to MDS. The condition is unlikely
- // to be temporary so abort.
- System. out .println( " - " + ex.getMessage());
- Pusher.java代碼分析
- break ;
- } catch (Pusher.MDSResponseException ex) {
- // Connected OK but MDS responded with error. Log it and
- // try the next email.
- System. out .println( " - MDS responded with "
- + ex.getMessage());
- } catch (Exception ex) {
- // Unexpected error. Log a full stack trace and try the
- // next email.
- System. out .println( " - unexpected error:" );
- ex.printStackTrace();
- }
- }
Pusher.java代碼實(shí)際上包括兩部分內(nèi)容,一部分是準(zhǔn)備要推送的數(shù)據(jù),一部分是真正的推送操作。
Begin Group(),add Contact(),finished Construction()三個(gè)方法是用來準(zhǔn)備要推送的數(shù)據(jù)。主邏輯程序多次調(diào)用這三個(gè)方法告訴Pusher有哪些聯(lián)系人數(shù)據(jù)要推送。Pusher會(huì)把這些數(shù)據(jù)拼裝成一個(gè)html或者是一個(gè)大文本,并最終推送給手機(jī)瀏覽器或者手機(jī)客戶端程序。writeTo(OutputStream)方法用來把前面三個(gè)方法構(gòu)造出來的數(shù)據(jù)寫到輸出流中。
注意:以上4個(gè)方法和push無關(guān),更好的做法應(yīng)該是把他們分離出去做一個(gè)獨(dú)立的數(shù)據(jù)構(gòu)造類。
Pusher.java代碼的核心方法是send To Handheld(Stringrecipient Email)。該方法構(gòu)造標(biāo)準(zhǔn)的http POST請(qǐng)求給MDS/BES服務(wù)器,通過參數(shù)DESTINATION指定要把數(shù)據(jù)push給哪些人(參數(shù)值可以是email地址或者是手機(jī)PIN碼),參數(shù)PORT告知要把數(shù)據(jù)推送到手機(jī)上面哪個(gè)端口(例子代碼中是端口911)。
- /**
- * Pushes the already - constructed message to the indicated recipient. May
- * be used many times, but only in the "sending" state.
- */
- public void sendToHandheld(String recipientEmail)
- throws IOException, MDSConnectionException, MDSResponseException
- {
- HttpURLConnection conn = null ;
- OutputStream out = null ;
- try {
- // Build the URL to define our connection to the BES.
- URL url = new URL( "http" , _props .getBesHostName(),
- _props .getBesPushPort(),
- "/push?DESTINATION=" + recipientEmail
- + "&PORT=" + getDevicePort()
- + "&REQUESTURI=/" );
- conn = (HttpURLConnection)url.openConnection();
- conn.setDoOutput(true ); //to post data
- conn.setRequestMethod("POST" );
- establishRequestHeaders(conn);
- //write the data to the http connection
- out = conn.getOutputStream();
- writeTo(out);
- // Check the MDS's response so that we report an error if the push
- // was unsuccessful.
- int responseCode = conn.getResponseCode();
- if (responseCode != HttpURLConnection. HTTP_OK ) {
- String serverMessage = conn.getResponseMessage();
- throw new MDSResponseException(
- "HTTP-" + responseCode + ": " + serverMessage);
- }
核心代碼說明,Java類列表
客戶端代碼由三個(gè)Java類,兩個(gè)圖標(biāo)文件,BlackBerry應(yīng)用描述文件構(gòu)成。

ECL客戶端程序三個(gè)Java類的功能說明列表如下:
ECL客戶端程序的兩個(gè)入口點(diǎn)(AlternateEntryPoints)
ECL客戶端程序是如何自動(dòng)啟動(dòng)監(jiān)聽程序的?又是如何區(qū)分點(diǎn)擊icon啟動(dòng)GUI界面程序的呢?答案在應(yīng)用描述文件BlackBerry_App_Descriptor.xml和主程序的main()方法上。
打開BlackBerry_App_Descriptor.xml,在Application標(biāo)簽欄目里面,你會(huì)看到Auto-runonstartup被選中。這樣,ECLSample程序會(huì)在手機(jī)啟動(dòng)過程中自動(dòng)地啟動(dòng),產(chǎn)生一個(gè)后臺(tái)Java進(jìn)程監(jiān)聽Push數(shù)據(jù)。
在Alternate Entry Points欄目中,設(shè)置了一個(gè)參數(shù)Applicationargument為gui,并單獨(dú)設(shè)置了程序Title和Icon,因此程序安裝后在“下載”目錄里面出現(xiàn)一個(gè)應(yīng)用圖標(biāo)。點(diǎn)擊圖標(biāo)將產(chǎn)生一個(gè)前臺(tái)GUI進(jìn)程來讀取并顯示Push過來的數(shù)據(jù)。

#p#
ECL Application客戶端主程序說明
在ECL Application的main()方法中,如果沒有任何參數(shù)傳進(jìn)來,那么就是說程序是在手機(jī)啟動(dòng)的時(shí)候被初始化調(diào)用的,啟動(dòng)Pushed Data Listener線程在后臺(tái)運(yùn)行,監(jiān)聽push來的數(shù)據(jù)。
- class ECLApplication extends UiApplication {
- private MenuItem _copyItem ;
- /******************************************************************************************
- * main() - controls the startup of the application...thread will start i n the background
- * and the GUI starts when user clicks from main menu
- ******************************************************************************************/
- public static void main(String[] args) {
- if ( args != null && args. length > 0) { //entry point 是有參數(shù) 的,那么 打開 GUI 窗口
- ECLApplication theApp = new ECLApplication();
- theApp.enterEventDispatcher();
- }
- else { //entry point 是沒有參 數(shù)的, 那么啟 動(dòng) Pu sh ed Da ta Li st en er 線程在后 臺(tái)運(yùn) 行,監(jiān)聽 push 來的數(shù) 據(jù)
- PushedDataListener.waitForSingleton ().start();
- }
- }
在ECL Application的main()方法中,如果發(fā)現(xiàn)有參數(shù)傳進(jìn)來,那么說是有用戶點(diǎn)擊了應(yīng)用圖標(biāo),想打開GUI界面查看數(shù)據(jù)。
- class ECLApplication extends UiApplication {
- public static void main(String[] args) {
- if ( args != null && args. length > 0) { //entry point 是有參數(shù) 的,那么 打開 GUI 窗口
- ECLApplication theApp = new ECLApplication();
- theApp.enterEventDispatcher();
- }
- else { //entry point 是沒有參 數(shù)的, 那么啟 動(dòng) Pu sh ed Da ta Li st en er 線程在后 臺(tái)運(yùn) 行,監(jiān)聽 push 來的數(shù) 據(jù)
- PushedDataListener.waitForSingleton ().start();
- }
- }
在ECLApplication構(gòu)造方法中,首先把應(yīng)用的圖標(biāo)從未讀狀態(tài),修改為已讀狀態(tài);然后調(diào)用DataStore類讀取PersistentStore里面的數(shù)據(jù),***彈出EclScreen窗口以樹狀組件顯示數(shù)據(jù)。
DataStore和EclScreen代碼因?yàn)楹蚉ush操作無關(guān),這里就不再做代碼分析了。
- public ECLApplication () {
- …
- Bitmap icon=Bitmap.getBitmapResource("icon/read.gif");
- net.rim.blackberry.api.homescreen.HomeScreen.updateIcon(icon);
- //call the datastore class
- DataStore dataStore = new DataStore();
- //opens the persistent store and loads in the group list dataStore.loadGroupListFromStore();
- EclScreen screen = new EclScreen(dataStore);
- pushScreen(screen);
- }
Pushed Data Listener代碼說明
Push監(jiān)聽代碼是客戶端最核心的代碼。Push.java首先是使用wait For Singleton()方法達(dá)到手機(jī)上只有一個(gè)Pushed Data Listener對(duì)象在運(yùn)行的目的,然后構(gòu)建并啟動(dòng)Listener Thread類開始監(jiān)聽。
wait For Singleton()方法把唯一的Pushed Data Listener對(duì)象實(shí)例保存到Runtime Store對(duì)象中,從而實(shí)現(xiàn)singleton模式。Runtime Store在黑莓手機(jī)中是程序間共享的存儲(chǔ)空間,或者說所有程序都可以訪問其他程序保存在Runtime Store里面的數(shù)據(jù)。在手機(jī)重新啟動(dòng)后,Runtime Store被清空。
- class PushedDataListener extends UiApplication {
- ime
- public static final long RTSID_MY_APP = 0x56b19e51d45ff827L;
- private static final String LISTEN_URL = "http://:911" ; //the listen port
- private ListenerThread myThread ;
- public PushedDataListener() {
- myThread = new ListenerThread();
- }
- public static PushedDataListener waitForSingleton (){
- Push.java Pushed Data Listener的監(jiān)聽代碼放在Listener Thread類中。Listener Thread類擴(kuò)展
- //make sure this is a singleton instance
- RuntimeStore store = RuntimeStore.getRuntimeStore ();
- Object o = store.get( RTSID_MY_APP );
- if (o == null ){
- store.put( RTSID_MY_APP , new PushedDataListener());
- return (PushedDataListener)store.get( RTSID_MY_APP );
- } else {
- return (PushedDataListener)o;
- }
- }
Thread線程類,調(diào)用(Stream Connection Notifier)Connector.open(LISTEN_URL)方法和stream=notify.acceptAndOpen();代碼開始監(jiān)聽911端口上push過來的數(shù)據(jù)。
收到數(shù)據(jù)后調(diào)用Data Store方法保存數(shù)據(jù)到持久存儲(chǔ)中,工ECLGUI進(jìn)程顯示數(shù)據(jù);然后調(diào)用Home Screen.update Icon(icon,1)代碼更新ECL圖標(biāo)為未讀提示。
- class ListenerThread extends Thread {
- public void run() {
- System. out .println( "eclBackGroundThread -- running" ); StreamConnectionNotifier notify = null ;
- StreamConnection stream = null ; InputStream input = null ;
- try {
- sleep (1000);
- }
- catch (Exception e){}
- try {
- notify = (StreamConnectionNotifier)Connector. open ( LISTEN_URL );
- for (;;) {
- //NOTE: the following will block until data is received
- stream = notify.acceptAndOpen();
- input = stream.openInputStream();
后記:
- //Extract the data from the input stream
- StringBuffer sb = new StringBuffer();
- int datum = -1;
- while ( -1 != (datum = input.read()) )
- {
- sb.append(( char )datum);
- }
- stream.close();
- stream = null ;
- String contactData = sb.toString(); DataStore dataStore = new DataStore(); dataStore.saveData(contactData);
- Bitmap icon=Bitmap.getBitmapResource ( "icon/unread.gif" );
- net.rim.blackberry.api.homescreen.HomeScreen. updateIcon (icon,1);
- bytes) \n" );
- System. err .println( "Push message received...(" +contactData.length()+ "
- System. err .println(contactData);
常見運(yùn)行錯(cuò)誤處理
1.模擬器無法收到Push數(shù)據(jù)
解決辦法:使用***的BlackberryPluginforeclipse1.1版本,運(yùn)行項(xiàng)目的時(shí)
候選擇啟動(dòng)MDS模擬器。啟動(dòng)模擬器后,確認(rèn)模擬器的網(wǎng)絡(luò)連接是好的,方法是打開瀏
覽器訪問任意外網(wǎng)網(wǎng)站。
2.服務(wù)器端和客戶端程序各自的端口不匹配
解決辦法:在ECL例子程序中兩個(gè)端口都是911,注意查看。如果你參考ECL代碼編寫自己的Push程序,那么建議你把服務(wù)器和客戶端的端口都修改為非911的端口,以避免在手機(jī)上參數(shù)監(jiān)聽端口沖突。
3.客戶端程序沒有autostart,因而沒能啟動(dòng)監(jiān)聽程序
解決辦法:在ECL例子程序中,編輯BlackBerry_App_Descriptor.xml,選擇Auto-runonstartup,并在代碼的main()方法中相應(yīng)處理,啟動(dòng)listenerthread在后臺(tái)開始監(jiān)聽。
4.客戶端收到的文字中文亂碼解決辦法:首先,服務(wù)器端代碼在提出Push請(qǐng)求時(shí)候要通過Http URL Connection.set Request Property(("Content-Type",…)方法告訴BES/MDS服務(wù)器,它將發(fā)送什么樣的內(nèi)容。如果是Content-Type是text/plain,那么服務(wù)器將以gb2312編碼發(fā)送數(shù)據(jù);為代碼清晰起見,建議設(shè)置Content-Type為text/plain;charset=utf-8。
- public void sendToHandheld(String recipientEmail) … {
- HttpURLConnection conn = null;
- …
- establishRequestHeaders(conn);
- …
- }
- protected void establishRequestHeaders(HttpURLConnection conn) {
- conn.setRequestProperty("Content-Type", "text/plain ; charset=utf-8 ");
- }
其次,客戶端接收數(shù)據(jù)的時(shí)候,建議讀取byte[],然后按照服務(wù)器Content-Type相同的編碼進(jìn)行轉(zhuǎn)碼獲得字符串String。
- stream = notify.acceptAndOpen();
- input = stream.openInputStream();
- //Extract the data from the input stream byte[] bytes = loadBytesFromStream(input); stream.close();
- stream = null;
- String contactData = new String(bytes , “UTF-8” );
英文縮寫說明
BES–BlackBerry Enterprise Server,是BlackBerry解決方案的核心服務(wù)器之一,架設(shè)在企業(yè)內(nèi)網(wǎng)。
MDS–BlackBerryMobileDataSystem,是BES服務(wù)器的一個(gè)重要組件。在Push技術(shù)中,
MDS接受Push請(qǐng)求,然后通過BES其他組件把數(shù)據(jù)推送出去。
參考資料
1.BES服務(wù)器推送機(jī)制分析
http://www.searchcio.com.cn/whitepaper_1161.htm
2.What Is-Sample applications demonstrating BlackBerry pushtechnology:Emergency ContactList
http://www.blackberry.com/go/ecl
附錄:
一.如何更換不同版本的BlackBerry SDK?
由于不同BlackBerry手機(jī)使用不同版本的OS,所以在應(yīng)用編譯的時(shí)候,需要使用不同的
BlackBerry SDK。
首先可以在Eclipse中獲取所有版本的BlackBerry SDK,目前有的包括4.5,4.6和5.0版本:Eclipse=>Help=>InstallNewSoftware=>輸入U(xiǎn)RL:
http://www.blackberry.com/go/eclipseUpdate/3.5/java
然后進(jìn)行更新即可。
二.如何選擇不同版本的BlackBerry SDK?


在上圖中選擇Edit

然后再次編譯即可:

或者:在JRE System Library右擊鼠標(biāo),屬性中選擇不同的SDK即可。
三.ECLsampleBrowserpush中文問題的解決
現(xiàn)象:xyzlist.xls數(shù)據(jù)源里面有中文,通過MDS服務(wù)器push到手機(jī)里面的網(wǎng)頁,中文是亂碼,顯示不正常。
step1.編輯ECL_Java\src\Server\BrowserChannelPusher.java把con.set Request Property('Content-Type','text/html');
修改為con.setRequestProperty('Content-Type','text/html;charset=gb2312');
step2.重新編譯生成ECL_Java\bin\Server\ecl.jar執(zhí)行ECL_Java\src\Server\build.bat
step3.重新運(yùn)行pushserver/client測(cè)試即可

