You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin跨平台应用集成NFC遇阻:NfcAdapter获取为Null问题求助

解决Xamarin.Forms跨平台NFC功能中NfcAdapter返回Null的问题

我一眼就看出问题所在了:你的NFCWorker_Droid继承了Activity,但这个类是通过DependencyService实例化的,它并不是Android系统真正托管的活跃Activity实例。当你把this传给NfcAdapter.GetDefaultAdapter()时,这个上下文是无效的,这就是为什么返回Null,哪怕设备本身支持NFC。

下面是具体的修复方案,一步步来:

1. 先保存Android主Activity的静态实例

Xamarin.Forms在Android端运行时,所有界面都依托于主Activity(通常是继承自FormsAppCompatActivity的MainActivity)。我们先在这个主Activity里保存一个静态实例,方便其他类获取有效的上下文:

namespace TestNavigationPage2.Droid
{
    [Activity(Label = "TestNavigationPage2", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        // 保存当前Activity的静态实例
        public static MainActivity Instance { get; private set; }

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Instance = this; // 初始化静态实例
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
        }

        // 处理NFC标签检测后的意图回调
        protected override void OnNewIntent(Intent intent)
        {
            base.OnNewIntent(intent);
            if (NfcAdapter.ActionTagDiscovered.Equals(intent.Action))
            {
                var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
                // 通过MessagingCenter把标签数据传递给Forms端
                MessagingCenter.Send<MainActivity, Tag>(this, "NfcTagDetected", tag);
            }
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}

2. 修改NFCWorker_Droid类,使用有效上下文

把NFCWorker_Droid的Activity继承去掉,改用上面保存的MainActivity.Instance作为上下文,这样就能正确获取NfcAdapter了:

[assembly: Xamarin.Forms.Dependency(typeof(NFCWorker_Droid))]
namespace TestNavigationPage2.Droid
{
    public class NFCWorker_Droid : INFCWorker
    {
        public const string ViewApeMimeType = "application/vnd.xamarin.nfcxample";
        public static readonly string NfcAppRecord = "xamarin.nfxample";
        public static readonly string Tag = "NfcXample";
        private bool _inWriteMode;
        private NfcAdapter _nfcAdapter;

        public void EnableWriteMode()
        {
            _inWriteMode = true;
            // 获取当前活跃的主Activity上下文
            var currentActivity = MainActivity.Instance;
            if (currentActivity == null)
            {
                Page4.Instance.GlobalText = "无法获取有效界面上下文";
                return;
            }

            // 用有效上下文获取NFC适配器
            _nfcAdapter = NfcAdapter.GetDefaultAdapter(currentActivity);

            var tagDetected = new IntentFilter(NfcAdapter.ActionTagDiscovered);
            var filters = new[] { tagDetected };

            if (_nfcAdapter == null)
            {
                Page4.Instance.GlobalText = "NFC is not supported on this device.";
            }
            else
            {
                DisplayMessage("NFC is here!", currentActivity);
                // 正确设置前台调度,使用主Activity的PendingIntent
                var intent = new Intent(currentActivity, currentActivity.GetType());
                intent.AddFlags(ActivityFlags.SingleTop);
                var pendingIntent = PendingIntent.GetActivity(currentActivity, 0, intent, PendingIntentFlags.UpdateCurrent);
                _nfcAdapter.EnableForegroundDispatch(currentActivity, pendingIntent, filters, null);
            }
        }

        // 辅助方法:用Activity上下文显示Toast
        private void DisplayMessage(string message, Activity activity)
        {
            Toast.MakeText(activity, message, ToastLength.Short).Show();
        }

        // 记得添加DisableWriteMode方法,在不需要时关闭前台调度
        public void DisableWriteMode()
        {
            var currentActivity = MainActivity.Instance;
            if (_nfcAdapter != null && currentActivity != null)
            {
                _nfcAdapter.DisableForegroundDispatch(currentActivity);
                _inWriteMode = false;
            }
        }
    }
}

3. 在Forms端接收NFC标签数据

在你的Page4里订阅MessagingCenter的消息,就能获取到Android端传递过来的NFC标签数据了:

namespace TestNavigationPage2
{
    public partial class Page4 : ContentPage
    {
        public static Page4 Instance { get; private set; }
        public string GlobalText { 
            get => lblStatus.Text; 
            set => lblStatus.Text = value; 
        }

        public Page4()
        {
            InitializeComponent();
            Instance = this;
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            // 订阅NFC标签检测消息
            MessagingCenter.Subscribe<MainActivity, Tag>(this, "NfcTagDetected", (sender, tag) =>
            {
                GlobalText = "检测到NFC标签!";
                // 这里可以添加读取标签数据的逻辑
            });
            // 开启NFC写入模式
            DependencyService.Get<INFCWorker>().EnableWriteMode();
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            // 取消订阅并关闭NFC模式
            MessagingCenter.Unsubscribe<MainActivity, Tag>(this, "NfcTagDetected");
            DependencyService.Get<INFCWorker>().DisableWriteMode();
        }
    }
}

4. 最后检查AndroidManifest配置

确保你的Android项目的AndroidManifest.xml里添加了NFC相关权限和特性:

<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="false" />

核心逻辑就是:NfcAdapter必须使用Android系统托管的、当前活跃的Activity上下文,而不是DependencyService创建的空Activity实例。通过保存主Activity的静态实例,就能解决上下文无效的问题了。

内容的提问来源于stack exchange,提问作者StriBog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:57:26