2016-03-30 2 views
-2

私はSQLiteにデータを格納するサービスを持っています。アプリケーションが閉じられたときにそのサービスを実行し続けたい。 (スワイプアウト)しかし、getInstance()は、アプリケーションが破棄されたときにnullを返します。アプリケーションを閉じた後でも、どうすればそれを生き続けることができますか?サービスでシングルトンSQLiteHelperを使用する

マイデータベースシングルトンクラス:

public class DbManager { 
    private static DbManager instance; 
    private CipherDbHelper dbHelper; 

    private DbManager() { 

    } 

    private DbManager(Context context, String password) { 
     SQLiteDatabase.loadLibs(context); 
     dbHelper = new CipherDbHelper(context, password); 
    } 

    public static void init(Context context, String password) { 
     instance = new DbManager(context, password); 
    } 

    public static DbManager getInstance() { 
     if (instance == null) { 
      Log.e("DbManager", "Can't access DbManager : instance is null.") 
     } 
     return instance; 
    } 

    //Closing 
    public void closeDatabase() { 
     dbHelper.close(); 
     dbHelper = null; 
     instance = null; 
    } 

    public <D extends Dao<T, String>, T> D getDAO(Class<T> clz) throws SQLException { 
     return dbHelper.getDao(clz); 
    } 


} 
+0

個人的にそれを取ることはありませんが、おそらくあなたが得た例外は実際には例外メッセージではなくあなたのコードにハードコードされているので、あなたはおそらくdownvotedです。 –

+0

「最初の問題」とはどういう意味ですか?あなたは "私にこの例外があります、なぜですか?"のように聞こえました。あなたが投稿したコードは、その理由はあなたの変数がnullであると思われるので、そうするようにコード化されているので例外がスローされます。 –

答えて

0

バックグラウンドでタスクを実行するには、Serviceを使用する必要があります。あなたがDBManager.getInstance()を呼び出す前に


だけDBManager.init(context)を呼び出します。インスタンスはnullのままですので、initメソッドを呼び出す必要があります。

1

ステップ1:closeDatabase()とそれを呼び出すコードを削除します。

ステップ2:の代わりにgetDatabase()が返されます。nullが例外をスローする代わりに返されるか、またはカスタム例外がスローされます。

ステップ#3:サービスは、そのgetDatabase()呼び出しからnullを取得した場合(またはそれはあなたのカスタム例外をキャッチ)、それは「私はあなたが再度ログインする必要があり、」ユーザーを伝え、どんな仕事にそれをやってスキップするNotificationを上げていやっているはずだった。

基本的に、アーキテクチャの問題があります。Androidプロセスは短命です。これは、バックグラウンドで暗号化されたデータベースを使用して作業することは通常不可能です。プロセスが終了するとすぐに、ユーザーのパスフレーズでロック解除されたデータベースにアクセスできなくなり、ユーザーは再度ログインする必要があります。

フォアグラウンドサービス(startForeground()経由)を使用すると、プロセスが終了する可能性を減らすことができますが、これはユーザーにとってコストがかかります(常に表示されますNotification、バックグラウンド作業など)。

+0

メソッドcloseDatabase()が呼び出されたことがないため、問題ではありません。だから、SQLCipherは、アプリケーションが実行されている場合にのみ動作しますか? 2つのデータベースを使用できますか?1つは暗号化され、もう1つは使用できませんか?ありがとうございます – Jaythaking

+1

@ジェイジング: "したがって、SQLCipherは、アプリケーションが実行されている場合にのみ動作しますか?" - 私はそれを "SQLCipherにはパスワードが必要ですが、あなたのUIを通してユーザーからしか得ることができません"とさらに記述します。 「暗号化されたデータベースとそうでないデータベースの2つを使用できますか?」確かに、私はそれがユーザーのセキュリティ上の懸念に対処するかどうかは言えませんが。 – CommonsWare

+0

"SQLCipherにはパスワードが必要ですが、これはユーザーからUIでしか取得できません"暗号化されたデータベースのロックが解除されたらサービスを開始します。アプリが死んでも破壊されない限りパスワードは必要ありませんいいえ? – Jaythaking

0

シングルトンクラスを使用してヘルパーインスタンスを取得するサービスでSQLiteデータベースにアクセスする(暗号化されているかどうかに関係なく)誰もが同じ問題に直面しています。私の問題をどのように解決したかは次のとおりです。サービスのコンテキストをSQLiteHelperに渡して、libを再度ロードし、ヘルパーインスタンスを再生成してください。アプリが閉じられると、それは(それをスワイプして)破壊されることはありません

私の例では、私は私のサービスののonCreateメソッドでこれを呼ばれる:

DbManager.init(TrackingService.this, "examplePassword"));