如何解决Android LocationListener,onStatusChanged和onProviderDisabled上的AbstractMethodError
我有一个带有按钮的简单活动,该按钮使用LocationManager尝试获取当前位置:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button buttonGps = findViewById(R.id.buttonGps);
final Context activity = this;
buttonGps.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!checkForPhonePermission()) {
return;
}
LocationManager locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
Log.d(TAG,location.getLatitude() + "");
}
},Looper.myLooper());
}
});
}
我在API级别为22的Android Studio中创建了一个模拟器,并在授予权限并启用了模拟器gps的情况下,单击按钮时该应用崩溃,并显示此错误:
java.lang.AbstractMethodError: abstract method "void android.location.LocationListener.onStatusChanged(java.lang.String,int,android.os.Bundle)"
java.lang.AbstractMethodError: abstract method "void android.location.LocationListener.onProviderdisabled(java.lang.String)"
如果我在小米Mi A1上尝试该应用程序,则只会在gps关闭并单击按钮时崩溃,而在gps开启并按下按钮时不会崩溃。
From the documentation,这些方法已标记为默认方法,因此我无需实现它们。
此行为有任何原因吗?
解决方法
只需在代码末尾添加这三个函数:
@Override
public void onProviderEnabled(@NonNull String provider) {
}
@Override
public void onProviderDisabled(@NonNull String provider) {
}
@Override
public void onStatusChanged(String provider,int status,Bundle extras) {
}
并编写您要在状态更改时执行的代码
,这是我的情况。在 Android 9 (API 28) 和 Android 10 (API 29) 上,在 android.location.LocationManager 类中有此方法:
private void _handleMessage(Message msg) {
switch (msg.what) {
case TYPE_LOCATION_CHANGED:
Location location = new Location((Location) msg.obj);
mListener.onLocationChanged(location);
break;
case TYPE_STATUS_CHANGED:
Bundle b = (Bundle) msg.obj;
String provider = b.getString("provider");
int status = b.getInt("status");
Bundle extras = b.getBundle("extras");
mListener.onStatusChanged(provider,status,extras);
break;
case TYPE_PROVIDER_ENABLED:
mListener.onProviderEnabled((String) msg.obj);
break;
case TYPE_PROVIDER_DISABLED:
mListener.onProviderDisabled((String) msg.obj);
break;
}
locationCallbackFinished();
}
这似乎被称为。此外,Android 29 和 Android 30 之间 LocationListener 的实现差异如下:
Android 29:
public interface LocationListener {
void onLocationChanged(Location location);
@Deprecated
void onStatusChanged(String provider,Bundle extras);
void onProviderEnabled(String provider);
void onProviderDisabled(String provider);
}
Android 30:
public interface LocationListener {
void onLocationChanged(@NonNull Location location);
@Deprecated
default void onStatusChanged(String provider,Bundle extras) {}
default void onProviderEnabled(@NonNull String provider) {}
default void onProviderDisabled(@NonNull String provider) {}
}
很明显,“默认”这个词是有区别的。鉴于我和你有同样的问题,我现在需要找到一个解决方法。或者使用mohit48的响应。祝你好运!
,我对上面的答案并不完全满意,决定详细说明一下。
正如@sunlover3 正确指出的那样,有问题的方法的实现已更改。在 API 30 之前,它们是抽象的,这意味着如果 compileSdk 不是 30,则 OP 的代码将给出编译错误(这些方法必须已实现)。但是在API 30中他们添加了空的默认方法的实现,这意味着如果compileSdk是30,编译器检查这些方法并且没有给出错误,它们已经实现了。
但是,如果在 compileSdk 30 和版本低于 30 的旧操作系统上运行应用程序,这些方法的实现仍然很旧,即没有,它们是抽象的!因此,错误。
老实说,这是明显的 SDK 开发人员错误,这种事情绝对不能发生。在最坏的情况下,应该有一个编译时警告,为了旧版本的兼容性,仍然应该覆盖这些方法。我希望在这个话题上比我更懒的人能向 google tracker 报告这个问题!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。