user8334240
user8334240

Reputation:

Read NFC tag from Xamarin

I'm new to Xamarin cross-platform app development, and I'm trying to implement on Android version of my app an external NFC tag reading.

When a tag is scanned, I would like my application to open and read the text inside the tag and finally perform some specific actions based on what was read.

I've this implementation on MainActivity.cs, but it doesn't work because it seems that I can't get the intent:

using Android.Content;
using System;
using System.Text;
using System.Diagnostics;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Xamarin.Forms;
using Android.Content.Res;
using FFImageLoading.Forms.Platform;
using Plugin.Permissions;
using Plugin.Permissions.Abstractions;
using Plugin.CurrentActivity;
using Android.Nfc;
using Android.Nfc.Tech;
using Poz1.NFCForms.Abstract;
using Poz1.NFCForms.Droid;

namespace Kibelis.Droid
{
    [Activity(Label = "Kibelis", Icon = "@drawable/icon", Theme = "@style/MainTheme", LaunchMode = LaunchMode.SingleTop, MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {

        private NfcAdapter _nfcAdapter;


        public object NFCUtil { get; private set; }


        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
            CachedImageRenderer.Init(true);
            base.OnCreate(savedInstanceState);
            CrossCurrentActivity.Current.Init(this, savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);


            _nfcAdapter = NfcAdapter.GetDefaultAdapter(this);
            System.Diagnostics.Debug.WriteLine("CREATE");


            // is attached.
            LoadApplication(new App());
        }

        protected override void OnResume()
        {
            base.OnResume();

            if (_nfcAdapter == null)
            {
                System.Diagnostics.Debug.WriteLine("NFC UNAVIABLE");
            }
            else
            {
                var tagDetected = new IntentFilter(NfcAdapter.ActionNdefDiscovered);
                var filters = new[] { tagDetected };

                var intent = new Intent(this, this.GetType()).AddFlags(ActivityFlags.SingleTop);

                var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);

                _nfcAdapter.EnableForegroundDispatch(this, pendingIntent, filters, null);

                System.Diagnostics.Debug.WriteLine("FOREGRAUND DISPATCH");
            }
        }


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

        protected override void OnNewIntent(Intent intent)
        {
            base.OnNewIntent(intent);

            System.Diagnostics.Debug.WriteLine("NEW INTENT");

            if (intent.Extras.IsEmpty)
            {
                System.Diagnostics.Debug.WriteLine("empty");
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Not empty");
            }

            //For start reading
            if (intent.Action == NfcAdapter.ActionTagDiscovered || intent.Action == NfcAdapter.ActionNdefDiscovered || intent.Action == NfcAdapter.ActionAdapterStateChanged
                || intent.Action == NfcAdapter.ActionTransactionDetected || intent.Action == NfcAdapter.ExtraNdefMessages || intent.Action == NfcAdapter.ExtraNdefMessages)
            {
                System.Diagnostics.Debug.WriteLine("DISCOVERD");
                var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
                if (tag != null)
                {
                    System.Diagnostics.Debug.WriteLine("TAG");
                    // First get all the NdefMessage
                    var rawMessages = intent.GetParcelableArrayExtra(NfcAdapter.ExtraNdefMessages);
                    if (rawMessages != null)
                    {
                        var msg = (NdefMessage)rawMessages[0];
                        System.Diagnostics.Debug.WriteLine("MESSAGE");
                        // Get NdefRecord which contains the actual data
                        var record = msg.GetRecords()[0];
                        if (record != null)
                        {
                            if (record.Tnf == NdefRecord.TnfWellKnown)
                            { 
                                // Get the transfered data
                                var data = Encoding.ASCII.GetString(record.GetPayload());
                                System.Diagnostics.Debug.WriteLine("RECORD");
                            }
                        }
                    }
                }
            }
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
        {
            PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}

Can you help me?

Upvotes: 3

Views: 6830

Answers (1)

Michael Roland
Michael Roland

Reputation: 40831

You are registering the foreground dispatch for the ActionNdefDiscovered intent. However, this intent filter also requires a specific data type (to be present on the tag and to be registered for the intent). If that's what you want, you need to add that data type (MIME type or URI) to the intent filter (variable tagDetected).

If, instead, you want to just listen for all tags, you want to use the ActionTagDiscovered intent instead. In fact, you can simply skip the intnent filter all together from the call to EnableForegroundDispatch:

_nfcAdapter.EnableForegroundDispatch(this, pendingIntent, null, null);

Upvotes: 2

Related Questions