3

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

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

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

4

1 回答 1

5

这取决于您实际想要查找的版本: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”(versionCode = 5)和“ 4.0.0”(版本代码 = 8)。因此,您可以确定派生 SmartcardService的SEEK的确切版本。

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

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

    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,这是 SEEK 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 开始,SEServiceOpen Mobile API 框架的类公开了一个方法,该方法getVersion()返回已实现的 Open Mobile API 规范的版本字符串(SEEK 4.0.0 为“3.0”)。因此,您可以查询该方法以查找已实现的 Open Mobile API 版本:

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该类的实例可能会导致您最初发现的不良行为,因为该类的构造函数SEService将自动启动与 SmartcardService 的连接。

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

public Channel openBasicChannel(byte[] aid, byte p2);

Session类(org.simalliance.openmobileapi.Session)中。该方法是在规范的 3.0 版中引入的。

但是,您应该知道,基于框架类的检测仅在您的应用程序使用目标设备随附的 Open Mobile API 框架类且未打包其自己版本的相关框架类时才有效。否则,您只会检测到您打包到应用程序中的内容,而不是系统上可用的内容。

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

于 2016-05-07T10:21:11.417 回答