如何将 BroadcastReceiver 中的 EventListener 与 Xamarin.Android 中的自定义 Action 结合使用?

How do I use EventListener in BroadcastReceiver with custom Action in Xamarin.Android?

我正在尝试在 BroadcastReceiver 收到自定义消息时启动 TickEvent

例如,

intent.Action == Intent.ActionTimeTick(而不是 GRID_STARTED)时,它工作正常。 我注释掉了工作代码,所以你可以轻松地进行实验。

似乎我遗漏了关于操作的重要信息。你能帮帮我吗?

using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Support.V7.App;
using Android.Util;
using Android.Views;
using Android.Widget;

namespace TestApp
{
    [Activity(Label = "BroadcastUpdateFormExample", MainLauncher = true)]
    public class MainActivity : Activity
    {
        int count = 1;
        TextView txtNote;
        BroadcastMessageCatcher catcher;
        static readonly string TAG = "MainActivity";

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);

            txtNote = FindViewById<TextView>(Resource.Id.textView1);

            Button button = FindViewById<Button>(Resource.Id.button1);

            button.Click += delegate
            {
                button.Text = string.Format("{0} clicks!", count++);
                BroadcastStarted();
            };

            catcher = new BroadcastMessageCatcher();
            catcher.TickEvent += delegate
            {
                Log.Debug(TAG, "before listener");
                txtNote.Text = "Tick";
                Log.Debug(TAG, "after listener");
            };
        }

        protected override void OnResume()
        {
            base.OnResume();
            // RegisterReceiver (catcher, new IntentFilter (Intent.ActionTimeTick));
            IntentFilter filter = new IntentFilter(BroadcastMessageCatcher.GRID_STARTED);
            RegisterReceiver(catcher, filter);
        }

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

        private void BroadcastStarted()
        {
            // Broadcast message to the view
            // Source: https://forums.xamarin.com/discussion/1147/updating-activity-using-a-background-service
            Intent BroadcastIntent = new Intent(this, typeof(BroadcastMessageCatcher));
            BroadcastIntent.SetAction(BroadcastMessageCatcher.GRID_STARTED);
            //BroadcastIntent.AddCategory(Intent.CategoryDefault);
            Log.Debug(TAG, "Broadcast started");
            SendBroadcast(BroadcastIntent);
        }
    }



    [BroadcastReceiver]
    public class BroadcastMessageCatcher : BroadcastReceiver
    {
        static readonly string TAG = "MainActivity";
        public static readonly string GRID_STARTED = "GRID_STARTED";
        public override void OnReceive(Context context, Intent intent)
        {
            // if (intent.Action == Intent.ActionTimeTick) 
            if (intent.Action == GRID_STARTED)
            {
                Log.Debug(TAG, "before event");
                // Here I get the error:
                TickEvent();
                Log.Debug(TAG, "after event");
            }
        }

        public delegate void TickEventHandler();
        public event TickEventHandler TickEvent;
    }
}

我在 BroadcastMessageCatcher 内的 TickEvent(); 上收到 'System.NullReferenceException: 'Object reference not set to an instance of an object.'' 错误(在注释中标记)。

我理解错了。主要是因为我不知道启动活动的意图和启动动作的意图是两个完全不同的东西。

所以如果它对任何人有帮助,我 post 工作代码。

主要清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
          android:versionCode="1" 
          android:versionName="1.0" 
          package="com.companyname.testapp">
  <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
  <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
    <activity
     android:name=".MainActivity">
     <intent-filter>
         <action android:name="com.companyname.testapp.MY_CUSTOM_ACTION"></action>
         <category android:name="android.intent.category.DEFAULT"></category>
     </intent-filter>
    </activity>
  </application>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

Activity:

using Android.App;
using Android.Content;
using Android.OS;
using Android.Util;
using Android.Widget;

namespace TestApp
{
    [Activity(Label = "BroadcastUpdateFormExample", MainLauncher = true)]
    public class MainActivity : Activity
    {
        int count = 1;
        TextView txtNote;
        BroadcastMessageCatcher catcher;
        static readonly string TAG = "FCMActivity";

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);

            txtNote = FindViewById<TextView>(Resource.Id.textView1);

            Button button = FindViewById<Button>(Resource.Id.button1);

            button.Click += delegate
            {
                button.Text = string.Format("{0} clicks!", count++);
                BroadcastStarted();
            };

            catcher = new BroadcastMessageCatcher();
            catcher.TickEvent += delegate
            {
                Log.Debug(TAG, "before listener");
                txtNote.Text = "Tick";
                Log.Debug(TAG, "after listener");
            };
        }

        protected override void OnResume()
        {
            base.OnResume();
            IntentFilter filter = new IntentFilter("com.companyname.testapp.MY_CUSTOM_ACTION");
            RegisterReceiver(catcher, filter);
        }

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

        private void BroadcastStarted()
        {
            // Broadcast message to the view

            Intent BroadcastIntent = new Intent();
            BroadcastIntent.SetAction("com.companyname.testapp.MY_CUSTOM_ACTION");
            //BroadcastIntent.AddCategory(Intent.CategoryDefault);
            Log.Debug(TAG, "Broadcast started");
            SendBroadcast(BroadcastIntent);
        }
    }



    [BroadcastReceiver]
    public class BroadcastMessageCatcher : BroadcastReceiver
    {
        private readonly string TAG = "MainActivity";

        public override void OnReceive(Context context, Intent intent)
        {
            if (intent.Action == "com.companyname.testapp.MY_CUSTOM_ACTION")
            {
                Log.Debug(TAG, "before event");
                TickEvent();
                Log.Debug(TAG, "after event");
            }
        }

        public delegate void TickEventHandler();
        public event TickEventHandler TickEvent;
    }
}