Проблемы с передачей намерения в службу Android из класса приложений - PullRequest
2 голосов
/ 16 декабря 2011

У меня есть установка, в которой я запускаю фоновую службу в Android с подключенным BroadcastReceiver для прослушивания определенных типов Intents.Эти намерения затем используются приемником вещания для вызова определенных методов в услуге.Ниже приведен код, описывающий структуру службы:

public class MyService extends Service {

     private class ServiceBroadcastReceiver extends BroadcastReceiver {


            private MyService getMyService() {
                return MyService.this;
            }

            public IntentFilter getASReceiverFilter() {
                IntentFilter filter = new IntentFilter()
                filter.addAction(Constants.ACTION_DO_SOMETHING);
                return filter;
            }

            @Override
            public void onReceive(Context context, Intent intent) {
                // TODO Auto-generated method stub
                MyService svc = getMyService();
                String intentAction = intent.getAction();
                Log.i(Constants.LOG_TAG, "Now trying to dispatch following action: " + intentAction);
                //Dispatch to the appropriate method in MyService. 
                if (intentAction.equals(AppServiceConstants.ACTION_DO_SOMETHING)) {
                    svc.doSomething();
                } 
            }
        }


    private ServiceBroadcastReceiver mRequestReceiver = new ServiceBroadcastReceiver();


    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }


    @Override
    public void onCreate() {

        Log.i(Constants.LOG_TAG, "Service Created!");
        //Register for broadcast messages indicating the add music button was pressed
        mRequestReceiver = new ServiceBroadcastReceiver();
       registerReceiver(mRequestReceiver, mRequestReceiver.getASReceiverFilter()); 
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.i(Constants.LOG_TAG, "Service Starting ... ");

        // If we get killed, after returning from here, restart
            return START_STICKY;
    }



    /***********************************************************************************
     * Service Dispatch Methods
     */
     protected void doSomething() {
         Log.i(Constants.LOG_TAG, "Doing something"); 
     }



}

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

getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

.., это сработает, только если я вызову это из Activity.Однако я хочу иметь возможность «что-то делать» даже при первом запуске приложения, поэтому я поместил этот оператор в свой собственный подкласс Application в методе onCreate () сразу после создания MyService и его запуска.По какой-то причине трансляция не работает из кода класса приложения при запуске приложения, но она будет работать, если я добавлю его в какой-то код внутри действия (например, в методе onCreate () действия).Я могу подтвердить, что методы onCreate () и onStartCommand () службы вызываются до передачи намерения в моем объекте Application, но, похоже, он просто не получает намерения и не выполняет соответствующую работу.

Буду признателен за любую помощь.

Обновление:

Вот как я отправляю трансляцию из своего приложения (обратите внимание, что я сначала запускаю службу):

 public class MyApplication extends Application {
        @Override
        public void onCreate() {
            Intent intent = new Intent(getApplicationContext(), MyService.class);
        getApplicationContext().startService(intent);
    getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

        }

 }

Обратите внимание, что я запускаю службу, прежде чем я на самом деле делаю трансляцию.Служба НЕ получает широковещательную рассылку, но если я выполняю аналогичный вызов из действия, которое запускаю позже, она получает.

1 Ответ

6 голосов
/ 16 декабря 2011

Ваш Application создан перед любым другим компонентом в процессе. Так что в onCreate() нет Serivce работы. И если вы отправляете широковещательную рассылку в момент вызова приложения onCreate(), Service не зарегистрировал широковещательный приемник, поскольку он даже не был создан.

Таким образом, другими словами, ваша служба не получает широковещательное уведомление, потому что широковещательный получатель еще не зарегистрирован. И он еще не зарегистрирован, потому что Service еще не запущен. И он не может быть запущен до того, как приложение onCreate() вернется в исходное состояние.

Вы можете напрямую запустить службу, используя Context.startService() из приложения onCreate(). Вы сможете направить все необходимые данные через Intent.


Обновленный ответ на обновленный вопрос:

При звонке:

getApplicationContext().startService(intent);

Вы просите Android запустить службу позже. Услуга не запущена сразу. Это только запланировано начать позже. На самом деле он точно не запустится, прежде чем вы вернетесь из функции onCreate() приложения. Это потому, что все функции обратного вызова жизненного цикла Сервиса (такие как onCreate() и onStart()) вызываются из основного потока пользовательского интерфейса. И заявка onCreate в настоящее время блокирует основной поток пользовательского интерфейса.

Итак, когда вы отправляете трансляцию, используя следующие строки кода:

getApplicationContext().startService(intent);
getApplicationContext().sendBroadcast(new Intent(Constants.ACTION_DO_SOMETHING));

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

Вы можете изменить код onStart() вашей службы для обработки намерения, а затем запустить службу, используя:

Intent intent = new Intent(getApplicationContext(), MyService.class);
intent.setAction(Constants.ACTION_DO_SOMETHING);
getApplicationContext().startService(intent);
...