NickPR
NickPR

Reputation: 594

Using Android service context for Room database

I'm working on an App that uses both Firebase Messaging and Room database.

This is how the db is initialized

public static AppDatabase getInstance(final Context appContext) {
    if (INSTANCE == null) {
        INSTANCE = Room.databaseBuilder(appContext, AppDatabase.class, "dbname.db")
                // prepopulate the database after onCreate was called
                .addCallback(rdc)
                .build();
    }
    return INSTANCE;
}

Somewhere on MainActivity the first call to AppDatabase is made and the database is instantiated, all is working fine and dandy!

Now the problem starts when the user kill the app...

For the sake of simplicity think of this App like Whatsapp... the application got killed but the service (MyFirebaseMessagingService) that is listening for messages is still running (as it should).

When a new message arrives and MyFirebaseMessagingService tries to save it to the database with a call to AppDatabase.getInstance() a crash will occur since the initial context reference on witch the database was created no longer exists because the application was killed.

Searching on how to solve this I learned that every service this is actually derived from context so I immediately tried to use the MyFirebaseMessagingService context to initialize the database, however, MyFirebaseMessagingService::onCreate where you really have access to the service context don't get fired until the first message arrives

The only solution I can think of is creating a completely new service, bindService() it to the MainActivity, and use that new service context to create the AppDatabase instance... but it seems completely overkill.

So my question is, how can initialize the Room Database in a way that MyFirebaseMessagingService can still use it even if the App was killed?

Upvotes: 12

Views: 3767

Answers (3)

Manoj Perumarath
Manoj Perumarath

Reputation: 10254

Since FirebaseMessagingService is a service we should have getApplicationContext() there, you should use that to create an instance of your dB and do the necessary operations, The other options are to create a service or write a custom broadcast receiver.

Upvotes: 0

Tharanga
Tharanga

Reputation: 2767

getApplicationContext() is not available in the constructor function. But it's available inside onStartCommand() function. I think that's a good place to build/open the database in a service.

Upvotes: 2

Rares Serban
Rares Serban

Reputation: 150

First: from a system context (NOTIFICATION_SERVICE) you are trying to use Room that uses the app context to access or create the database. But the app context might be null in that moment. Maybe just because the app got killed. So you get a nice crash.

Second, some logs would be nice. With the crash. It might keep people from guessing.

Third: (Again a guess) Maybe you should try Work manager. Something like: you receive data > start work. Will run reliably and do not have to run right in that moment. A great place to start here

Upvotes: -1

Related Questions