NFC Smartposter to Dial a number - android

i want to create a NFC SmartPoster which dial a number with Action Record type "act".
Can anyone tell how to get Action Record type "act" in android from packet and check whether packet contains Action Record type "act" or not.
Below is packet i have created.
/**
* Smart Poster containing a Telephone number and Action record type.
*/
public static final byte[] SMART_POSTER_Dial_Number =
new byte[] {
// SP type record
(byte) 0xd1, (byte) 0x02, (byte) 0x26, (byte) 0x53, (byte) 0x70,
// Call type record
(byte) 0xd1, (byte) 0x01, (byte) 0x0e, (byte) 0x55, (byte) 0x05, (byte) 0x2b,
(byte) 0x39, (byte) 0x31, (byte) 0x38, (byte) 0x38, (byte) 0x37, (byte) 0x32,
(byte) 0x37, (byte) 0x34, (byte) 0x33, (byte) 0x39, (byte) 0x33, (byte) 0x39,
// Action type record
(byte) 0x11, (byte) 0x03, (byte) 0x01, (byte) 0x61, (byte) 0x63, (byte) 0x74,
(byte) 0x00,
// Text type record with 'T'
(byte) 0x91, (byte) 0x01, (byte) 0x09, (byte) 0x54, (byte) 0x02, (byte) 'C',
(byte) 'a', (byte) 'l', (byte) 'l', (byte) 'i', (byte) 'n', (byte) 'g', (byte) '.'
};
Please help..

When you receive an NDEF message in your Activity via an ACTION_NDEF_DISCOVERED intent, you can parse and check the contents for a SmartPoster record with an embedded 'act' record as follows:
Intent intent = getIntent();
final Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage mesg = (NdefMessage) rawMsgs[0]; // in theory there can be more messages
// let's inspect the first record only
NdefRecord[] record = mesg.getRecords()[0];
byte[] type = record.getType();
// check if it is a SmartPoster
byte[] smartPoster = { 'S', 'p'};
if (Arrays.equals(smartPoster, type) {
byte[] payload = record.getPayload();
// try to parse the payload as NDEF message
NdefMessage n;
try {
n = new NdefMessage(payload);
} catch (FormatException e) {
return; // not an NDEF message, we're done
}
// try to find the 'act' record
NdefRecord[] recs = n.getRecords();
byte[] act = { 'a', 'c', 't' };
for (NdefRecord r : recs) {
if (Arrays.equals(act, r.getType()) {
... // found it; do your thing!
return;
}
}
}
return; // nothing found
BTW: You will find that there are a couple of format errors in the example message in your question: the first byte of the Uri record should be 0x81 and the first byte of the Text record should be 0x51.

Related

How to define an APDU for STORE DATA for Host Card Emulation?

I have been looking in the Global Platform Spec on how to define an APDU for my app which will use Host Card Emulation (HCE). My app is supposed to have one phone behaving like an NFC tag through HCE and another phone acting as the NFC reader. The arbitrary data that i am trying to transfer between the phones is just a simple string containing an ID number, but I'm not really sure how to apply it in the code. I have looked at what the different byte commands mean but I'm really not sure how to apply it.
I think I need to use the STORE DATA command but I'm not sure how to intuitively do it and don't really understand. I am currently looking at the HCE side rather than the reader side.
This is my code so far for the HCE side
public class SecondaryActivity extends HostApduService {
#Override
public void onDeactivated(int reason) {
}
#Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
String inboundApduDescription;
byte[] responseApdu;
if (Arrays.equals(AID_SELECT_APDU, commandApdu)) {
inboundApduDescription = "Application selected";
Log.i("HCEDEMO", inboundApduDescription);
byte[] answer = new byte[2];
answer[0] = (byte) 0x90;
answer[1] = (byte) 0x00;
responseApdu = answer;
return responseApdu;
}
return commandApdu;
}
private static final byte[] AID_SELECT_APDU = {
(byte) 0x00,
(byte) 0xA4,
(byte) 0x04,
(byte) 0x00,
(byte) 0x07,
(byte) 0xF0, (byte) 0x39, (byte) 0x41, (byte) 0x48, (byte) 0x14, (byte) 0x81, (byte) 0x00,
(byte) 0x00
};
private static final byte[] STORE_DATA = {
(byte) 0x00,
(byte) 0xA4,
(byte) 0x04,
(byte) 0xA5, // forproprietary data according to the spec
(byte) 0xE2,
(byte) 0x66, (byte) 0x39, (byte) 0x41, (byte) 0x48, (byte) 0x14, (byte) 0x81, (byte) 0x00,
(byte) 0x00
};
private static final byte[] INSTALL = {
(byte) 0x00,
(byte) 0x00,
};
}
How do I send the data from the HCE phone to the reader phone?
What am I missing?
What needs to be done?
You can define virtually any APDU command for HCE. Only the initial SELECT (by AID) command is required. After that, you can create your own command set (or try to follow ISO/IEC 7816-4 commands) as long as you obey the rules of ISO/IEC 7816 for command/response APDU structure, and stick to valid CLA, INS, and status word values.
Since you only want to transfer an ID, you could send this ID directly in response to the SELECT command:
private static final String ID = "1234567890"
#Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
byte[] responseApdu = new byte[] { (byte)0x6F, (byte)0x00 };
if ((commandApdu != null) && (commandApdu.length >= 4)) {
if ((commandApdu[0] == (byte)0x00) && (commandApdu[1] == (byte)0xA4) && (commandApdu[2] == (byte)0x04) && (commandApdu[3] == (byte)0x00)) {
Log.i("HCEDEMO", "Application selected");
byte[] id = ID.getBytes(Charset.forName("UTF-8"));
responseApdu = new byte[id.length + 2];
System.arraycopy(id, 0, responseApdu, 0, id.length);
responseApdu[id.length] = (byte)0x90;
responseApdu[id.length + 1] = (byte)0x00;
}
}
return responseApdu;
}

ACR122 - Android / How to get the UID's [duplicate]

I try to integrate an ACR122 to my android app. I'm using the ANDROID Library (http://www.acs.com.hk/en/products/3/acr122u-usb-nfc-reader/) available from ACS.
Everything work, I can detect the presence of a card but I want to extract the UID/ID of the card. Someone know the function to do that?
Do you have an example of this type of integration?
In case of Mifare card you need to send this APDU byte array to the card: (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 . I'm not sure about ACR122 API but probably you need to wrap this APDU into specific API method like transmit()
UPDATE
Sample code:
byte[] command = new byte[] { (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
byte[] response = new byte[300];
int responseLength;
responseLength = reader.transmit(slotNum, command, command.length, response,response.length);
System.out.println(new String(response));
Reader is com.acs.smartcard.Reader object
and slotNum is a the slot number. I’m not sure how to find it because I don’t have ACR to test. But if you told that you was able to establish basic communication with reader probably you know slotNum.
In order to prevent this error when trying to read the UID:
com.acs.smartcard.InvalidDeviceStateException: The current state is not equal to specific.
This should rather be:
int slotNum = 0;
byte[] payload = new byte[] { (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
byte[] response = new byte[7]; // 7 bytes + 90 00 (9 bytes)
try {
reader.power(slotNum, Reader.CARD_WARM_RESET);
reader.setProtocol(slotNum, Reader.PROTOCOL_T0 | Reader.PROTOCOL_T1);
reader.transmit(slotNum, payload, payload.length, response, response.length);
logBuffer(response, response.length);
} catch (ReaderException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}

What is / how do I find the universal ibeacon identifier?

I am trying to write an android application to interface with iBeacons, but I need to find the start of the UUID / major / minor characteristics in the byte array. Through look at a couple of resources including this question, it seems like ALL iBeacons transmit some pattern in the byte array that is the same that identifies them as iBeacons.
I asked another question recently and got a useful answer, link here but 1) I haven't been able to test it's functionality (waiting on my device) and 2) I want to know how it is working.
So my questions: What is that pattern? Can I find it just by searching that array for the pattern? And is the UUID / Major / Minor always a predefined number of spots in the array from that identifying pattern?
Thanks!
So after looking around on a few different sites, I have found that 3 people list their patterns as
02 01 06 1A FF 4C 00 02 15
or
02 01 1A 1A FF 4C 00 02 15
which isn't super helpful, since the 4C 00 appears to just be the Apple identifier, which I'm assuming could switch based on the manufacturer (Estimote, GE, Apple, whatever). However, it appears that the
02 15
is static, so I'm using that. My solution for finding it basically is just searching the byte array that I get for the first occurrence of that sequence of 2 bytes, and starting right after that I grab the next 16 as the UUID, the next 2 after that as the Major, and the next 2 after that as the Minor. So to clarify with code:
//adPacket is an array I created to represent an iBeacon ad for testing
byte[] adPacket = {(byte) 0xd6, (byte) 0xbe, (byte) 0x89, (byte) 0x8e, 0x40, 0x24, 0x05, (byte) 0xa2,
0x17, 0x6e, 0x3d, 0x71, 0x02, 0x01, 0x06, 0x1A, (byte) 0xFF, 0x4C, 0x00, 0x02, 0x15, (byte) 0xe2,
(byte) 0xc5, 0x6d, (byte) 0xb5, (byte) 0xdf, (byte) 0xfb, 0x48, (byte) 0xd2, (byte) 0xb0, 0x60, (byte) 0xd0,
(byte) 0xf5, (byte) 0xa7, 0x10, (byte) 0x96, (byte) 0xe0, 0x00, 0x00, 0x00, 0x00, (byte) 0xc5, 0x52, (byte) 0xab, (byte) 0x8d, 0x38, (byte) 0xa5};
byte[] pattern = {0x02, 0x15};
int startIndex = findAdPacketEnd(adPacket, pattern) + 1;
if(startIndex == 0){ System.out.println("Pattern not found"); return;}
int endIndex = startIndex + 21;
ArrayList<Byte> tempArray = new ArrayList<Byte>();
for(int i = startIndex; i<endIndex; i++){
tempArray.add(adPacket[i]);
}
byte[] proxUUID = new byte[16];
for(int i = 0; i<16; i++){
proxUUID[i] = tempArray.get(i);
}
byte[] major = new byte[2];
major[0] = tempArray.get(16);
major[1] = tempArray.get(17);
byte[] minor = new byte[2];
minor[0] = tempArray.get(18);
minor[1] = tempArray.get(19);
...
where my findAdPacketEnd function is (not the most efficient but it works):
private static int findAdPacketEnd(byte[] adPacket, byte[] pattern){
//return -1 if pattern is too long
if(adPacket.length < pattern.length)
return -1;
//iterate over adPacket
for(int i = 0; i<adPacket.length - pattern.length; i++){
System.out.println("Searching Ad Packet");
//iterate over pattern
for(int j = 0; j<pattern.length; j++){
//compare wherever you are in the adpacket to the pattern, break if it doesn't match
if(adPacket[i+j] != pattern[j])
break;
// if you get to the end of the pattern and there wasn't a mismatch, return the index
if(j == pattern.length-1)
return i+pattern.length-1;
}
}
//pattern not found
return -1;
}

How to do authentication for MIFARE Ultralight C on Android

I used an android APP (NFC tag info by NXP) to read my MIFARE Ultraglith C tag and it shows the tag has NXP default key "BREAKMEIFYOUCAN!" on page 0x2C to 0x2F. But I was still failing to authenticate this tag use this key.
// NXP default key: BREAKMEIFYOUCAN! (16 bytes)
byte[] mifareULCDefaultKey = { (byte) 0x49, (byte) 0x45,
(byte) 0x4D, (byte) 0x4B, (byte) 0x41, (byte) 0x45,
(byte) 0x52, (byte) 0x42, (byte) 0x21, (byte) 0x4E,
(byte) 0x41, (byte) 0x43, (byte) 0x55, (byte) 0x4F,
(byte) 0x59, (byte) 0x46 };
In details, I got following result:
1st authentication command: 1A00
response of 1st authentication command: AFCCF489BFB7B98605
ek(RndB): CCF489BFB7B98605
IV 1: 0000000000000000
RndB: 6183511C5B7EF046
RndA: 6E262630E299F94F
RndB': 83511C5B7EF04661
RndA || RndB': 6E262630E299F94F83511C5B7EF04661
IV 2: CCF489BFB7B98605
ek(RndA || RndB'): AB7AF6C6E76675F52B9FF40021A8E2D6
2nd authentication command: AFAB7AF6C6E76675F52B9FF40021A8E2D6
But I still got "Transceive failed" IOException after sending 2nd authentication command. I'm sure the tag is still connected before sending 2nd authentication command.
I have cost 8+ hours on this issue, but still cannot move ahead. Anyone can help?
I had the same problem. The problem is that you are using the wrong Diversified Key for Authentication.

Wifi printer not printing the pages android

I have using the following code:
Socket client = new Socket(etIp.getText().toString(), 515);
String printText = "This is a print test from Wifi";
byte[] mybytearray = printText.getBytes();
OutputStream outputStream = client.getOutputStream();
outputStream.write(mybytearray, 0, mybytearray.length); //write file to the output stream byte by byte
outputStream.flush();
outputStream.close();
client.close();
Socket connection opened, and no exception while complete process of write data in output stream. But printer not eject the page.
Please help me what I have did wrong.
I think you need to send few more data for it to eject and let the printer know.
For Epson L355 I am appending a byte array at the end of my string.
byte[] EjectByteArray = {0X00, 0X0D, 0X0C, 0X1B, 0X40, 0X1B, 0X28, 0X52, 0X08, 0X00, 0X00, 0X52, 0X45, 0X4D, 0X4F, 0X54, 0X45, 0X31, 0X4C, 0X44, 0X00, 0X00, 0X1B, 0X00, 0X00, 0X00, 0X1B, 0X40, 0X1B, 0X28, 0X52, 0X08, 0X00, 0X00, 0X52, 0X45, 0X4D, 0X4F, 0X54, 0X45, 0X31, 0X4C, 0X44, 0X00, 0X00, 0X4A, 0X45, 0X01, 0X00, 0X00, 0X1B, 0X00, 0X00, 0X00};
You may need to run a Port sniffer and try to capture the last byte array being passed after a print is finished. It would give you a clue on how you should send an eject command. This is one works on me using port 9100 on Epson L355
outputStream.write(mybytearray, 0, mybytearray.length);
outputStream.write(EjectByteArray, 0, EjectByteArray.length);
outputStream.flush();
outputStream.close();
client.close();
Add \n end of the line.this is work for me
String printText = "Finally its working \n";

Categories

Resources