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
相关产品推荐
相关产品推荐

