Как зарегистрировать в манифесте *внутренний* MEDIA_BUTTON BroadcastReceiver?

Мне удалось, чтобы кнопки моей гарнитуры распознавались моим приложением при нажатии, но одна из кнопок должна вызывать метод, который в MyCustomActivity. Проблема в том, что первый параметр onReceive — это контекст, который нельзя привести к действию, поэтому я вынужден реализовать свой BroadcastReceiver как внутренний класс внутри MyCustomActivity.

Пока все хорошо, но как мне зарегистрировать этот внутренний MediaButtonEventReceiver в манифесте?

Для независимого класса это было просто:

<receiver android:name=".RemoteControlReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

Каков трюк/синтаксис, чтобы сделать то же самое для mReceiver MyCustomActivity?

  private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context ctx, Intent intent) {
         // ...
        }
  }

person an00b    schedule 25.02.2013    source источник


Ответы (2)


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

BroadcastReceiver receiver;

@Override
protected void onCreate (Bundle b)
{
  super.onCreate (b);
  IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);    
  filter.setPriority(10000);  
  receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context ctx, Intent intent) {
      // ...
    }
  };
  registerReceiver (receiver, filter);
}

Затем не забудьте отменить регистрацию в onPause() (во избежание утечки).

@Override
protected void onPause()
{ 
  try{
    unregisterReceiver (receiver);
  }
  catch (IllegalStateException e)
  {
    e.printStackTrace();
  }
  super.onPause();
}

Однако эта динамическая регистрация означает, что если ваша активность не находится на переднем плане, кнопка не будет работать. Вместо этого вы можете попробовать отменить регистрацию в onDestroy(), но самый надежный способ избежать утечки — onPause().

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

person A--C    schedule 25.02.2013
comment
Спасибо! Я думал, что пробовал это, но, увидев, что new BroadcastReceiver() снова создается в onCreate(), я попробую еще раз и сообщу, как это сработало. +1 пока. - person an00b; 25.02.2013
comment
Странный. Я попробовал этот подход, но он почему-то не работает. Что мне не хватает? - person an00b; 25.02.2013
comment
@an00b ты выходишь из Активности? Помните, что мы отменяем регистрацию в onPause(), чтобы избежать утечки. Также не работает, как при компиляции, но ничего не делает при запуске? Я рекомендую сделать Toast в onReceive(), чтобы проверить, вызывается ли Receiver вообще. - person A--C; 25.02.2013
comment
Он компилируется и строится нормально. Это получатель, которому не звонят. Я не оставляю деятельность. - person an00b; 25.02.2013
comment
@an00b, возможно, CommonsWare имеет в виду что-то вроде этот вопрос. AudioManager#registerMediaButtonEventReceiver() И я действительно не вижу, что Intent.ACTION_MEDIA_BUTTON делает по-другому из-за того, что это статическая переменная, которая содержит строку "android.intent.action.MEDIA_BUTTON". Тем не менее, стоит попробовать. - person A--C; 25.02.2013
comment
Это filter.setPriority(10000); в конце концов сделал свое дело. Интересный. Плюс ACTION_MEDIA_BUTTON вместо MEDIA_BUTTON, конечно. - person an00b; 25.02.2013
comment
@ an00b хм, интересно, почему это упорядоченная трансляция, я ожидаю, что она будет неупорядоченной. Но приятно, что вы это узнали :D Надеюсь, это поможет большему количеству людей. - person A--C; 25.02.2013
comment
@ A--C я думаю, почему это упорядочено, так что, скажем, ответ / завершение телефонного звонка имеет приоритет над запуском / приостановкой музыки. - person Steven Byle; 25.02.2013
comment
Кстати, приведенный выше код отлично работает в Android 2.x, но не работает в Android 4.1 (Jelly Bean). Фрагментация Android Уггррр... - person an00b; 25.02.2013
comment
@an00b Это интересно. Я предполагаю, что вы можете заставить получателя начать действие с флагом singleTop, чтобы новый Intent был перенаправлен на onNewIntent() и обновил пользовательский интерфейс там. - person A--C; 25.02.2013
comment
@A--C Из-за того, что ваше замечательное решение не работает в 4.1, я все еще ищу решение (или обходной путь). У вас есть дополнительные предложения? Спасибо. - person an00b; 27.02.2013
comment
@an00b может быть расточительным, но пусть этот Receiver сделает настраиваемую трансляцию для другого BroadCastReceiver, реализованного вашей Activity. - person A--C; 27.02.2013
comment
Это не расточительно, если это единственный способ решить эту проблему. :) Почему Google решил сделать нашу жизнь такой невыносимой, убрав все прелести, которые были доступны в Android 2.x? - person an00b; 27.02.2013
comment
@an00b an00b У вас случайно нет обновленного кода 4.1 в виде какого-то проекта? Я на кастомном ПЗУ, и кнопка мультимедиа отказывается работать, поэтому мне нужна чья-то работающая реализация для проверки :) - person A--C; 02.03.2013

Пока все хорошо, но как мне зарегистрировать этот внутренний MediaButtonEventReceiver в манифесте?

Вы не можете. Однако вы можете зарегистрировать его динамически, вызвав registerReceiver() для действия.

person CommonsWare    schedule 25.02.2013
comment
Ой! Я думал, что так и будет, поэтому попробовал совет, предоставленный здесь, но по какой-то причине это не сработало. Должен ли я new BroadcastReceiver() в onCreate() или я могу сделать это при инициализации частного члена данных mReceiver? - person an00b; 25.02.2013
comment
@an00b: В любом случае работает. Обычно я устанавливаю закрытый элемент данных для получателя. - person CommonsWare; 25.02.2013
comment
закрытый член данных для получателя, это то, что у меня тоже есть, но ни один из двух подходов не работает. Я могу упустить что-то простое, но я не знаю, что это такое. Нажатия клавиш не направляются на мой внутренний приемник, как в автономном. - person an00b; 25.02.2013
comment
@an00b: медиа-кнопка может быть специальной. Проверьте AudioManager -- я припоминаю, что вам нужно настроить некоторые вещи, чтобы получить управление из работающего приложения. Обычно подход A-C работает нормально. - person CommonsWare; 25.02.2013
comment
Я так и подозревал. Возможно, мне следует использовать класс приемника, отличный от BroadcastReceiver? Есть ли MediaButtonEventReceiver? Кроме того, этот ответ говорит использовать ACTION_MEDIA_BUTTON вместо MEDIA_BUTTON. - person an00b; 25.02.2013
comment
@an00b: Не то, чтобы я знал об этом. - person CommonsWare; 25.02.2013