简体   繁体   中英

Using Singleton SQLiteHelper in Service

I have a service that store data in SQLite. I want that service to keep running when the application is closed. (Swipe out) But getInstance() return null when the app is destroyed. How can I keep it alive even after my application is closed?

My database singleton class:

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);
    }


}

Step #1: Delete closeDatabase() and any code that calls it.

Step #2: Have getDatabase() return null instead of throwing an exception, or have it throw a custom exception instead of IllegalArgumentException .

Step #3: If the service gets null from its getDatabase() call (or it catches your custom exception), have it raise a Notification to tell the user "I need you to log in again" and skip doing whatever work it was supposed to be doing.

Fundamentally, you have an architecture problem: Android processes are short-lived. A ramification of this is that working with an encrypted database in the background usually is not possible. You will lose access to the database (that was unlocked with the user's passphrase) as soon as your process ends, requiring the user to log in again.

You can use a foreground service (via startForeground() ) to reduce the chances of your process being terminated, but this has costs to the user (always-visible Notification , possibilities of too much CPU being used by the not-really-background work, etc.).

To run a task in the background, you need to use a Service .


Just call DBManager.init(context) before you call DBManager.getInstance() ; Because your instance remains null until you call your init method.

To whomever faces the same issue of accessing SQLite Database (encrypted or not) in a service using a singleton class to get the helper instance. Here is how I fixed my issue. Just pass the context of your service to the SQLiteHelper to load the lib again and re-generate the helper instance. Then it won't be destroyed once the app is closed(by swiping it out)

In my example I called this on the onCreate method of my service:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM