工作中需要用到 openmobileapi接口,由于遇到不少问题,所以记录一下
1、OpenMobileApi 在Android P以后,谷歌将此API的实现纳入官方API中。但是在Android P之前需要外部引入org.simalliance.openmobileapi.jar包才能使用相关功能。jar包可以自己网上去下载,注意由于android5.0后不支持隐士启动service,所以需要下载支持android5.0以上的jar包,可以通过如下链接下载jar和测试demo
https://download.youkuaiyun.com/download/x995630736/86937805?spm=1001.2014.3001.5503
2、集成好jar后需要验证接口功能是否正常
首先 创建app工程,在AndroidManifest.xml 中加权限
<uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD"></uses-permission>
然后编写测试代码,链接demo中有提供
SEServiceCallback callback = new SEServiceCallback(); new SEService(this, callback);
public class SEServiceCallback implements SEService.CallBack { @Override public void serviceConnected(SEService service) { _service = service; performTest(); } } private void performTest() { Reader[] readers = _service.getReaders(); logd("Available readers: \n"); for (Reader reader : readers) logd(" " + reader.getName() + " - " + ((reader.isSecureElementPresent()) ? "present" : "absent") + "\n"); if (readers.length == 0) { logd("No reader available \n"); return; } for (Reader reader : readers) { if (!reader.isSecureElementPresent()) continue; logd("\n--------------------------------\nSelected reader: \"" + reader.getName() + "\"\n"); try { _session = reader.openSession(); } catch (Exception e) { logd(e.getMessage()); } if (_session == null) continue; try { byte[] atr = _session.getATR(); logd("ATR: " + ((atr == null) ? "unavailable" : bytesToString(atr)) + "\n\n"); } catch (Exception e) { logd("Exception on getATR(): " + e.getMessage() + "\n\n"); } testBasicChannel(null); testBasicChannel(ISD_AID); testLogicalChannel(null); testLogicalChannel(ISD_AID); _session.close(); } } void testBasicChannel(byte[] aid) { try { logd("BasicChannel test: " + ((aid == null) ? "default applet" : bytesToString(aid)) + "\n"); Channel channel = _session.openBasicChannel(aid); byte[] cmd = new byte[] { (byte) 0x80, (byte) 0xCA, (byte) 0x9F, 0x7F, 0x00 }; logd(" -> " + bytesToString(cmd) + "\n"); byte[] rsp = channel.transmit(cmd); logd(" <- " + bytesToString(rsp) + "\n\n"); channel.close(); } catch (Exception e) { logd("Exception on BasicChannel: " + e.getMessage() + "\n\n"); } } void testLogicalChannel(byte[] aid) { try { logd("LogicalChannel test: " + ((aid == null) ? "default applet" : bytesToString(aid)) + "\n"); Channel channel = _session.openLogicalChannel(aid); byte[] cmd = new byte[] { (byte) 0x80, (byte) 0xCA, (byte) 0x9F, 0x7F, 0x00 }; logd(" -> " + bytesToString(cmd) + "\n"); byte[] rsp = channel.transmit(cmd); logd(" <- " + bytesToString(rsp) + "\n\n"); channel.close(); } catch (Exception e) { logd("Exception on LogicalChannel: " + e.getMessage() + "\n\n"); } } private static String bytesToString(byte[] bytes) { StringBuffer sb = new StringBuffer(); for (byte b : bytes) sb.append(String.format("%02x ", b & 0xFF)); return sb.toString(); }
最后运行测试代码,发现一直打印绑定失败 SEService: bindingSuccessful: false,从jar包源码中可以看到是由于绑定smartcardService失败了,所以需要检查固件编译时是否有把smartcardService源码编译进去。我这边是由于没有编译进去导致
在system/app目录下可以查看是否存在相关APP,存在表示源码已经成功合入
重新编译固件源码后测试 ,打印绑定成功 SEService: bindingSuccessful: true
绑定成功后说明OMA通道是正常的,就可以对SE模块进项相关操作了