如何将参数传递给BroadcastReceiver的子类?

13
我成功让我的应用程序识别了耳机按钮的按下操作,但其中一个按钮需要调用MyCustomActivity中的一个方法。问题在于onReceive的第一个参数是Context类型,不能转换为Activity类型,并且使用MyCustomActivity的内部类在Android 4.1中无法工作,除非它是静态的(这有同样无法访问MyCustomActivity方法的问题)。
所以,唯一留给我的选择(为了支持2.x和4.1)就是将活动作为参数传递给RemoteControlReceiver
但是,当实例化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的数据成员。

1
您可以在Activity的onResume/onCreate中创建和注册BroadcastReceiver,在onPause/onStop中取消注册。这样,当前Activity就可以管理其生命周期,而接收器应该能够与其容器(Activity)通信。 - Sudar Nimalan
2
@SudarNimalan 我已经尝试过了。这个仅适用于Android 2.x。在4.1中不起作用。我需要想办法让RemoteControlReceiver(而不是BroadcastReceiver!)知道MyCustomActivity的存在。谢谢。 - an00b
这是一个棘手的问题,但是这里有一个想法:你能检查在 onReceive 中传递的 Intent 上的 Extra 吗?或者使用这个 GlobalVariable 技巧? - Android Eve
看看这个答案,也许可以帮到你。https://dev59.com/v27Xa4cB1Zd3GeqPut_R#15060082 - Jignesh Ansodariya
1个回答

7

registerMediaButtonEventReceiver需要在应用程序清单中声明BroadcastReceiver。这意味着接收器必须是独立的类,即它不知道您当前的活动或服务。

为了将此消息传递到您的活动或服务,您有多种选择:

  • Use a static global for the activity or service so the receiver can forward the message to it. This is generally not a good idea as it leads to leaks and isn't very adaptable when you want to change the code later. Statics are generally to be avoided.

  • Re-broadcast the message to a specific class, which happens to be an inner class of the activity or service you want to invoke. E.g. in the BroadcastReceiver for 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() {
        }
    }
  • 与上述方法类似,它不必一定是广播,可以根据您的用例将Intent传递给活动。如果要使用此方法而不是使用sendBroadcast,则应使用startActivity(或startService,如果您正在使用服务)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接