Как проверить версию Open Mobile API для Android?

Насколько я понимаю, Open Mobile API в комплекте с Android ROM, созданными производителями. Мы используем SDK, который интенсивно использует Open Mobile API, и обнаружили, что некоторые поставщики создают ПЗУ, где версия Open Mobile API несовместима с версией Android. Это приводит к катастрофе, когда мы пытаемся использовать упомянутый SDK, происходит сбой приложения. Потому что SDK запускает новый поток и вылетает на нем. Мы даже не можем поместить всю логику в блок try-catch, потому что все это выполняется в отдельном потоке.

Мы решили проверить версию Android и Open Mobile API и посмотреть, являются ли они несовместимыми, и если они есть, полностью отключить функциональность, которая требует этого.

Есть ли способ определить версию предустановленного Open Mobile API? Если есть, как я могу это сделать?

1 ответ

Решение

Это зависит от того, какую версию вы действительно хотите узнать: версию системного компонента 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" (versionCode = 8). Таким образом, вы можете определить точную версию SEEK, из которой был извлечен SmartcardService.

    К сожалению, несколько производителей оборудования (например, Samsung) решили удалить информацию о версии из пакета приложения. Следовательно, это не так надежно, как можно было бы ожидать.

  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 SEService класс фреймворка Open Mobile API предоставляет метод getVersion() который возвращает строку версии реализованной спецификации Open Mobile API ("3.0" для SEEK 4.0.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, которые поставляются вместе с целевым устройством, и не упаковывает свою собственную версию соответствующих классов инфраструктуры. В противном случае вы обнаружите только то, что упаковано в ваше приложение, а не то, что доступно в системе.

Платформа Open Mobile API, предварительно установленная на устройстве, обычно будет совместима с его серверной частью (SMartcardService) на том же устройстве. Поскольку у вас, похоже, возникают конфликты версий, вполне вероятно, что ваше приложение упаковывает свою собственную версию Open Mobile API Framework, несовместимую с целевой версией Android и системной службой Smartcard, установленной на целевом устройстве. Это то, что вы просто не должны делать.

Другие вопросы по тегам