2012-09-06 38 views
2

概述:黑莓 - 如何訪問數據庫(或創建HTTP連接)在後臺線程時,UI應用程序不開

我們的應用延伸的UIApplication並且具有註冊的短信監聽器類在開機時。當收到符合我們標準的消息時,我們會處理消息,然後我們希望將其保存到本地SQLite數據庫,並將其上傳到Web服務器。即使UI應用程序在該階段未打開,在收到SMS後儘快發生這一點很重要。

問題:

當SMSListener實例在後臺運行,沒有UIApplication的情況下有效,並且想訪問SQLite數據庫或試圖創建一個HTTP連接「無應用程序實例」的例外是拋出。

期望的結果:

我們要處理,保存和上傳所有從SMSListener後臺線程的消息,即使UIApplication的不活躍。目前SMSListener後臺線程會將消息存儲在RuntimeStore中;當UI應用程序啓動時,它將從RuntimeStore中讀取消息並將其保存到數據庫中。但這不是一個最佳解決方案,因爲與Web服務器的同步只會在下次打開UI應用程序時纔會發生。收到消息時相當重要。

應用僞代碼:

主類,檢查啓動並創建一個SMSListener實例或從RuntimeStore得到實例。

public class OurAppUi extends UiApplication { 
public static void main(String[] args) { 
    if (args != null && args.length > 0 && args[0].endsWith("gui")) { 
     // Create a new instance of the application and make the currently 
     // running thread the application's event dispatch thread. 
     OurAppUi theApp = new OurAppUi(); 
     theApp.enterEventDispatcher(); 
    } else { 
     // Entered through the alternate application entry point 
     SmsListener.waitForSingleton(); 
    } 
} 
} 

的SMSListener類監聽任何傳入的消息,利用了RuntimeStore singlton模型的。這是按預期工作的。

public class SmsListener implements javax.wireless.messaging.MessageListener { 
public static SmsListener waitForSingleton() { 
    //Ensure this is a singleton instance. 
    //Open RuntimeStore and obtain the reference of BackgroundListener 
    RuntimeStore store = RuntimeStore.getRuntimeStore(); 
    Object obj = store.get(ID_BACKGROUND_LISTENER); 

    //If obj is null, there is no current reference to BackgroundListener 
    //Start a new instance of BackgroundLIstener if one is not running 
    if(obj == null) { 
     store.put(ID_BACKGROUND_LISTENER, new SmsListener()); 
     return (SmsListener)store.get(ID_BACKGROUND_LISTENER); 
    } else { 
     return(SmsListener)obj; 
    } 
} 

public void notifyIncomingMessage(MessageConnection conn) { 
    new Thread() { 
     MessageConnection connection; 
     Thread set (MessageConnection con) { 
      this.connection = con; 
      return (this); 
     } 

     public void run() { 
      try { 
       Message m = connection.receive(); 
       String msg = null; 

       if (m instanceof TextMessage) { 
        TextMessage tm = (TextMessage)m; 
        msg = tm.getPayloadText(); 
       } 
       // Process the SMS 
       SMSObject sms = processSMS(msg); 
       // Save to DataBase { Exception is Thrown Here } 
       SQLManager.getInstance().save(sms); 
       // Upload to Web Server { Exception is Thrown Here } 
       WebServer.upload(sms); 

      } catch(Exception error) { 
      } 
     } 
    }.set(conn).start(); 

} 
} 

當SmsListener實例要訪問​​SQLite數據庫或試圖創建一個HTTP連接「無應用程序實例」拋出異常。

public final class SQLManager { 
private SQLManager() { 
    try { 
     db = OpenOrCreateDatabase(); 
    } catch (MalformedURIException e) { 
     Debug.log(TAG, "Get connection: URI: " + e.getMessage()); 
    } catch (ControlledAccessException e) { 
     Debug.log(TAG, "Get connection: Controlled Access: " + e.getMessage()); 
    } catch (DatabasePathException e) { 
     Debug.log(TAG, "Get connection: Database Path: " + e.getMessage()); 
    } catch (DatabaseIOException e) { 
     Debug.log(TAG, "Get connection: Database IO: " + e.getMessage()); 
    } catch (Exception e) { 
     Debug.log(TAG, e); 
    } 
} 

public static synchronized SQLManager getInstance() { 
    if (instance == null) { 
     instance = new SQLManager(); 
    } 
    return instance; 
} 
} 

我們試圖店在RuntimeStore SQLite的情況下,使用相同的辛格爾頓模型作爲SMSListener但是當UI應用程序試圖訪問存儲的數據庫實例收到錯誤。

+0

'通過備用應用程序入口點進入' - 在這裏您可能需要創建一個應用程序實例並需要調用該實例的enterEventDispatcher()。檢查這個,http://stackoverflow.com/questions/3921029/how-to-setup-alternate-entry-point-in-blackberry-application。 – Rupak

回答

2

一般處理這種類型的活動的方式是將應用程序分爲兩個部分:需要用戶界面,當用戶想要與互動只需要運行

  1. 用戶互動的部分應用;
  2. 將存儲數據並與遠程服務器進行通信的後臺處理部分。

後臺處理應該在net.rim.device.api.system.Application擴展的上下文中進行,該擴展可能應該是基於RuntimeStore的單例。這部分應該從您的自動運行代碼開始,註冊聽衆並保持活動狀態。確保代碼在正確的上下文中執行有一些複雜性。我有一個blog post可能會有幫助。

+0

謝謝。看起來像這樣。我們啓動一個Application Singleton,然後啓動SMSListener單例。 – ricoza