How To Mock A Android Nfc Tag Object For Unit Testing
Solution 1:
It's possible to create a mock tag object instance using reflection (note that this is not part of the public Android SDK, so it might fail for future Android versions).
Get the
createMockTag()
method though 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:
finalintTECH_NFC_A=1; finalStringEXTRA_NFC_A_SAK="sak"; // short (SAK byte value)finalStringEXTRA_NFC_A_ATQA="atqa"; // byte[2] (ATQA value)finalintTECH_NFC_B=2; finalStringEXTRA_NFC_B_APPDATA="appdata"; // byte[] (Application Data bytes from ATQB/SENSB_RES)finalStringEXTRA_NFC_B_PROTINFO="protinfo"; // byte[] (Protocol Info bytes from ATQB/SENSB_RES)finalintTECH_ISO_DEP=3; finalStringEXTRA_ISO_DEP_HI_LAYER_RESP="hiresp"; // byte[] (null for NfcA)finalStringEXTRA_ISO_DEP_HIST_BYTES="histbytes"; // byte[] (null for NfcB)finalintTECH_NFC_F=4; finalStringEXTRA_NFC_F_SC="systemcode"; // byte[] (system code)finalStringEXTRA_NFC_F_PMM="pmm"; // byte[] (manufacturer bytes)finalintTECH_NFC_V=5; finalStringEXTRA_NFC_V_RESP_FLAGS="respflags"; // byte (Response Flag)finalStringEXTRA_NFC_V_DSFID="dsfid"; // byte (DSF ID)finalintTECH_NDEF=6; finalStringEXTRA_NDEF_MSG="ndefmsg"; // NdefMessage (Parcelable)finalStringEXTRA_NDEF_MAXLENGTH="ndefmaxlength"; // int (result for getMaxSize())finalStringEXTRA_NDEF_CARDSTATE="ndefcardstate"; // int (1: read-only, 2: read/write, 3: unknown)finalStringEXTRA_NDEF_TYPE="ndeftype"; // int (1: T1T, 2: T2T, 3: T3T, 4: T4T, 101: MF Classic, 102: ICODE)finalintTECH_NDEF_FORMATABLE=7; finalintTECH_MIFARE_CLASSIC=8; finalintTECH_MIFARE_ULTRALIGHT=9; finalStringEXTRA_MIFARE_ULTRALIGHT_IS_UL_C="isulc"; // boolean (true: Ultralight C)finalintTECH_NFC_BARCODE=10; finalStringEXTRA_NFC_BARCODE_BARCODE_TYPE="barcodetype"; // int (1: Kovio/ThinFilm)
Create the tech-extras bundle for your tag type. For instance, for an NFC-A tag with an NDEF message:
BundlenfcaBundle=newBundle(); nfcaBundle.putByteArray(EXTRA_NFC_A_ATQA, newbyte[]{ (byte)0x44, (byte)0x00 }); //ATQA for Type 2 tag nfcaBundle.putShort(EXTRA_NFC_A_SAK , (short)0x00); //SAK for Type 2 tagBundlendefBundle=newBundle(); 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 tagNdefMessagemyNdefMessage= ...; // create an NDEF message ndefBundle.putParcelable(EXTRA_NDEF_MSG, myNdefMessage); // add an NDEF message
Prepare an anti-collision identifier/UID for your tag (see
Tag.getId()
method). E.g. a 7-byte-UID for a Type 2 tag:byte[] tagId = newbyte[] { (byte)0x3F, (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78, (byte)0x90, (byte)0xAB };
Then you can create a mock tag instance by invoking the
createMockTag()
methodTag mockTag = (Tag)createMockTagMethod.invoke(null, tagId, // tag UID/anti-collision identifier (see Tag.getId() method)newint[] { TECH_NFC_A, TECH_NDEF }, // tech-listnew Bundle[] { nfcaBundle, ndefBundle }); // array of tech-extra bundles, each entry maps to an entry in the tech-list
Once you created that mock tag object, you can send it as part of an NFC discovery intent. E.g. for a TECH_DISCOVERED
intent:
IntenttechIntent=newIntent(NfcAdapter.ACTION_TECH_DISCOVERED);
techIntent.putExtra(NfcAdapter.EXTRA_ID, tagId);
techIntent.putExtra(NfcAdapter.EXTRA_TAG, mockTag);
techIntent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, newNdefMessage[]{ myNdefMessage }); // optionally add an NDEF message
You can then send this intent to your activity:
techIntent.setComponent(...); // or equivalent to optionally set an explicit receiverstartActivity(techIntent);
The receiver can even use the mock tag object to retrieve instances of the technology classes. However, any method that requires IO operations will fail.
Solution 2:
I don't think it is possible to mock these intents as these are fired by NFCService and without system permissions it is not possible to fire these intents and currently there is not support in the android framework to mock nfc tags.
Post a Comment for "How To Mock A Android Nfc Tag Object For Unit Testing"