Как передать параметр подклассу BroadcastReceiver?

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

Таким образом, единственный оставшийся мне вариант (для поддержки как 2.x, так и 4.1) - передать действие в качестве параметра RemoteControlReceiver< /а>.

Но как мне это сделать, когда единственный способ создать экземпляр - через:

private ComponentName mRemoteControlReceiver = new ComponentName(this, RemoteControlReceiver.class);

Который не принимает никаких дополнительных параметров?

Любая идея, как обойти это ограничение?

Примечание. Если я попытаюсь определить RemoteControlReceiver как имеющий конструктор с параметром, я получу следующее исключение:

E/AndroidRuntime(2836): java.lang.RuntimeException: Unable to instantiate receiver com.example.RemoteControlReceiver: java.lang.InstantiationException: can't instantiate class com.example.RemoteControlReceiver; no empty constructor

Caused by:
E/AndroidRuntime(2836): Caused by: java.lang.InstantiationException: can't instantiate class com.example.RemoteControlReceiver; no empty constructor
E/AndroidRuntime(2836):     at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime(2836):     at java.lang.Class.newInstance(Class.java:1319)
E/AndroidRuntime(2836):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2205)

Итак, ясно, что это новое требование registerMediaButtonEventReceiver (появившееся в Android 4.1) предполагает наличие пустого конструктора.

Нет ли способа обойти это?

Например, есть ли способ получить ссылку на фактический объект RemoteControlReceiver (создан косвенно через mAudioManager.registerMediaButtonEventReceiver())? Чтобы я мог использовать метод доступа для установки члена данных RemoteControlReceiver после его создания?


person an00b    schedule 27.02.2013    source источник
comment
вы можете создать и зарегистрировать BroadcastReceier в onResume/onCreate Activity и отменить регистрацию внутри onPause/onStop. Таким образом, текущая активность может позаботиться о времени своего существования, а получатель должен иметь возможность общаться со своим контейнером (активностью).   -  person Sudar Nimalan    schedule 27.02.2013
comment
Это сложный вопрос, но вот идея: можете ли вы проверить Extra, переданные с Intent onReceive? Или использовать этот трюк GlobalVariable?   -  person Android Eve    schedule 27.02.2013
comment
см. этот ответ, может быть, это поможет вам. stackoverflow.com/questions/15059886/   -  person Jignesh Ansodariya    schedule 27.02.2013


Ответы (1)


registerMediaButtonEventReceiver требует, чтобы BroadcastReceiver быть объявлены в манифесте приложения. Это означает, что получатель должен быть автономным классом, то есть он ничего не знает о вашей текущей деятельности или услуге.

Чтобы получить это сообщение для вашей деятельности или услуги, у вас есть несколько вариантов:

  • Используйте статический глобальный объект для действия или службы, чтобы получатель мог переслать ему сообщение. Как правило, это не очень хорошая идея, так как это приводит к утечкам и не очень адаптируется, когда вы хотите изменить код позже. Обычно следует избегать статики.

  • Повторно передайте сообщение определенному классу, который является внутренним классом действия или службы, которую вы хотите вызвать. Например. в BroadcastReceiver для registerMediaButtonEventReceiver:

    // Standalone class, declared in the manifest
    public class ButtonReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            Intent intent = new Intent();
            intent.setAction("com.foo.ACTION");
    
            // Rebroadcasts to your own receiver. 
            // This receiver is not exported; it'll only be received if the receiver is currently registered.
            context.sendBroadcast(intent); 
        }
    }
    

И в вашей деятельности:

    class MyActivity extends Activity {
        private BroadcastReceiver myReceiver = new BroadcastReceiver() {
            @Override
             public void onReceive(final Context context, final Intent intent) {
                MyActivity.this.onMessageReceived();
             }
        }
        @Override
        protected void onResume() {
            registerReceiver(myReceiver, new IntentFilter("com.foo.ACTION"));
        }

        @Override
        protected void onPause() {
            unregisterReceiver(myReceiver);
        }

        private void onMessageReceived() {
        }
    }
  • Подобно описанному выше методу, это не обязательно должна быть широковещательная рассылка, это может быть намерение, переданное действию, в зависимости от вашего варианта использования. Чтобы сделать это вместо sendBroadcast, вы должны использовать startActivity (или startService, если вы используете службу).
person Sofi Software LLC    schedule 27.02.2013