针对Android API方法的UnsupportedOperationException CardEmulation.getInstance()

问题描述:

我需要检查设备上是否启用了卡仿真。我找到了一个方法here针对Android API方法的UnsupportedOperationException CardEmulation.getInstance()

boolean isDefault = CardEmulation 
       .getInstance(NfcAdapter.getDefaultAdapter(this)) 
       .isDefaultServiceForCategory(
         new ComponentName(this, MyPaymentService.class), 
         CardEmulation.CATEGORY_PAYMENT); 

它看起来像这样的工作在某些设备上,但不是所有的设备。

例如,在Samsung GT-I9300I(带有Android 4.4)上,有一个NFC模块,但它没有在设置中显示Tap-and-pay选项。

当我的应用程序,设备出现以下错误上运行:

 
E/CardEmulation: This device does not support card emulation 
09-26 16:41:13.592 2625-2625/? E/AndroidRuntime: FATAL EXCEPTION: main 
               Process: com.android.settings, PID: 2625 
               java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.settings/com.android.settings.nfc.PaymentDefaultDialog}: java.lang.UnsupportedOperationException 
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2441) 
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2500) 
                at android.app.ActivityThread.access$900(ActivityThread.java:171) 
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309) 
                at android.os.Handler.dispatchMessage(Handler.java:102) 
                at android.os.Looper.loop(Looper.java:146) 
                at android.app.ActivityThread.main(ActivityThread.java:5679) 
                at java.lang.reflect.Method.invokeNative(Native Method) 
                at java.lang.reflect.Method.invoke(Method.java:515) 
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291) 
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107) 
                at dalvik.system.NativeStart.main(Native Method) 
                Caused by: java.lang.UnsupportedOperationException 
                at android.nfc.cardemulation.CardEmulation.getInstance(CardEmulation.java:159) 
                at com.android.settings.nfc.PaymentBackend.(PaymentBackend.java:53) 
                at com.android.settings.nfc.PaymentDefaultDialog.onCreate(PaymentDefaultDialog.java:57) 
                at android.app.Activity.performCreate(Activity.java:5582) 
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093) 
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2405) 
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2500) 
                at android.app.ActivityThread.access$900(ActivityThread.java:171) 
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309) 
                at android.os.Handler.dispatchMessage(Handler.java:102) 
                at android.os.Looper.loop(Looper.java:146) 
                at android.app.ActivityThread.main(ActivityThread.java:5679) 
                at java.lang.reflect.Method.invokeNative(Native Method) 
                at java.lang.reflect.Method.invoke(Method.java:515) 
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291) 
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107) 
                at dalvik.system.NativeStart.main(Native Method) 

然而,根据the documentationCardEmulation是因为API级别19中(Android 4.4)可用。

所以任何人都可以解释为什么我得到这个异常?我怎样才能克服这个问题?

的错误是在日志输出很清楚:

 
E/CardEmulation: This device does not support card emulation 

这个类只能在支持卡模拟和基于AID路由配置设备来使用。这也记录在the documentation of the class CardEmulation

Use of this class requires the FEATURE_NFC_HOST_CARD_EMULATION to be present on the device.

因此,你必须只使用方法getInstance()上实际支持HCE功能的设备。请注意,主机卡仿真在这里有点让人误解,因为该功能还需要使用OffHostApduService声明来管理路由配置,并使用CardEmulation类来处理与OffHostApduService相关的任何操作。所以这个特性适用于HCE和基于安全元件卡仿真的路由配置管理。但是,一些设备制造商开发了其他机制来测试基于安全元件的卡仿真的可用性(还可用于管理路由)。

您可以使用下面的代码来检查HCE功能调用CardEmulation.getInstance()方法之前:

boolean isDefault = false; 
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) { 
    isDefault = CardEmulation.getInstance(NfcAdapter.getDefaultAdapter(this)) 
           .isDefaultServiceForCategory(
             new ComponentName(this, MyPaymentService.class), 
             CardEmulation.CATEGORY_PAYMENT); 
} 
+0

十分感谢您的帮助! –