Android OMAPI中SEService的OnConnectedListener未触发问题求助
问题描述
我正在开发一款使用OMAPI库向SIM卡传输APDU的应用,但SEService的OnConnectedListener始终未被调用。我参考谷歌CTS测试代码结构实现,等待30秒仍未触发该监听器,最终抛出超时异常:
throw new TimeoutException( "Service could not be connected after " + SERVICE_CONNECTION_TIME_OUT + "ms");
我的SIM卡包含ARA-M小程序及必要的SHA-1密钥,应用已获取运营商权限,且在另一款使用TelephonyManager库的应用中成功传输过APDU。请问是否存在操作错误?应用清单是否需要声明特殊权限?
以下是部分实现代码:
public class MainActivity extends AppCompatActivity [...]{ /*FOR OMAPI*/ private final Object serviceMutex = new Object(); private SEService seService; private boolean connected = false; private Timer connectionTimer; private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask(); private final long SERVICE_CONNECTION_TIME_OUT = 30000; ////////////////////////////////////////////////////////////////////////////// @Override public void onCreate(Bundle savedInstanceState) { [...] setUp(getApplicationContext()); try { waitForConnection(); } catch (TimeoutException e) { throw new RuntimeException(e); } Reader[] readers = seService.getReaders(); byte [] apdu = {(byte)0x80, (byte)0x02, (byte)0xfC, (byte)0x00}; for (Reader reader : readers){ byte [] response = new byte[0]; try { response = Util.internalTransmitAPDU(reader, apdu); } catch (IOException e) { throw new RuntimeException(e); } Log.i("response OMAPI", String.valueOf(response)); } } public void setUp(Context context){ seService = new SEService(context, new SynchronousExecutor(), mListener); connectionTimer = new Timer(); connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT); } static class SynchronousExecutor implements Executor { public void execute(Runnable r) { r.run(); } } private final SEService.OnConnectedListener mListener = () -> { synchronized (serviceMutex){ connected = true; serviceMutex.notify(); Log.i("OMAPI", "EntraOnconnect"); } private void waitForConnection() throws TimeoutException { synchronized (serviceMutex) { if (!connected) { try { serviceMutex.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if (!connected && !seService.isConnected()) { throw new TimeoutException( "Service could not be connected after " + SERVICE_CONNECTION_TIME_OUT + " ms"); } if (connectionTimer != null) { connectionTimer.cancel(); } } } }
排查与解决建议
1. 代码中的致命问题
主线程阻塞导致回调无法执行:你在
onCreate(主线程)中调用waitForConnection(),该方法通过serviceMutex.wait()阻塞了主线程。而你的SynchronousExecutor是直接在当前线程(主线程)执行回调,主线程被阻塞后,OnConnectedListener的回调根本无法运行。
解决:将OMAPI的连接逻辑和APDU传输放到后台线程(如Coroutine、Thread或ExecutorService),避免阻塞主线程。监听器代码未闭合:
mListener的lambda表达式缺少闭合的};,这会导致编译或运行时异常,使得监听器无法正常注册。修正后的代码:
private final SEService.OnConnectedListener mListener = () -> { synchronized (serviceMutex){ connected = true; serviceMutex.notify(); Log.i("OMAPI", "EntraOnconnect"); } }; // 补充闭合符号
- 未实现超时任务:
ServiceConnectionTimerTask未实现,它应该在超时后设置connected = false并唤醒等待的线程,否则超时逻辑不完整。示例实现:
class ServiceConnectionTimerTask extends TimerTask { @Override public void run() { synchronized (serviceMutex) { connected = false; serviceMutex.notify(); } } }
2. 应用清单权限检查
必须在AndroidManifest.xml中声明以下权限:
- 基础权限:
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> - 运营商/SE访问权限:
如果你是运营商特权应用,需要声明:
另外,OMAPI访问SE需要系统级权限,需添加:<uses-permission android:name="com.android.carrierapi.permission.CARRIER_PRIVILEGED" />
注意:<uses-permission android:name="com.android.se.permission.SECURE_ELEMENT_ACCESS" />SECURE_ELEMENT_ACCESS是系统签名权限,你的应用需要有运营商或系统签名才能获取,需确保签名与权限要求匹配。
3. 其他注意事项
- 避免在
onCreate中直接执行耗时操作,将APDU传输等逻辑放到后台线程。 - 确认设备支持OMAPI访问SIM卡SE:部分设备可能限制了OMAPI对SIM卡的访问,即使
TelephonyManager可用,OMAPI可能需要额外的设备配置。 - 管理
SEService生命周期:在Activity销毁时调用seService.shutdown()释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Dariel Reyes
相关产品推荐
相关产品推荐

