概要:
このアプリケーションはUIApplicationを拡張し、起動時に登録されるSMSリスナークラスを持っています。基準に一致するメッセージを受信したら、メッセージを処理してから、ローカルのSQLiteデータベースに保存し、Webサーバーにアップロードします。その段階でUIアプリケーションが開いていなくても、SMSを受信した後できるだけ早くこれを行うことが重要です。
問題:
SMSListenerインスタンスがバックグラウンドで実行されていて、UIApplicationインスタンスがアクティブになっておらず、SQLiteデータベースにアクセスしたい場合、またはHTTP接続を作成しようとすると、「アプリケーションインスタンスなし」例外がスローされます。
望ましい結果:
UIApplicationがアクティブでない場合でも、SMSListenerバックグラウンドスレッドからのすべてのメッセージを処理、保存、およびアップロードする必要があります。現在、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シングルトンモデルを利用します。これは期待どおりに機能しています。
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;
}
}
SMSListenerと同じシングルトンモデルを使用してSQLiteインスタンスをRuntimeStoreに保存しようとしましたが、UIアプリケーションが保存されたDBインスタンスにアクセスしようとしたときにエラーが発生しました。