AlarmManager, BroadcastReceiver и служба не работают - PullRequest
13 голосов
/ 29 января 2012

Я выполняю рефакторинг некоторого кода, чтобы мое приложение получало данные с веб-сайта один раз в день в указанное время.Из моего исследования кажется, что AlarmManager является наиболее подходящим подходом.

Урок, которым я следовал, таков: http://mobile.tutsplus.com/tutorials/android/android-fundamentals-downloading-data-with-services/

Пока AlarmManager и BroadcastReceiverкажется, что работает, однако Service никогда не запускается (т. е. onStartCommand, кажется, не вызывается)

Вот важные фрагменты кода, который я до сих пор имел:

MyActivity.java

private void setRecurringAlarm(Context context) {
    Calendar updateTime = Calendar.getInstance();
    updateTime.setTimeZone(TimeZone.getDefault());
    updateTime.set(Calendar.HOUR_OF_DAY, 20);
    updateTime.set(Calendar.MINUTE, 30);

    Intent downloader = new Intent(context, AlarmReceiver.class);
    downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    // should be AlarmManager.INTERVAL_DAY (but changed to 15min for testing)
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent); 
    Log.d("MyActivity", "Set alarmManager.setRepeating to: " + updateTime.getTime().toLocaleString());
}

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent dailyUpdater = new Intent(context, MyService.class);
        context.startService(dailyUpdater);
        Log.d("AlarmReceiver", "Called context.startService from AlarmReceiver.onReceive");
    }
}

MyService.java

public class MyService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyService", "About to execute MyTask");
        new MyTask().execute();
        return Service.START_FLAG_REDELIVERY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private class MyTask extends AsyncTask<String, Void, boolean> {
        @Override
        protected boolean doInBackground(String... strings) {
            Log.d("MyService - MyTask", "Calling doInBackground within MyTask");
            return false;
        }
    }
}

AndroidManifest.xml

<application ...>
    ...
    <service android:name="MyService"></service>
    <receiver android:name="AlarmReceiver"></receiver>
</application>

Когда я запускаю setRecurringAlarm в MyActivity, журнал печатает, как и ожидалось, аналогично, каждые 15 минут журнал из AlarmReceiver появляется.Однако я никогда не вижу журнал из MyService: (

Пример того, что я вижу в журналах:

DEBUG/MyActivity(688): Set alarmManager.setRepeating to: Jan 29, 2012 8:30:06 PM
DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive
DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive

Не могу понять, что я сделал неправильноМое понимание из Документов для разработчиков Android таково, что в AlarmReceiver, когда я звоню context.startService(dailyUpdater), это, в свою очередь, должно вызывать onStartCommand в MyService, хотя, похоже, это не так!

Что я делаю неправильно, из-за чего MyService вообще не запускается?

Ответы [ 3 ]

15 голосов
/ 12 февраля 2012

Разобрался!

MyService должно расширяться IntentService вместо Сервис !

С этим изменением это также означает, что вместо переопределения onStartCommand вместо этого следует переопределить onHandleIntent (см. Документы по IntentService )

Итак MyService теперь выглядит так:

public class MyService extends IntentService {

    public MyService() {
        super("MyServiceName");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("MyService", "About to execute MyTask");
        new MyTask().execute();
    }

    private class MyTask extends AsyncTask<String, Void, boolean> {
        @Override
        protected boolean doInBackground(String... strings) {
            Log.d("MyService - MyTask", "Calling doInBackground within MyTask");
            return false;
        }
    }
}

Примечание: из документов реализация по умолчанию onBind возвращает null, поэтому нет необходимости переопределять ее.

Подробнее о расширении IntentService: http://developer.android.com/guide/topics/fundamentals/services.html#ExtendingIntentService

0 голосов
/ 29 января 2012

Вместо использования

Intent dailyUpdater = new Intent(context, MyService.class);

использование

Intent dailyUpdater = new Intent(this, MyService.class);

Другое предложение состоит в том, чтобы запускать службу непосредственно из тревоги, а не отправлять трансляцию и запускать службу в приемнике трансляции.

0 голосов
/ 29 января 2012

Вы можете заставить AlarmManager сразу запустить Сервис, а не через BroadcastReceiver, если вы измените свое намерение следующим образом:

//Change the intent
Intent downloader = new Intent(context, MyService.class);
    downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

//Change to getService()
PendingIntent pendingIntent = PendingIntent.getService(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);

Это может решить вашу проблему!

...