广播接收器无法接收广播。

9
我的BroadcastReceiver没有接收到任何信息。很可能是我的设置出了问题,因为我在这方面找不到任何好的例子。 我需要让我的接收器在MainActivity中接收一些东西,并更改一个视图。 我在Android项目中几乎有相同的代码,在那里它可以工作,但是在Xamarin中似乎实现BroadcastReceivers有点不同(在Android中,我可以像对象一样创建新的BroadcastReceiver,但在Xamarin或C#中,我似乎必须自己创建类,因此不能直接引用视图)。 如果我让它起作用,我也会为每个人发布一个完整的工作示例。
以下是我尝试设置的方式:
[Activity(Label = "GetLocation.Droid", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    Button button;
    protected override void OnCreate(Bundle bundle)
    {
        // ... various OnCreate() code

        LocationBroadcastReciever lbr = new LocationBroadcastReciever();
        RegisterReceiver(lbr, new IntentFilter("test"));

    }

    public void SetButtonText(string text)
    {
        button.Text = text;
    }
}

[BroadcastReceiver]
public class LocationBroadcastReciever : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        /* My program never get this far, so I have not been able
           to confirm if the bellow code works or not (its from
           another example I saw). */
        //EDIT: It does NOT work. See my answer for a working example
        string text = intent.GetStringExtra("title");
        ((MainActivity)context).SetButtonText(text);
        InvokeAbortBroadcast();
    }
}

在我的IntentService中,我有这个方法实际运行,但从未到达我的接收器。

    private void SendBroadcast(double lat, double lng, string activity)
    {
        Intent intent = new Intent("test");
        intent.PutExtra("title", "Updated");
        LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
    }

这段代码与我在工作中使用的Android代码基本相同(只是微调了BroadcastReceiver并进行了一些小的调整以使其编译)。

有谁能看出问题在哪里吗?

编辑 最终,我让整个事情都正常工作了。您可以查看我的答案以获取完整而清晰的示例。

3个回答

8

本地

您将接收器注册为全局的,但通过LocalBroadcastManager发送意图。如果要使用此管理器,应像这样注册接收器:

LocalBroadcastManager.GetInstance(this).RegisterReceiver(lbr, filter);

您可以在此处了解更多关于LocalBroadcastManager的信息


全局广播

或者,如果您想使用全局广播,您应该按类型创建意图:

var intent = new Intent(this, typeof(LocationBroadcastReciever));

并通过Android Context(在您的服务中)发送它:

this.SendBroadcast(intent);

另外,您也可以使用意图(intent)和操作(action),但这需要在接收器上添加IntentFilter属性:

[IntentFilter(new []{ "test" })]
[BroadcastReceiver]
public class LocationBroadcastReciever : BroadcastReceiver { ... }


谢谢!我之前不知道局部变量和全局变量的区别,也没有在BroadcastReceiver上添加IntentFilter,正如两个答案所建议的那样。 - mathkid91
@mathkid91,你可能会发现这篇文章很有趣:http://codetheory.in/android-broadcast-receivers/ - Kirill

2

有几件事情:

首先,您需要在接收器上使用[IntentFilter]。所以它应该是这样的....

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new [] { "test" })]
public class LocationBroadcastReciever : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        /* My program never get this far, so I have not been able
           to confirm if the bellow code works or not (its from
           another example I saw). */
        string text = intent.GetStringExtra("title");
        ((MainActivity)context).SetButtonText(text);
        InvokeAbortBroadcast();
    }
}

这应该能解决你的问题。

其次,你需要在OnResume中注册接收器,并在OnPause中注销接收器。

[Activity(Label = "GetLocation.Droid", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    LocationBroadcastReciever _lbr;
    Button button;

    protected override void OnCreate(Bundle bundle)
    {
        // ... various OnCreate() code
    }

    protected override void OnResume()
    {
        base.OnResume();
        _lbr = new LocationBroadcastReciever();
        RegisterReceiver(lbr, new IntentFilter("test"));
    }

    protected override void OnPause()
    {
        UnregisterReceiver(_lbr);
        base.OnPause();
    }

    public void SetButtonText(string text)
    {
        button.Text = text;
    }
}

注意:这些更改是我在一个可用的广播接收器代码和你的代码之间看到的区别。我的更改是否必要,我并不完全确定。

2
为了将来的搜索结果,这里提供一个干净的示例代码,其中包含一个工作的广播接收器。
// ** MainActivity
namespace GetLocation.Droid
{
    [Activity(Label = "GetLocation.Droid", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        //I initialize my view(s) here to access them from outside of OnCreate().
        Button button;
        //I found this in an Android BroadcastReceiver example of how to access the MainActivity from the BroadcastReceiver.
        private static MainActivity ins;
        public static MainActivity getInstace()
        {
            return ins;
        }
        protected override void OnCreate(Bundle bundle)
        {

            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);
            button = FindViewById<Button>(Resource.Id.myButton);
            ins = this;

            button.Click += delegate
            {
                Intent intent = new Intent(this, typeof(MyIntentService));
                StartService(intent);
            };

            LocationBroadcastReciever lbr = new LocationBroadcastReciever();
            LocalBroadcastManager.GetInstance(this).RegisterReceiver(lbr, new IntentFilter("test"));

        }

        public void SetButtonText(string text)
        {
            button.Text = text;
        }
    }

    [BroadcastReceiver]
    [IntentFilter(new[] { "test" })]
    public class LocationBroadcastReciever : BroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            string text = intent.GetStringExtra("title");
            MainActivity.getInstace().SetButtonText(text);
        }
    }
}

在我的IntentService中

namespace GetLocation.Droid
{
    [Service]
    [IntentFilter(new String[] { "com.mytos.MyIntentService" })]
    public class MyIntentService : IntentService
    {

        protected override void OnHandleIntent(Intent intent)
        {
            SendBroadcast("My message");
        }

        private void SendBroadcast(string message)
        {
            //Here you can of course send whatever variable you want. Mine is a string
            Intent intent = new Intent("test");
            intent.PutExtra("title", message);
            LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
        }
    }
}

如果您正在使用LocalBroadcastManager,则可以从接收器中删除BroadcastReceiverIntentFilter属性。它们仅在全局广播中才是必需的。 - Kirill
@g4s8 你确定吗?我认为它们是必要的,你有任何例子吗? - CDrosos
@CDrosos,是的,正如您在这里https://developer.xamarin.com/api/type/Android.App.IntentFilterAttribute/所看到的那样,“IntentFilterAttribute”会在“AndroidManifest.xml”中生成“intent-filter”元素。但是,“LocalBroadcastManager”不需要清单的意图过滤器,而是需要将过滤器作为参数传递给“registerReceiver(receiver,intentFilter)”。https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter) - Kirill
所以我们不应该在服务上放置像这样的东西 [IntentFilter(new String[] {"com.mytos.MyIntentService"})]? - CDrosos
@CDrosos,不,我说的是[IntentFilter]只在BroadcastReceiver上是多余的。服务的[IntentFilter]可能是必需的 - 在这个例子中它是无关紧要的,服务过滤器不依赖于广播。这个链接可能会对你有所帮助:https://developer.xamarin.com/guides/android/application_fundamentals/services/part_1_-_started_services/#Starting_a_Service_With_an_Intent_Filter - Kirill

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