Android位置侦听器、抽象方法在状态已更改和提供程序已禁用时出错

zc0qhyus  于 2022-11-27  发布在  Android
关注(0)|答案(6)|浏览(156)

我有一个带按钮的简单Activity,它使用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());
        }
    });
}

我在Android Studio中创建了一个模拟器,API级别为22,在授予权限后,在模拟器的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)"

如果我在小米A1上试用这款应用,它只会在GPS关闭并点击按钮时崩溃,而不会在GPS打开并按下按钮时崩溃。
From the documentation,这些方法都标记为default,所以我不需要实现它们。
这种行为有什么原因吗?

ezykj2lf

ezykj2lf1#

只需在代码末尾添加以下三个函数:

@Override
public void onProviderEnabled(@NonNull String provider) {

}

@Override
public void onProviderDisabled(@NonNull String provider) {

}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
    
}

并编写要在状态更改时执行的代码

r3i60tvu

r3i60tvu2#

我对上面的答案并不完全满意,决定再详细说明一点。
正如@sunlover3正确地指出的,有问题的方法的实现被改变了。在API 30之前,它们是抽象的,这意味着如果compileSdk不是30,OP的代码将给予编译错误(这些方法必须已经被实现了).但是在API 30中他们添加了空的默认方法的实现,这意味着如果compileSdk是30,如果编译器检查这些方法并且没有给出错误,则它们已经实现。
但是,如果一个人在版本低于30的旧操作系统上运行一个compileSdk 30的应用程序,这些方法的实现仍然是旧的,i.o.没有,它们是抽象的!因此,错误。
老实说,这是一个明显的SDK的开发错误,这样的事情不应该发生。在最坏的情况下,应该有一个编译时警告,一个人仍然应该覆盖这些方法的旧版本兼容性。我希望有人不懒于我在这个主题上将报告给谷歌跟踪器:)

juud5qan

juud5qan3#

在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, int status, 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, int status, Bundle extras) {}

    default void onProviderEnabled(@NonNull String provider) {}

    default void onProviderDisabled(@NonNull String provider) {}
}

很明显,“默认”这个词就是区别。鉴于我和你有同样的问题,我现在需要找到一个解决方案。或者使用mohit 48的响应。祝你好运!

irlmq6kh

irlmq6kh4#

我遇到了同样的问题,我设法通过覆盖上面建议的onStatusChanged()来解决它。
然而,Android团队可能正在做一些事情,我发现有this接口,解决了这个问题,而没有覆盖,据我测试。
您可以查看androidx. core. location软件包的here摘要。
为了在项目中使用这些新类,您应该使用androidx. core的最新测试版。阅读here

ubbxdtey

ubbxdtey5#

覆写程式码中的方法。...

override fun onProviderDisabled(provider: String) {}
override fun onProviderEnabled(provider: String) {}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {}
...
wnvonmuf

wnvonmuf6#

仅添加实现LocationListener
@覆盖公共void onProviderEnabled(@非空字符串提供程序){
}
@Override public void onProviderDisabled(@非空字符串提供程序){
}
@Override public void onStatusChanged(字符串提供程序,int状态,捆绑包附加项){
}

相关问题