Search code examples
androidxamarin.androidtagsxamarin.formsnfc

NFC with Xamarin.Forms nothing happens


For the first time, I want to implement NFC to cross platform Xamarin.Forms for projects WinPhone and Android.

I was testing on Android my app, but nothing really happens. As a tool, I used Visa Pay Wave card which I tested in program reTag for Android, and it was successful scan. I used solution from a GitHub from this link I had 0 errors, also application "works", but when I add my Visa card to my phone on the back, I get nothing.

My first question is: Which protocol uses Visa card? (TAG_DISCOVERED,TECH_DISCOVERED or NDEF_DISCOVERED). i think that's a reason for being my program in "idle" state.

My second question is: Do you know why I can't get any event from program? (for start to just get UID number..)

Here is my AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
 android:installLocation="auto">
  <uses-sdk android:minSdkVersion="15" />
  <uses-permission android:name="android.permission.NFC" />
  <application android:label="NFCTest002.Android"></application>
  <uses-feature
    android:name="android.hardware.nfc"
    android:required="true" />
 <application>
 <activity
    android:name="MainActivity"
    android:label="@string/app_name" >
  <intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain" />
  </intent-filter>
  <intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED"/>
  </intent-filter>
  <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
      android:resource="@xml/nfc" />
  </activity>
 </application>
</manifest>

My MainActivity.cs:

using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Nfc;
using Android.OS;
using Poz1.NFCForms.Abstract;
using Poz1.NFCForms.Droid;
using System;

namespace NFCTest002.Droid
{
[Activity(Label = "NFCTest002", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[IntentFilter(new[] { NfcAdapter.ActionTechDiscovered })]
[MetaData(NfcAdapter.ActionTechDiscovered, Resource = "@xml/nfc")]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    public NfcAdapter NFCdevice;
    public NfcForms x;
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        global::Xamarin.Forms.Forms.Init(this, bundle);

        NfcManager NfcManager = (NfcManager)Android.App.Application.Context.GetSystemService(Context.NfcService);
        NFCdevice = NfcManager.DefaultAdapter;

        Xamarin.Forms.DependencyService.Register<INfcForms, NfcForms>();
        x = Xamarin.Forms.DependencyService.Get<INfcForms>() as NfcForms;

        LoadApplication(new NFCTest002.App());
    }
    protected override void OnResume()
    {
        base.OnResume();
        if (NFCdevice != null)
        {
            var intent = new Intent(this, GetType()).AddFlags(ActivityFlags.SingleTop);
            NFCdevice.EnableForegroundDispatch
            (
                this,
                PendingIntent.GetActivity(this, 0, intent, 0),
                new[] { new IntentFilter(NfcAdapter.ActionTechDiscovered) },
                new String[][] {new string[] {
                        NFCTechs.Ndef,
                    },
                    new string[] {
                        NFCTechs.MifareClassic,
                    },
                }
            );
        }
    }

    protected override void OnPause()
    {
        base.OnPause();
        NFCdevice.DisableForegroundDispatch(this);
    }

    protected override void OnNewIntent(Intent intent)
    {
        base.OnNewIntent(intent);
        x.OnNewIntent(this, intent);
    }
}
}

I've added to Resource folder and xml folder with nfc.xml file, if it's needed I will post it.

Content Page is the same as it is on GitHub in the link that I provided.


Solution

  • Visa payWave cards are based on EMV standards. In terms of RF communication protocol these cards use ISO/IEC 7816-4 over ISO-DEP (ISO/IEC 14443-4).

    On Android you can pick up these cards using a TECH_DISCOVERED intent filter in combination with an appropriate filter XML file. For these cards the XML file would need to look like this:

    <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
        <tech-list>
            <tech>android.nfc.tech.IsoDep</tech>
        </tech-list>
    </resources>
    

    Similarly, to the above method for the manifest-based intent filter, you could use the following to enable foreground-dispatch based tag discovery:

    NFCdevice.EnableForegroundDispatch(
            this,
            PendingIntent.GetActivity(this, 0, intent, 0),
            new[] { new IntentFilter(NfcAdapter.ActionTechDiscovered) },
            new String[][] {
                new string[] {
                    NFCTechs.IsoDep,
                },
            }
    );
    

    The NDEF_DISCOVERED intent filter won't work with EMV cards since they don't contain any NDEF structured data.