微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Android LocationListener,onStatusChanged和onProviderDisabled上的AbstractMethodError

如何解决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)"

如果我在gps关闭的情况下按下按钮,则会收到此错误

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 举报,一经查实,本站将立刻删除。