0

i wrote a sample code to sending APDU to contactless smartcard by phone nfc reader and it worked succesfully. Now i want to write a android library to perform some operations like verify PIN and etc. these functions must connect to contactless smartcard and send apdu to it and return the result. The problem is here :(

This is my sample code which works:

public class MainActivity extends Activity {

    private NfcAdapter mAdapter = null;
    static IsoDep myTag;
    private TextView lblStatus;
    private Button btnSelectApplet;
    private PendingIntent mPendingIntent;
    boolean mFirstDetected=false;
    boolean mShowAtr=false;

    private String[][] mTechLists;
    private IntentFilter[] mFilters;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lblStatus = (TextView) findViewById(R.id.lblStatus);
        btnSelectApplet = (Button) findViewById(R.id.btnSelect);
        btnSelectApplet.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                byte[] select = new byte[] {0x00, (byte)0xa4, 0x04, 0x00, 0x09, (byte)0xa0, 0x00,
                        0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x1a};

                byte[] res = transceives(select);
            }
        });
        resolveIntent(getIntent());
        mAdapter = NfcAdapter.getDefaultAdapter(this);
        mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        try
        {
            ndef.addDataType("*/*");
        }
        catch (IntentFilter.MalformedMimeTypeException e)
        {
            throw new RuntimeException("fail", e);
        }
        mFilters = new IntentFilter[] { ndef, };
        mTechLists = new String[][] { new String[] { IsoDep.class.getName() } };

    }

    private static byte[]  transceives (byte[] data)
    {
        byte[] ra = null;
        try
        {
            ra = myTag.transceive(data);
        }
        catch (IOException e)
        {
        }
        try
        {

        }
        catch (Exception e1)
        {
            e1.printStackTrace();
        }

        return (ra);
    }


    private void resolveIntent(Intent intent)
    {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
            Parcelable tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            final Tag t = (Tag) tag;
            myTag = IsoDep.get(t);
            mFirstDetected = true;
            if (myTag != null) {
                if (!myTag.isConnected()) {
                    try {
                        myTag.connect();
                        myTag.setTimeout(5000);
                    } catch (IOException e) {
                        e.printStackTrace();
                        return;
                    }
                }
                if (myTag.isConnected()) {
                    String szATR = null;
                    try {
                        mShowAtr = true;
                        szATR = " 3B " + getATRLeString(myTag.getHistoricalBytes()) + "80 01 " + getHexString(myTag.getHistoricalBytes()) + "" + getATRXorString(myTag.getHistoricalBytes());
                    } catch (Exception e) {
                        mShowAtr = false;
                        szATR = "CARD DETECTED  ";
                    }
                    lblStatus.setText(szATR);
                } else {
                    lblStatus.setText("Not Connected!");
                }
                if (mFirstDetected == true && myTag.isConnected()) {

                } else {
                    lblStatus.setText("Not Connected!");
                }
            }
        }
    }

    private static String getATRLeString(byte[] data) throws Exception
    {
        return String.format("%02X ", data.length | 0x80);
    }

    private static String getATRXorString(byte[] b) throws Exception
    {
        int Lrc=0x00;
        Lrc = b.length | 0x80;
        Lrc = Lrc^0x81;
        for (int i=0; i < b.length; i++)
        {
            Lrc = Lrc^(b[i] & 0xFF);
        }
        return String.format("%02X ", Lrc);
    }

    private static String getHexString(byte[] data) throws Exception
    {
        String szDataStr = "";
        for (int ii=0; ii < data.length; ii++)
        {
            szDataStr += String.format("%02X ", data[ii] & 0xFF);
        }
        return szDataStr;
    }

    @Override
    protected void onNewIntent(Intent intent)
    {
        setIntent(intent);
        resolveIntent(intent);
    }

    @Override
    public void onResume()
    {
        super.onResume();
        if (mAdapter != null)
        {
            mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
        }
    }

}

Sample code used enableForegroundDispatch function to detect smartcard in NFC field. When smartcard detected, onNewIntent is called.

I want put all of the code in android library module X and use it in Activity Y like

Activity Y extend X

or

X x = new X() 

and call it functions. how could i implement it? I have a problem when i want to call

mAdapter = NfcAdapter.getDefaultAdapter(this);

if i use this code:

mAdapter = NfcAdapter.getDefaultAdapter(context);// context pass from Y Activity to X(Android library)

the function

mAdapter.enableForegroundDispatch(this , mPendingIntent, mFilters, mTechLists); // In X (Android library)

doesn't work correctly because it doesn't use Y activity (it used X axtivity). How can i solve my problem such way all code will be in X(android library)?

Thanks.

Mohsen Gorgani
  • 420
  • 4
  • 18

1 Answers1

0

as per my understanding, you are trying to access some of the methods from other activity,

  1. here I suggest you to create third class for that NFC module methods,
  2. create singleton method that returns a static instance of that model class.
  3. you can access that instance from any of your Activity.
  4. you also can set a callback in a class and another method call from another class of activity.

Hope this will help you. ask if anything not clear.

Happy Coding :)

RBK
  • 2,481
  • 2
  • 30
  • 52
  • thanks for reply. Can i use " enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists)" function in singleton class which is not an activity? – Mohsen Gorgani Aug 11 '16 at 18:02