user4657635
user4657635

Reputation:

How simulate NFC tag (not card) with smartphone on NFC antenna

I use a small NFC antenna, connected on PC with USB interface, and delivering read-data on standard output (like keyboard). So I put a small sticker-tag (MIFARE Ultralight) and I receive tag id on console.
I wish to do the same thing with my smartphone (Samsung S4). For tag emulation, not for card emulation.
How to do that (java, Android Studio) ? I found sample for card emulation, but not for tag.
Do I need first to dump the tag content (NdefMessage and NdefRecord) in order to send back the same content ?
Which java sample is dedicated to this specific behavior ?

I have found a small sample http://www.frugalprototype.com/android-nfc-hce/#comment-22 which seems to work... but not by me !
My NFC antenna triggers "beep", and display random id value on console, but I never enters the processCommandApdu() method. Where is the mistake ?

MainActivity.java:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("MainActivity",">>> onCreate...");
        setContentView(R.layout.activity_main);
    }
}

HceActivity.java:

public class HceService extends HostApduService {
    /*  Il s’agit en réalité ici de la commande SELECT AID + la taille en octet de l’AID + l’AID.
    Dans une application en production, il est préférable de déclarer la commande
    SELECT AID = {0x00, (byte) 0xA4, 0x04,0x00}
    et de déclarer l’AID séparément : AID = {0xF0, 0x46, 0x52, 0x55, 0x47, 0x41, 0x4c}.
    Sans oublier d’ajouter la taille de l’AID à la commande SELECT AID*/
    private static final byte[] SELECT_AID = {0x00,
            (byte) 0xA4, 0x04,0x00,0x07,
            (byte) 0xF0, 0x46, 0x52, 0x55, 0x47, 0x41, 0x4C};
    private static final byte[] MY_UID = {0x01, 0x02, 0x03, 0x04, (byte) 0x90, 0x00};

    private static final byte[] MY_ERROR = {0x6F, 0x00};

    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {

        Log.d("HceService",">>> processCommandApdu...");
        if (Arrays.equals(SELECT_AID, apdu)) {
            return MY_UID;
        } else return MY_ERROR;
    }

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.pdf.cardemulation">

    <!-- Demander la permission la permission à l'utilisateur pour l'utilisation du NFC -->
    <uses-feature
        android:name="android.hardware.nfc.hce"
        android:required="true" />

    <uses-permission
        android:name="android.permission.NFC" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Déclaration de notre service HceService -->
        <service
            android:name=".HceService"
            android:exported="true"
            android:permission="android.permission.BIND_NFC_SERVICE" >
            <intent-filter>
                <action
                    android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
            </intent-filter>
            <!-- Fichier dans lequel est déclaré l’AID. Nous devons créer un dossier xml dans le dossier values
            et créer un fichier apduservice.xml dans lequel nous allons déclarer l’AID de notre application   -->
            <meta-data
                android:name="android.nfc.cardemulation.host_apdu_service"
                android:resource="@xml/apduservice" />
        </service>
    </application>
</manifest>

and finally:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
                   android:description="@string/app_name"
                   android:requireDeviceUnlock="false">
    <aid-group
        android:description="@string/membership_number"
        android:category="other">
        <aid-filter android:name="F046525547414c"/>
    </aid-group>
</host-apdu-service>

Upvotes: 0

Views: 2705

Answers (1)

LaurentY
LaurentY

Reputation: 7653

Tag and card are same thing.

Tag can't send data to a reader (phone device for instance). Reader send APDU commands to a tag. Tag give a response to the command for the reader.

Maybe your Mifare Ultralight is NDEF formatted. NDEF defines the protocol to exchange command and response and how data are stored on tag.

You could reproduce the same with HCE (Host Card Emulation) on Android.

UPDATE

Why you have random UID ? Please have a look at documentation https://developer.android.com/guide/topics/connectivity/nfc/hce.html#ProtocolParams

In the first part of the exchange the HCE device will present its UID; HCE devices should be assumed to have a random UID. This means that on every tap, the UID that is presented to the reader will be a randomly generated UID. Because of this, NFC readers should not depend on the UID of HCE devices as a form of authentication or identification.

Upvotes: 0

Related Questions