【摘要】随着NFC支付的不断发展,以及NFC城市一卡通的不断普及,越来越多的大众开始接触到NFC技术带来的安全以及便捷,本文主要针对ANDROID如何通过OMA获取ESE的CPLC作下简单的介绍
OMA调用的流程图如下:
public class OMASEServiceCallBack implements SEService.CallBack {
@Override
public void serviceConnected(SEService seService) {
Log.d(TAG, "connect to SEService");
mSEservice = seService;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getApplicationContext();
setContentView(R.layout.activity_cplc_layout);
mBtn_sendCommand = (Button) findViewById(R.id.bt_sendCommand);
mBtn_sendCommand.setOnClickListener(this);
mTxtShowCplc = (TextView) findViewById(R.id.txt_showCplc);
getSEService();
}
首先我们得获取SEService的对象,上述的代码实现了这一点,当我们new SEService(mContext, mCallBack)时,会提供一个callback,在SEService的构造函数里面,会去bind SmartcardService,一旦bind成功,会通过callback回调上面的serviceConnected方法,这时候,就可以拿到SEService对象了,这个操作一般方法onCreate()方法里面执行。
private Reader getEseReader(Reader[] readers){
Reader eseReader = null;
Log.d(TAG, "getReader start");
if(readers != null && readers.length >= 1){
int idx = 0;
for(Reader reader : readers){
if(reader.getName().startsWith("eSE")){
break;
}
idx++;
}
if(idx < readers.length){
eseReader = readers[idx];
}else{
Log.d(TAG, "eSE reader not exist");
}
}else{
Log.d(TAG, "_readers is null");
}
Log.d(TAG,"getReader end");
return eseReader;
}
接下来,我们需要获得eSEReader,通过SEService的getReaders()方法,我们可以获得一个Readers的数组,这里用reader.getName().startsWith(“eSE”)筛选出来。
private Session initSession(Reader[] readers) {
Log.d(TAG, "initSession start");
Session session = null;
try {
session = getEseReader(readers).openSession();
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "initSession end");
if (session == null){
Log.d(TAG, "session null, re-connect");
if (mSEservice != null && mSEservice.isConnected())
mSEservice.shutdown();
SEService seService = getSEService();
if (seService == null){
return null;
}
mReaders = seService.getReaders();
try {
session = getEseReader(mReaders).openSession();
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "re-connect end session is " + session);
}
return session;
}
拿到eSEReader之后,接下来就是openSession的操作了,这里我们加入了一个re-connect机制,如果第一次get失败了,会重新get一次。
public static final String openChannelCommand = "A000000151000000";
public static final String getCplcCommand = "80CA9F7F00";
synchronized private boolean sendCommand() {
boolean result = true;
Session session = null;
Channel channel = null;
if (mSEservice == null) {
Log.d(TAG, "init failed !!!");
return false;
}
try {
if (mReaders == null) {
mReaders = mSEservice.getReaders();
}
session = initSession(mReaders);
if (session == null) {
return false;
}
byte[] openChannelAidByte = CplcUtils.hexStringToBytes(openChannelCommand);
channel = session.openBasicChannel(openChannelAidByte);
Log.d(TAG, "sendCommand openBasicChannel");
if (channel != null) {
byte[] respSetstatus = channel.transmit(CplcUtils.hexStringToBytes(getCplcCommand));
mStrCplc = CplcUtils.bytesToHexString(respSetstatus);
Log.d(TAG, "aid response" + mStrCplc);
channel.close();
}
session.close();
}
catch (IOException e) {
e.printStackTrace();
return false;
} catch (Exception e1) {
e1.printStackTrace();
return false;
} finally {
if (channel != null && !channel.isClosed()) {
channel.close();
}
if (session != null && !session.isClosed()) {
session.close();
}
}
return true;
}
最后就是openChannel以及sendCommand了,对于Ese来说,basicChannel和logicChannel都可以,我们这里打开的是BasicChannel,select的Aid为”A000000151000000”,当然如果我们把参数设置为null的话,也会用默认的Aid去执行,效果是一样的。Channel打开之后,通过transmit方法,就可以把查询CPLC的命令发送过去,正常情况下会成功返回9000结尾的一串数字,解析之后就是我们最终需要的CPLC了
完整的代码请见这里: http://download.csdn.net/download/shaoyuan1314520/10176536