13

我设法让我的耳机按钮在按下时被我的应用程序识别,但是其中一个按钮需要调用 MyCustomActivity 中的方法。问题是 onReceive 的第一个参数是一个不能转换为 Activity 的 Context 并且使用 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 的数据成员吗?

4

1 回答 1

7

registerMediaButtonEventReceiver要求在应用程序清单中声明 BroadcastReceiver。这意味着接收器必须是一个独立的类,这意味着它对您当前的活动或服务一无所知。

为了将此消息发送给您的活动或服务,您有多种选择:

  • 为活动或服务使用静态全局,以便接收者可以将消息转发给它。这通常不是一个好主意,因为它会导致泄漏,并且在您以后想要更改代码时不是很适应。通常要避免静电。

  • 将消息重新广播到特定类,该类恰好是您要调用的活动或服务的内部类。例如,在 registerMediaButtonEventReceiver 的 BroadcastReceiver 中:

    // 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() {
        }
    }
  • 与上述方法类似,它不一定是广播,它可以是传递给活动的 Intent,具体取决于您的用例。要做到这一点,而不是使用 sendBroadcast,您将使用 startActivity(或 startService,如果您正在使用服务)。
于 2013-02-27T06:06:34.850 回答