As far as I understand, Open Mobile API is bundled with the Android ROMs created by manufacturers. We are using an SDK that is heavily using Open Mobile API, and found out, that some vendors create ROMs, where the version of the Open Mobile API is incompatible with the version of Android. This results in a disaster, that when we try to use the mentioned SDK, the application crashes. Because the SDK starts a new thread, and crashes on it. We cannot even put the whole logic in a try-catch block because of all this is running in a separate thread.
We decided to check the version of Android and the Open Mobile API, and see if they are incompatible, and if they are, completely disable the functionality that requires it.
Is there a way to determine the version of the preinstalled Open Mobile API? If there is, how can I do it?
That depends on what version you actually want to find out: the version of the SmartcardService system component or the version of the Open Mobile API framework.
Finding the version of the SmartcardService system application
The most obvious way would be to check the version information of the SmartcardService application package:
Typical values for
versionNameare "2.3.0" (versionCode = 1), "2.4.0" (versionCode = 3), "3.0.0" (versionCode = 4), "3.1.0" (versionCode = 5), and "4.0.0" (versionCode = 8). Thus, you can determine the exact version of SEEK that the SmartcardService was forked from.Unfortunately, several OEMs (e.g. Samsung) decided to remove the version information from the application package. Consequently, this is not as reliable as one might expect.
Another method that allows you to distinguish between implementations based on SEEK versions < 4.0.0 and SEEK versions >= 4.0.0 is to check the intent filter of the SmartcardService component:
Yet another method that allows you to distinguish between SEEK < 4.0.0 and SEEK >= 4.0.0 is to check if the SmartcardService holds the permission BIND_TERMINAL, a permission introduced in SEEK 4.0.0:
Finding the version of the Open Mobile API framework
Starting with SEEK version 4.0.0 the
SEServiceclass of the Open Mobile API framework exposes a methodgetVersion()that returns the version string of the implemented Open Mobile API specification ("3.0" for SEEK 4.0.0). Thus, you could query that method to find the implemented Open Mobile API version:Further, if you have an instance of the
SEServiceobject, you could invoke thegetVersion()method to find the implemented Open Mobile API specification version:If your application was compiled against SEEK < 4.0.0:
If your application was compiled against SEEK >= 4.0.0:
Note that trying to obtain an instance of the
SEServiceclass may result in exactly the undesired behavior that you found in the first place since the constructor of theSEServiceclass will automatically initiate the connection to the SmartcardService.Similar to discovering the
getVersion()method, you could also try to discover methods in the API that are specific to a certain version of the Open Mobile API specification. For instance, you could test for the existence of the methodin the
Sessionclass (org.simalliance.openmobileapi.Session). This method was introduced in version 3.0 of the specification.However, you should be aware that detection based on the framework classes will only work if your app uses the Open Mobile API framework classes that are shipped with the target device and does not package its own version of the relevant framework classes. Else you would only detect what you packed into your app and not what's available on the system.
The Open Mobile API framework that is preinstalled on a device would usually be compatible with its backend (SMartcardService) on the same device. Since you seem to have version conflicts it is likely the case that your app packages its own version of the Open Mobile API framework that is incomatible with the target Android version and the Smartcard system service installed on the target device. This is something that you simply should not do.