如何在 Android 上查看 Open Mobile API 的版本?

How do I check the version of Open Mobile API on Android?

据我了解,Open Mobile API 与制造商创建的 Android ROM 捆绑在一起。我们使用的 SDK 大量使用 Open Mobile API,并发现一些供应商创建 ROM,其中 Open Mobile API 的版本与 Android 的版本不兼容.这会导致灾难,当我们尝试使用上述 SDK 时,应用程序崩溃了。因为 SDK 启动了一个新线程,并在其上崩溃。我们甚至不能将整个逻辑放在一个 try-catch 块中,因为所有这些都是 运行 在一个单独的线程中。

我们决定检查 Android 和 Open Mobile API 的版本,看看它们是否不兼容,如果不兼容,则完全禁用需要它的功能。

有没有办法确定预装的 Open Mobile API 的版本?如果有,怎么办?

这取决于您实际想要了解的版本:SmartcardService 系统组件的版本或 Open Mobile API 框架的版本。

正在查找 SmartcardService 系统应用程序的版本

  1. 最明显的方法是查看SmartcardService应用包的版本信息:

    final String SMARTCARD_SERVICE_PACKAGE = "org.simalliance.openmobileapi.service";
    PackageInfo pi = getPackageManager().getPackageInfo(SMARTCARD_SERVICE_PACKAGE, 0);
    String versionName = pi.versionName;
    String versionCode = pi.versionCode;
    

    versionName 的典型值为“2.3.0”(versionCode = 1)、“2.4.0”(versionCode = 3)、“3.0.0”(versionCode = 4)、“3.1。 0”(版本代码 = 5)和“4.0.0”(版本代码 = 8)。因此,您可以确定 SmartcardService 派生的 SEEK 的确切版本。

    不幸的是,一些 OEM(例如三星)决定从应用程序包中删除版本信息。因此,这并不像人们预期的那样可靠。

  2. 另一种可以区分基于 SEEK 版本 < 4.0.0 和 SEEK 版本 >= 4.0.0 的实现的方法是检查 SmartcardService 组件的 Intent 过滤器:

    final String SMARTCARD_SERVICE_PACKAGE = "org.simalliance.openmobileapi.service";
    final String SMARTCARD_SERVICE_CLASS = "org.simalliance.openmobileapi.service.SmartcardService";
    final String SMARTCARD_SERVICE_ACTION_V4 = "org.simalliance.openmobileapi.BIND_SERVICE";
    final String SMARTCARD_SERVICE_ACTION_PRE4 = "org.simalliance.openmobileapi.service.ISmartcardService";
    Intent intent = new Intent();
    intent.setClassName(SMARTCARD_SERVICE_PACKAGE, SMARTCARD_SERVICE_CLASS);
    intent.setAction(SMARTCARD_SERVICE_ACTION_V4);
    ResolveInfo ri = getPackageManager().resolveService(intent, 0);
    if (ri != null) {
        // is version >= 4.0.0
    } else {
        intent.setAction(SMARTCARD_SERVICE_ACTION_PRE4);
        ResolveInfo ri = getPackageManager().resolveService(intent, 0);
        if (ri != null) {
            // is version < 4.0.0
        } else {
            // is unknown version
        }
    }
    
  3. 另一种区分 SEEK < 4.0.0 和 SEEK >= 4.0.0 的方法是检查 SmartcardService 是否持有权限 BIND_TERMINAL,这是在寻求 4.0.0:

    final String SMARTCARD_SERVICE_PACKAGE = "org.simalliance.openmobileapi.service";
    final String PERMISSION_BIND_TERMINAL = "org.simalliance.openmobileapi.BIND_TERMINAL";
    if (PackageManager.PERMISSION_GRANTED == getPackageManager().checkPermission(PERMISSION_BIND_TERMINAL, SMARTCARD_SERVICE_PACKAGE)) {
        // is version >= 4.0.0
    } else {
        // is version < 4.0.0
    }
    

查找 Open Mobile API 框架的版本

从 SEEK 版本 4.0.0 开始,Open Mobile API 框架的 SEService class 公开了一个方法 getVersion() returns 版本字符串已实施的 Open Mobile API 规范(SEEK 4.0.0 的“3.0”)。因此,您可以查询该方法以找到已实现的 Open Mobile API version:

Class cls = org.simalliance.openmobileapi.SEService.class;
Method getVersion = null;
try {
    getVersion = cls.getDeclaredMethod("getVersion");
} catch (NoSuchMethodException e) {}
if (getVersion != null) {
    // probably SEEK >= 4.0.0
} else {
    // probably SEEK < 4.0.0
}

此外,如果您有 SEService 对象的实例,您可以调用 getVersion() 方法来查找已实现的 Open Mobile API 规范版本:

  1. 如果您的应用程序是针对 SEEK < 4.0.0 编译的:

    if (getVersion != null) {
        String version = (String)getVersion.invoke(seService);
    }
    
  2. 如果您的应用程序是针对 SEEK >= 4.0.0 编译的:

    if (getVersion != null) {
        String version = seService.getVersion();
    }
    

请注意,尝试获取 SEService class 的实例可能会导致您在 SEService class 将自动启动与 SmartcardService 的连接。

类似于发现 getVersion() 方法,您也可以尝试发现 API 中特定于特定版本的 Open Mobile API 规范的方法。例如,您可以测试方法

是否存在
public Channel openBasicChannel(byte[] aid, byte p2);

中的Session class (org.simalliance.openmobileapi.Session)。此方法在规范的 3.0 版本中引入。

但是,您应该知道基于框架 classes 的检测只有在您的应用程序使用 Open Mobile API 框架 classes 时才有效随目标设备一起提供,并且打包它自己的相关框架版本classes。否则你只会检测你打包到你的应用程序,而不是系统上可用的内容。

预装在设备上的 Open Mobile API 框架通常与其在同一设备上的后端 (SMartcardService) 兼容。由于您似乎存在版本冲突,因此您的应用可能会打包自己的 Open Mobile API 框架版本,该版本与目标 Android 版本和安装在目标上的智能卡系统服务不兼容设备。 这是你根本不应该做的事情。