It is possible to instantiate a mock tag using reflection (note that this is not part of the public Android SDK, so it may not work for future versions of Android).
Get createMockTag() method, although reflection:
Class tagClass = Tag.class; Method createMockTagMethod = tagClass.getMethod("createMockTag", byte[].class, int[].class, Bundle[].class);
Define some constants for preparing the mock tag instance:
final int TECH_NFC_A = 1; final String EXTRA_NFC_A_SAK = "sak"; // short (SAK byte value) final String EXTRA_NFC_A_ATQA = "atqa"; // byte[2] (ATQA value) final int TECH_NFC_B = 2; final String EXTRA_NFC_B_APPDATA = "appdata"; // byte[] (Application Data bytes from ATQB/SENSB_RES) final String EXTRA_NFC_B_PROTINFO = "protinfo"; // byte[] (Protocol Info bytes from ATQB/SENSB_RES) final int TECH_ISO_DEP = 3; final String EXTRA_ISO_DEP_HI_LAYER_RESP = "hiresp"; // byte[] (null for NfcA) final String EXTRA_ISO_DEP_HIST_BYTES = "histbytes"; // byte[] (null for NfcB) final int TECH_NFC_F = 4; final String EXTRA_NFC_F_SC = "systemcode"; // byte[] (system code) final String EXTRA_NFC_F_PMM = "pmm"; // byte[] (manufacturer bytes) final int TECH_NFC_V = 5; final String EXTRA_NFC_V_RESP_FLAGS = "respflags"; // byte (Response Flag) final String EXTRA_NFC_V_DSFID = "dsfid"; // byte (DSF ID) final int TECH_NDEF = 6; final String EXTRA_NDEF_MSG = "ndefmsg"; // NdefMessage (Parcelable) final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength"; // int (result for getMaxSize()) final String EXTRA_NDEF_CARDSTATE = "ndefcardstate"; // int (1: read-only, 2: read/write, 3: unknown) final String EXTRA_NDEF_TYPE = "ndeftype"; // int (1: T1T, 2: T2T, 3: T3T, 4: T4T, 101: MF Classic, 102: ICODE) final int TECH_NDEF_FORMATABLE = 7; final int TECH_MIFARE_CLASSIC = 8; final int TECH_MIFARE_ULTRALIGHT = 9; final String EXTRA_MIFARE_ULTRALIGHT_IS_UL_C = "isulc"; // boolean (true: Ultralight C) final int TECH_NFC_BARCODE = 10; final String EXTRA_NFC_BARCODE_BARCODE_TYPE = "barcodetype"; // int (1: Kovio/ThinFilm)
Create a technical add-on package for your tag type. For example, for an NFC-A tag with an NDEF message:
Bundle nfcaBundle = new Bundle(); nfcaBundle.putByteArray(EXTRA_NFC_A_ATQA, new byte[]{ (byte)0x44, (byte)0x00 }); //ATQA for Type 2 tag nfcaBundle.putShort(EXTRA_NFC_A_SAK , (short)0x00); //SAK for Type 2 tag Bundle ndefBundle = new Bundle(); ndefBundle.putInt(EXTRA_NDEF_MAXLENGTH, 48); // maximum message length: 48 bytes ndefBundle.putInt(EXTRA_NDEF_CARDSTATE, 1); // read-only ndefBundle.putInt(EXTRA_NDEF_TYPE, 2); // Type 2 tag NdefMessage myNdefMessage = ...; // create an NDEF message ndefBundle.putParcelable(EXTRA_NDEF_MSG, myNdefMessage); // add an NDEF message
Prepare a collision avoidance identifier / UID for your tag (see Tag.getId() method). For instance. 7-byte UID for Type 2 tag:
byte[] tagId = new byte[] { (byte)0x3F, (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, (byte)0x90, (byte)0xAB };
Then you can create an instance of the mock tag by calling the createMockTag() method
Tag mockTag = (Tag)createMockTagMethod.invoke(null, tagId, // tag UID/anti-collision identifier (see Tag.getId() method) new int[] { TECH_NFC_A, TECH_NDEF }, // tech-list new Bundle[] { nfcaBundle, ndefBundle }); // array of tech-extra bundles, each entry maps to an entry in the tech-list
Once you have created this mock tag object, you can send it as part of your NFC discovery intent. For instance. for the purpose of TECH_DISCOVERED :
Intent techIntent = new Intent(NfcAdapter.ACTION_TECH_DISCOVERED); techIntent.putExtra(NfcAdapter.EXTRA_ID, tagId); techIntent.putExtra(NfcAdapter.EXTRA_TAG, mockTag); techIntent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[]{ myNdefMessage });
You can then submit this intention to your activity:
techIntent.setComponent(...);
The receiver can even use the mock tag object to retrieve instances of technology classes. However, any method that requires I / O will fail.
source share