samo
samo

Reputation: 373

Service could not be started from ContentProvider

After an update of the App I need to fill uniquely the databases with additional data from the internet. For this purpose I've implemented a service called OnUpgradeService(). This service should be started in the OnUpgrade() method of the SQLiteOpenHelper.

I can see that startService is executed but onStartCommand() is not called.

public class MyContentProvider extends ContentProvider {
    ...
    private static class MyOpenHelper extends SQLiteOpenHelper {
        ...
        public MyOpenHelper(Context context, String name, CursorFactory factory, int version) {
            super(context, name, factory, version);
            this.context = context;
        }
        ...
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            if (oldVersion == 1) {
                db.execSQL(DATABASE_CREATE_THUMBNAIL);
                db.execSQL("alter table " + DATABASE_TABLE_FRIEND + " add column " + KEY_THUMBNAIL_URI + " text;");
                ...
                Intent intent = new Intent(context, OnUpgradeService.class);
                context.startService(intent);
            }
            else {
                db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE_FRIEND);
                onCreate(db);
            }
        }
        ...
        public class OnUpgradeService extends Service {
            ...
            @Override
            public int onStartCommand(Intent intent, int flags, int startId) {
                Thread t = new Thread(new Runnable() {
                    public void run() {
                        upgradeDatabase();
                        stopSelf();
                    }
                });
                t.start();
                return Service.START_REDELIVER_INTENT;
            }

The relevant entries in the manifest looks as follows:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
    ...
    <application>
        ...
        <service android:enabled="true" android:name=".OnUpgradeService" /> 
        ...
    </application>
    ...
</manifest>

Upvotes: 0

Views: 243

Answers (1)

CommonsWare
CommonsWare

Reputation: 1006849

The app does neither crash nor are there any hints in the LogCat why the Service is not started

I find that somewhat difficult to believe -- I am willing to bet that there are some warnings (not necessarily errors) related to this.

Android components, like a Service, cannot be an ordinary inner class, as then Android has no way of creating an instance. Your OnUpgradeService would need to be a static inner class.

Then, if you make that change, your manifest entry is wrong, as it claims that OnUpgradeService is not an inner class of anything.

The simplest way to fix both problems is to move OnUpgradeService to be a regular top-level public Java class, in its own file.

All that being said, I will be fairly surprised if you find that your given approach will work well over the long haul. Burying something like populating a database from the Internet the way you have seems like it will give you lots of problems. As it stands, it is relatively unpredictable when you will be asked to populate the database, as it will be whenever somebody tries performing some operation on this ContentProvider, and that may not be an appropriate moment. Also, there is the question of what the user will see immediately, while the data population has not occurred. I would strongly encourage you to think much more seriously about your data synchronization model, rather than considering it to be some side-effect of a whenever-it-happens database schema change.

Upvotes: 2

Related Questions