如何为较旧和较新的 Android 版本实现不同的 API?

Posted

技术标签:

【中文标题】如何为较旧和较新的 Android 版本实现不同的 API?【英文标题】:How to handle implementing different APIs for older and newer Android versions? 【发布时间】:2016-07-22 05:23:24 【问题描述】:

我正在编写一个应用程序,它使用旧的 android 版本的旧相机 API 和 API 23 及更高版本的新 camera2/torch API。 基本上,我确定设备是否正在运行足够新的 Android 版本,然后根据它在实现之间切换。归结为:

private static final int SDK_VERSION = Build.VERSION.SDK_INT;

private boolean isSdkVersionGreaterThanOrEqualTo(final int sdk) 
    return SDK_VERSION >= sdk;


if (marshmallowOrNewer)  //isSdkVersionGreaterThanOrEqualTo(23);
                            try 
                                cameraManager.setTorchMode(cameraManager.getCameraIdList()[0], true);
                             catch (final CameraAccessException e) 
                                e.printStackTrace();
                            
                         else 
                            cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                            camera.setParameters(cameraParameters);
                            camera.startPreview();
                        

在 Gingerbread 上运行时,我强制关闭:FATAL EXCEPTION: main java.lang.VerifyError 在这一行:

 toggleButton.setOnClickListener(new View.OnClickListener() 

打开包含上述代码的 OnClickListener 并指示此版本的 android 不支持 API 方法,这是有道理的,但我实际上并没有在这里调用它。我应该如何正确处理这种情况,为不同的 Android 版本实现不同的 API,或者如何绕过这种非常化?

堆栈跟踪:

04-02 13:42:54.413 3815-3815/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 java.lang.VerifyError: t.t.t.MainActivity$1
                                                     at t.t.t.MainActivity.onCreate(MainActivity.java:61)
                                                     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)
                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
                                                     at android.app.ActivityThread.access$1500(ActivityThread.java:123)
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
                                                     at android.os.Handler.dispatchMessage(Handler.java:99)
                                                     at android.os.Looper.loop(Looper.java:130)
                                                     at android.app.ActivityThread.main(ActivityThread.java:3835)
                                                     at java.lang.reflect.Method.invokeNative(Native Method)
                                                     at java.lang.reflect.Method.invoke(Method.java:507)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
                                                     at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

请发布堆栈跟踪。 您的问题不在于调用方法。 AFAIK,它位于t.t.t.MainActivity$1 的某个接口或超类中。您确定t.t.t.MainActivity$1View.OnClickListener()?你附近还有其他匿名内部类吗? View.OnClickListener 自 API 级别 1 以来一直存在,因此这似乎不是 VerifyError 的来源。 第 61 行是 OnClickListener,它是 MainActivity 中唯一的匿名内部类,这是我的代码中唯一的类。我还在我的 logkitty 中找到了这个:04-02 13:42:54.413 3815-3815/? I/dalvikvm:找不到方法 android.hardware.camera2.CameraManager.getCameraIdList,引用自方法 t.t.t.MainActivity$1.onClick “找不到方法 android.hardware.camera2.CameraManager.getCameraIdList,从方法 t.t.t.MainActivity$1.onClick 引用”——好的,这似乎是你的问题。你能发这个OnClickListener吗? Samgak 的回答很有帮助。显然,我不能对旧 android 版本上不受支持的 API 有任何引用。将它们移动到不同的类修复它。 【参考方案1】:

我在将 Camera2 功能添加到我的应用程序时遇到了这个问题。我不能权威地谈论底层机制,因为我只是通过反复试验来修复它,但通过测试我发现问题只发生在比冰淇淋三明治更早的设备上,之后可以通过运行来避免它像您一样对 SDK 版本进行时间测试。似乎对于 ICS 及更高版本,可以在您的类中使用不受支持的 API,只要您从不调用它,但在此之前,您需要确保从不实例化使用不受支持的 API 调用的类,无论您叫不叫。

我用这个方法解决了这个问题:

创建一个Camera2Object 类(随意命名),它调用您使用的Camera2 API 函数。从所有其他类中删除所有导入的 Lollipop+ Camera2 类。可以在您的其他类中引用此 Camera2Object 类。 仅在检查 API 版本 >= 21(Lollipop)或您的情况下为 Marshmallow 后才创建此类的实例。 在您当前在 API 版本检查 if 语句中调用 Camera2 函数的类中,更改您的代码以检查您的 Camera2Object 是否不为空,如果是,则在其上调用一个方法来实现您在 if 中的功能声明。

您可能需要聪明一点并重新排列代码,以便将所有 Camera2 内容隐藏在此类中 - 您可能需要将返回代码等转换为不依赖于 Camera2 导入的内容,并可能返回整数或字符串作为对 Camera2 对象的引用,而不是在此类和应用程序的其余部分之间的边界处来回转换。

您可以拥有多个调用 Camera2 函数的类,只要 API 版本低于 21 时它们都不是实例。

这是在 2.3.3 设备上测试的,我不能保证 Gingerbread 的早期版本。我也不能保证您不需要为 ICS 及之后执行此操作。

【讨论】:

这真是太奇怪了。我会试试的。 相信它,我不能。谢谢,伙计,这解决了它。 哇,你真快!我花了一个下午最好的时间来重构我的代码。很高兴有帮助

以上是关于如何为较旧和较新的 Android 版本实现不同的 API?的主要内容,如果未能解决你的问题,请参考以下文章

将较新的 Visual Studio 版本与较旧的 MFC 版本一起使用?

为啥在较新的 Android 设备上预检失败,但在较旧的设备和台式机上却没有?

如何为旧版 Android API 实现 TextView 行间距方法?

将使用 pip 安装的站点包/模块从较旧版本的 python 迁移到较新/最新版本的 python

什么决定了最大纹理尺寸?

如何为不同版本的 Xcode 编写条件