Как определить, отключил ли пользователь местоположение в настройках?

Я хочу определить, отключил ли пользователь местоположение во время выполнения. Я могу проверить, включает ли он его или было ли местоположение отключено пользователем до запуска приложения, но я не могу проверить, выключил ли он его после.

Пример кода: MapEntity расширяет LocationListener

class MapViewer(a: MainActivity, parentView: ViewGroup) : MapEntity(a, parentView) {

    override fun onProviderEnabled(provider: String?) {
        activity.hideGpsSnackbar()
    }

    override fun onProviderDisabled(provider: String?) {
        activity.showGpsSnackbar()
    }

}

Для проверки местоположения GPS в реальном времени я использую GnssStatus.Callback()

ОБНОВИТЬ:

Я создал BroadcastReceiver в соответствии с ответом ниже.

abstract class GPSReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        try {
           val locationManager = context.getSystemService(LOCATION_SERVICE) as LocationManager

             if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                    onGpsChanged(true)
                } else {
                    onGpsChanged(false)
                }
            } catch (ex: Exception) {
                App.log("IsGPSEnabled: $ex")
            }

        }

        abstract fun onGpsChanged(isEnabled: Boolean)
    }

Код внутри одного из моих действий:

private val gpsStatusReceiver = object : GPSReceiver() {

     override fun onGpsChanged(isEnabled: Boolean) {
         if (isEnabled){
             hideGpsSnackbar()
         } else {
             showGpsSnackbar()
         }
     }
}

override fun onStart() {
    super.onStart()
    registerReceiver(gpsStatusReceiver, IntentFilter())
}

override fun onStop() {
    super.onStop()
    unregisterReceiver(gpsStatusReceiver)
}

ОБНОВЛЕНИЕ

Если вы хотите поддерживать Android 6.0, вы не можете использовать абстрактный класс. Потому что он попытается создать объект из этого класса, определенного в AndroidManifest. Android 8.0+ не будет проверять приемник внутри AndroidManifest, поэтому вы можете создать экземпляр объекта из абстрактного класса. Поэтому вместо него создайте интерфейс.


person martin1337    schedule 01.08.2019    source источник


Ответы (3)


На самом деле я делаю это с BroadcastReceiver.

Я могу поделиться своим кодом; это java, но я думаю, вы можете легко преобразовать его в kotlin.

  1. Создайте Broadcastreceiver

Пример:

public class GPSBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
            if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                //isGPSEnabled = true;
            } else {
                //isGPSEnabled = false;
            }
        }catch (Exception ex){
        }
    }
}
  1. Добавьте свой BroadcastReceiver к manifest

Пример:

    <receiver android:name=".others.GPSBroadcastReceiver">
        <intent-filter>
            <action android:name="android.location.PROVIDERS_CHANGED" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

Затем (для моего случая) я управляю этим в своем ApplicationContext следующим образом:

private GPSBroadcastReceiver gpsBroadcastReceiver = new GPSBroadcastReceiver();

@Override
public void onCreate() {
    ....
    registerReceiver(gpsBroadcastReceiver, new IntentFilter());
}

@Override
public void onTerminate() {
    ...
    unregisterReceiver(gpsBroadcastReceiver);
}

Это просто пример, для этого могут быть другие способы, но на самом деле я в порядке с этим; удачи!

Редактировать:

попробуйте добавить это разрешение в свой манифест

<uses-permission android:name="android.permission.ACCESS_GPS" />

Изменить: для Android 8.0+ зарегистрируйте свой BroadcastReceiver следующим образом:

registerReceiver(gpsBroadcastReceiver,IntentFilter("android.location.PROVIDERS_CHANGED"))

Добавление действия внутри AndroidManifest не сработает.

person Pier Giorgio Misley    schedule 01.08.2019
comment
@ martin1337 проверьте правки, возможно, я забыл упомянуть, чтобы добавить разрешение - person Pier Giorgio Misley; 01.08.2019
comment
добавлено разрешение, но все равно ничего - person martin1337; 01.08.2019
comment
@ martin1337 ваш журнал написан в logcat? - person Pier Giorgio Misley; 01.08.2019
comment
Неа. Я не получил никаких журналов от приемника. Я немного обновил свое решение. Получатель является абстрактным классом, и метод переопределения onGpsChanged должен возвращать статус моей активности. Но ничего не произошло. - person martin1337; 01.08.2019
comment
@ martin1337 martin1337, если вы замените onGpsChanged (bool) журналом, вы что-нибудь получите? попробуйте отладку; поставьте точку останова в onReceive и проверьте, вызвана ли она и когда - person Pier Giorgio Misley; 01.08.2019
comment
Это проблема. onReceive никогда не вызывается. Это означает, что android.location.PROVIDERS_CHANGED не будет запускаться в месте, включенном в настройках. - person martin1337; 01.08.2019
comment
Я нашел аналогичную проблему здесь stackoverflow.com/questions/48659124/ Может быть, поэтому. Я тестирую его на Android 9.0, поэтому есть вероятность, что регистрация приемника внутри манифеста не будет работать. registerReceiver(gpsStatusReceiver, IntentFilter("android.location.PROVIDERS_CHANGED")) исправил проблему. - person martin1337; 01.08.2019
comment
@ martin1337 о, черт, я забыл об этом, потому что мне это не нужно .. спасибо за редактирование! и рад, что вы решили проблему! - person Pier Giorgio Misley; 01.08.2019

Для этой цели вы можете использовать широковещательные приемники, которые будут запускаться при изменении состояния. Проверьте этот ответ

person Furqan Khan    schedule 01.08.2019
comment
И почему здесь не работает onProviderEnabled и onProviderDisabled? - person martin1337; 01.08.2019

Пожалуйста, используйте следующий подход, чтобы включить настройки местоположения:

LocationServices
        .getSettingsClient(this)
        .checkLocationSettings(mLocationSettingsRequest)
        .addOnSuccessListener(this, object : OnSuccessListener<LocationSettingsResponse> {    
                override fun onSuccess(locationSettingsResponse: LocationSettingsResponse) {
                    Log.i(TAG, "LocationManager: All location settings are satisfied.");
                    mLocationCallback?.let {
                        fusedLocationClient?.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
                    }
                    //updateUI();
                }
        })
        .addOnFailureListener(this, object : OnFailureListener {
                override fun onFailure(e: Exception) {
                    var statusCode = (e as ApiException).getStatusCode()
                    when (statusCode) {
                        LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                            try {
                                // Show the dialog by calling startResolutionForResult(), and check the
                                // result in onActivityResult().
                                var rae = e as ResolvableApiException;
                                rae.startResolutionForResult(this@BaseLocationActivity, REQUEST_CHECK_SETTINGS);
                            } catch (sie: IntentSender.SendIntentException) {
                                Log.i(TAG, "PendingIntent unable to execute request.");
                            }
                        }
                        LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                            mRequestingLocationUpdates = false;
                        }    
                    }
                }
        })

Создать запрос местоположения

private fun createLocationRequest(interval: Long, distance: Float = 0f) {
    mLocationRequest = LocationRequest()
    mLocationRequest.interval = interval
    mLocationRequest.fastestInterval = interval

    Log.v(TAG, "distance => $distance")
    if (distance > 0) {
        mLocationRequest.smallestDisplacement = distance
    }
    mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
person Mustansar Saeed    schedule 01.08.2019