这取决于您实际想要查找的版本:SmartcardService 系统组件的版本或 Open Mobile API 框架的版本。
查找 SmartcardService 系统应用程序的版本
最明显的方法是检查 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的确切版本。
不幸的是,一些原始设备制造商(例如三星)决定从应用程序包中删除版本信息。因此,这并不像人们预期的那样可靠。
另一种允许您区分基于 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
}
}
另一种允许您区分 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 开始,SEService
Open 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 规范版本:
如果您的应用程序是针对 SEEK < 4.0.0 编译的:
if (getVersion != null) {
String version = (String)getVersion.invoke(seService);
}
如果您的应用程序是针对 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 版本和安装在目标设备上的智能卡系统服务不兼容。这是您根本不应该做的事情。