为目标 API 级别 29 编译时,在 Android API 级别 < 24 上访问 NMEA?

Accessing NMEA on Android API level < 24 when compiled for target API level 29?

我刚刚尝试更新目标并将我们应用程序的 API 级别编译为 29 (Android 10) 并注意到我无法再编译,因为 LocationManager.addNmeaListener 只接受 OnNmeaMessageListener(在 API 级别 24 中引入)而不是旧的和弃用的 GpsStatus.NmeaListener(所以,我得到“不兼容的类型:NmeaListener 无法转换为 OnNmeaMessageListener ").

我知道 addNmeaListener(NmeaListener) 在以前的版本中已被弃用,我准备重构我的代码以针对不同的 API 级别进行分支,但是由于我找不到任何具有不同名称的弃用方法或 LocationManager 的任何兼容性库,如果我的目标是 Android 10(这在某些时候是强制性的),似乎无法访问 Android 6 设备上的 NMEA 数据。

关于如何在旧设备上获取 NMEA 数据有什么建议吗?

如果有人对如何避免 NMEA 数据有想法,请提供一些额外的背景知识: 我们的应用程序 "phyphox" 旨在让学生使用手机中的传感器进行物理实验。在旧设备(Android 4+)上 运行 对我们来说很重要,因为在物理教育中使用智能手机传感器对于资金很少的学校和学生特别有价值。同时,我们希望所有设备的实验结果具有可比性(new/old,Android/iOS)。因此,我们需要 NMEA 数据来计算大地水准面以上的高度,而不是 WGS84 椭球以上的高度(由 Location.getAltitude() 提供),以便学生获得一致且可比较的结果。因此,任何替代方法的建议也很受欢迎。

您可以在此处查看 API 28 的当前代码:

https://github.com/Staacks/phyphox-android/blob/master/app/src/main/java/de/rwth_aachen/phyphox/gpsInput.java

Android SDK 29 版本中似乎存在问题,提供追溯兼容性的方法被遗漏了。

There is an issue opened in the Android bugtracker

从那个issue的Android工程师的评论来看,推荐的方式是通过反射来访问。。。我还是要测试一下,估计会在以下:

nmeaListenerDeprecated = new GpsStatus.NmeaListener() {
    @Override
    public void onNmeaReceived(long timestamp, String message) {
        // TODO
    }
};
try {
    //noinspection JavaReflectionMemberAccess
    Method addNmeaListener =
        LocationManager.class.getMethod("addNmeaListener", GpsStatus.NmeaListener.class);
    addNmeaListener.invoke(locationManager, nmeaListenerDeprecated);
} catch (Exception exception) {
    // TODO
}

编辑:.invoke() 调用中缺少参数。它需要目标对象引用来执行调用! (自从学习反射以来太久了......从那以后就没有使用过它!)

自从现在(2020 年 11 月)开始,部署到 Google 时允许的最低 Target SDK 为 29,有人可能会再次遇到此错误(就像我遇到的那样)。 然后,今天一个更快的解决方案是:

compileSdkVersion 30