nfc - Android HCE issue -


i'm working on nfc-hce project android. stuck problem app doesn't recognize apdu select query.

i'm using acl122u reader powered chrome-nfc forum type 4 support , apdu_select query goes 00a4040007f039414848483500. checked many time, there can't error in aid. tried change several times, found working app on net working when changed aid in chrome-nfc. guess there manifest problem or service launching problem. appreciate help.

androidmanifest.xml

<service android:name=".myhostapduservice"                   android:exported="true"                  android:permission="android.permission.bind_nfc_service">             <intent-filter>                 <action android:name="android.nfc.cardemulation.action.host_apdu_service"/>             </intent-filter>             <meta-data android:name="android.nfc.cardemulation.host_apdu_service"                        android:resource="@xml/apduservice"/>         </service> 

apduservice.xml

<?xml version="1.0" encoding="utf-8"?> <host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"     android:description="@string/servicedesc"     android:requiredeviceunlock="false">     <aid-group android:description="@string/aiddescription"         android:category="other">          <aid-filter android:name="f0394148484835"/>     </aid-group> </host-apdu-service> 

myhostapduservice.java

public class myhostapduservice extends hostapduservice {      private static final string tag = "myhostapduservice";       //     private static final byte[] apdu_select = {             (byte)0x00, // cla  - class - class of instruction             (byte)0xa4, // ins  - instruction - instruction code             (byte)0x04, // p1   - parameter 1 - instruction parameter 1             (byte)0x00, // p2   - parameter 2 - instruction parameter 2             (byte)0x07, // lc field - number of bytes present in data field of command             (byte)0xf0, (byte)0x39, (byte)0x41, (byte)0x48, (byte)0x48, (byte)0x48, (byte)0x35, // ndef tag application name             (byte)0x00  // le field - maximum number of bytes expected in data field of response command     };      private static final byte[] capability_container = {             (byte)0x00, // cla  - class - class of instruction             (byte)0xa4, // ins  - instruction - instruction code             (byte)0x00, // p1   - parameter 1 - instruction parameter 1             (byte)0x0c, // p2   - parameter 2 - instruction parameter 2             (byte)0x02, // lc field - number of bytes present in data field of command             (byte)0xe1, (byte)0x03 // file identifier of cc file     };      private static final byte[] read_capability_container = {             (byte)0x00, // cla  - class - class of instruction             (byte)0xb0, // ins  - instruction - instruction code             (byte)0x00, // p1   - parameter 1 - instruction parameter 1             (byte)0x00, // p2   - parameter 2 - instruction parameter 2             (byte)0x0f  // lc field - number of bytes present in data field of command     };      // in scenario have done cc read, same byte[] match     // readbinary trigger , don't want in succession     private boolean read_capability_container_check = false;      private static final byte[] read_capability_container_response = {             (byte)0x00, (byte)0x0f, // cclen length of cc file             (byte)0x20, // mapping version 2.0             (byte)0x00, (byte)0x3b, // mle maximum 59 bytes r-apdu data size             (byte)0x00, (byte)0x34, // mlc maximum 52 bytes c-apdu data size             (byte)0x04, // t field of ndef file control tlv             (byte)0x06, // l field of ndef file control tlv             (byte)0xe1, (byte)0x04, // file identifier of ndef file             (byte)0x00, (byte)0x32, // maximum ndef file size of 50 bytes             (byte)0x00, // read access without security             (byte)0x00, // write access without security             (byte)0x90, (byte)0x00 // a_okay     };      private static final byte[] ndef_select = {             (byte)0x00, // cla  - class - class of instruction             (byte)0xa4, // instruction byte (ins) select command             (byte)0x00, // parameter byte (p1), select identifier             (byte)0x0c, // parameter byte (p1), select identifier             (byte)0x02, // lc field - number of bytes present in data field of command             (byte)0xe1, (byte)0x04 // file identifier of ndef file retrieved cc file     };      private static final byte[] ndef_read_binary_nlen = {             (byte)0x00, // class byte (cla)             (byte)0xb0, // instruction byte (ins) readbinary command             (byte)0x00, (byte)0x00, // parameter byte (p1, p2), offset inside cc file             (byte)0x02  // le field     };      private static final byte[] ndef_read_binary_get_ndef = {             (byte)0x00, // class byte (cla)             (byte)0xb0, // instruction byte (ins) readbinary command             (byte)0x00, (byte)0x00, // parameter byte (p1, p2), offset inside cc file             (byte)0x0f  //  le field     };      private static final byte[] a_okay = {             (byte)0x90,  // sw1 status byte 1 - command processing status             (byte)0x00   // sw2 status byte 2 - command processing qualifier     };      private static final byte[] ndef_id = {             (byte)0xe1,             (byte)0x04     };      private ndefrecord ndef_uri = new ndefrecord(             ndefrecord.tnf_well_known,             ndefrecord.rtd_text,             ndef_id,             "hello world, bitch!".getbytes(charset.forname("utf-8"))     );     private byte[] ndef_uri_bytes = ndef_uri.tobytearray();     private byte[] ndef_uri_len = biginteger.valueof(ndef_uri_bytes.length).tobytearray();      @override     public int onstartcommand(intent intent, int flags, int startid) {          if (intent.hasextra("ndefmessage")) {             ndef_uri = new ndefrecord(                     ndefrecord.tnf_well_known,                     ndefrecord.rtd_text,                     ndef_id,                     intent.getstringextra("ndefmessage").getbytes(charset.forname("utf-8"))             );              ndef_uri_bytes = ndef_uri.tobytearray();             ndef_uri_len = biginteger.valueof(ndef_uri_bytes.length).tobytearray();              context context = getapplicationcontext();             charsequence text = "your ndef text has been set!";             int duration = toast.length_short;             toast toast = toast.maketext(context, text, duration);             toast.setgravity(gravity.center, 0, 0);             toast.show();         }          log.i(tag, "onstartcommand() | ndef" + ndef_uri.tostring());          return 0;     }      @override     public byte[] processcommandapdu(byte[] commandapdu, bundle extras) {          //         // following flow based on appendix e "example of mapping version 2.0 command flow"         // in nfc forum specification         //         log.i(tag, "processcommandapdu() | incoming commandapdu: " + utils.bytestohex(commandapdu));          //         // first command: ndef tag application select (section 5.5.2 in nfc forum spec)         //         if (utils.isequal(apdu_select, commandapdu)) {             log.i(tag, "apdu_select triggered. our response: " + utils.bytestohex(a_okay));             return a_okay;         }          //         // second command: capability container select (section 5.5.3 in nfc forum spec)         //         if (utils.isequal(capability_container, commandapdu)) {             log.i(tag, "capability_container triggered. our response: " + utils.bytestohex(a_okay));             return a_okay;         }          //         // third command: readbinary data cc file (section 5.5.4 in nfc forum spec)         //         if (utils.isequal(read_capability_container, commandapdu) && !read_capability_container_check) {             log.i(tag, "read_capability_container triggered. our response: " + utils.bytestohex(read_capability_container_response));             read_capability_container_check = true;             return read_capability_container_response;         }          //         // fourth command: ndef select command (section 5.5.5 in nfc forum spec)         //         if (utils.isequal(ndef_select, commandapdu)) {             log.i(tag, "ndef_select triggered. our response: " + utils.bytestohex(a_okay));             return a_okay;         }          //         // fifth command:  readbinary, read nlen field         //         if (utils.isequal(ndef_read_binary_nlen, commandapdu)) {              byte[] start = {                     (byte)0x00             };              // build our response             byte[] response = new byte[start.length + ndef_uri_len.length + a_okay.length];              system.arraycopy(start, 0, response, 0, start.length);             system.arraycopy(ndef_uri_len, 0, response, start.length, ndef_uri_len.length);             system.arraycopy(a_okay, 0, response, start.length + ndef_uri_len.length, a_okay.length);              log.i(tag, response.tostring());             log.i(tag, "ndef_read_binary_nlen triggered. our response: " + utils.bytestohex(response));              return response;         }          //         // sixth command: readbinary, ndef data         //         if (utils.isequal(ndef_read_binary_get_ndef, commandapdu)) {             log.i(tag, "processcommandapdu() | ndef_read_binary_get_ndef triggered");              byte[] start = {                     (byte)0x00             };              // build our response             byte[] response = new byte[start.length + ndef_uri_len.length + ndef_uri_bytes.length + a_okay.length];              system.arraycopy(start, 0, response, 0, start.length);             system.arraycopy(ndef_uri_len, 0, response, start.length, ndef_uri_len.length);             system.arraycopy(ndef_uri_bytes, 0, response, start.length + ndef_uri_len.length, ndef_uri_bytes.length);             system.arraycopy(a_okay, 0, response, start.length + ndef_uri_len.length + ndef_uri_bytes.length, a_okay.length);              log.i(tag, ndef_uri.tostring());             log.i(tag, "ndef_read_binary_get_ndef triggered. our response: " + utils.bytestohex(response));              context context = getapplicationcontext();             charsequence text = "ndef text has been sent reader!";             int duration = toast.length_short;             toast toast = toast.maketext(context, text, duration);             toast.setgravity(gravity.center, 0, 0);             toast.show();              read_capability_container_check = false;             return response;         }          //         // we're doing outside our scope         //         log.wtf(tag, "processcommandapdu() | don't know what's going on!!!.");         return "can you?".getbytes();     }      @override     public void ondeactivated(int reason) {         log.i(tag, "ondeactivated() fired! reason: " + reason);     } } 

sendovernfcactivity.java

public class sendovernfcactivity extends activity{      private static final string tag = "sendovernfcactivity";      @override     protected void oncreate(bundle savedinstancestate) {         super.oncreate(savedinstancestate);         setcontentview(r.layout.sendnfc);               button setndef = (button) findviewbyid(r.id.set_ndef_button);         setndef.setonclicklistener(new view.onclicklistener() {                                        @override                                        public void onclick(view view) {                                             //                                            // technically, if past our byte limit,                                            // cause issues.                                            //                                            // todo: add validation                                            //                                            textview getndefstring = (textview) findviewbyid(r.id.ndef_text);                                            string test = getndefstring.gettext().tostring();                                             intent intent = new intent(getapplicationcontext(), myhostapduservice.class);                                            intent.putextra("ndefmessage", test);                                            startservice(intent);                                        }                                    }         );     }      @override     public void onresume() {         super.onresume();     }      @override     public void onpause() {         super.onpause();     }      @override     public void onstop() {         super.onstop();     }      @override     public void ondestroy() {         super.ondestroy();     } 

the problem public byte[] processcommandapdu(byte[] commandapdu, bundle extras) never runs , app sending 6a82 every time in response mean file/app not found. totally can't understand why happens if aid correct.


Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -