我今天晚上更新了the sample project you referenced 以使用 gradle 构建,并注意到使用 API 级别 17 中引入的setElapsedRealtimeNanos 存在相同的问题。该应用程序在我的 4.4 设备上运行良好,但会因 NoSuchMethodError 上而崩溃我的 4.1 设备。
我深入研究了位置类的源代码,以确切了解 API 17 发生了什么变化。以下是相应的差异:
https://android.googlesource.com/platform/frameworks/base/+/2eeeec248a38ff33999c83f4b8d5bab7d50e79d2%5E%21/
如果您搜索新引入的字段mElapsedRealtimeNano 的用法,您会发现它的值仅在单个位置被查询(保留+ 以指示新插入的行):
+ public boolean isComplete() {
+ if (mProvider == null) return false;
+ if (!mHasAccuracy) return false;
+ if (mTime == 0) return false;
+ if (mElapsedRealtimeNano == 0) return false;
+ return true;
+ }
新引入的“完整”位置概念也仅用于单个位置:
public void setTestProviderLocation(String provider, Location loc) {
+ if (!loc.isComplete()) {
+ if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) {
+ // for backwards compatibility, allow mock locations that are incomplete
+ Log.w(TAG, "Incomplete Location object", new Throwable());
+ loc.makeComplete();
+ } else {
+ throw new IllegalArgumentException(
+ "Location object not complete. Missing timestamps or accuracy?");
+ }
+ }
+
// original setTestProviderLocation code is then executed here
}
由于 API 17 之前的 Location 类中缺少此验证,因此如果您在版本检查中包装对 SystemClock.elapsedRealtimeNanos() 的两个调用,则应用应该在所有 API 级别 >= 7 上正常工作,即
elapsedTimeNanos = SystemClock.elapsedRealtimeNanos();
应该替换为
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
elapsedTimeNanos = SystemClock.elapsedRealtimeNanos();
}
和
mockLocation.setElapsedRealtimeNanos(elapsedTimeNanos);
应该替换为
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mockLocation.setElapsedRealtimeNanos(elapsedTimeNanos);
}
在 SendMockLocationService 类中。 Android Studio 会抱怨 elapsedTimeNanos 可能尚未初始化 - 您可以安全地将其初始化为值 0 来解决此问题。
通过这些更改,该应用程序在我的 4.1 设备上运行良好。如果您在使用旧版 Android 时遇到任何问题,请告诉我。
编辑:repository for my updated version of the Google sample app。