如何检测用户是否在设置中关闭了位置?
How to detect if user turned off Location in Settings?
我想检测用户是否在运行时关闭了定位功能。我可以检查他是否打开它,或者该位置是否在应用程序启动之前被用户关闭,但我无法检查他是否在之后将其关闭。
代码示例:
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)
}
更新
如果要支持Android6.0,就不能使用abstractclass。因为它将尝试根据 AndroidManifest 中定义的 class 创建对象。 Android 8.0+ 不会检查 AndroidManifest 中的接收器,因此您可以从抽象 Class 中实例化对象。因此,与其创建接口,不如创建接口。
您可以为此目的使用广播接收器,它会在状态更改时触发。
检查这个 Answer
我实际上是用 BroadcastReceiver
来做的。
我可以分享我的代码;它是 java,但我认为您可以轻松地将其转换为 kotlin。
- 创建
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){
}
}
}
- 将您的
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
中添加操作将不起作用。
请使用以下方法启用位置设置:
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
}
我想检测用户是否在运行时关闭了定位功能。我可以检查他是否打开它,或者该位置是否在应用程序启动之前被用户关闭,但我无法检查他是否在之后将其关闭。
代码示例:
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)
}
更新
如果要支持Android6.0,就不能使用abstractclass。因为它将尝试根据 AndroidManifest 中定义的 class 创建对象。 Android 8.0+ 不会检查 AndroidManifest 中的接收器,因此您可以从抽象 Class 中实例化对象。因此,与其创建接口,不如创建接口。
您可以为此目的使用广播接收器,它会在状态更改时触发。 检查这个 Answer
我实际上是用 BroadcastReceiver
来做的。
我可以分享我的代码;它是 java,但我认为您可以轻松地将其转换为 kotlin。
- 创建
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){
}
}
}
- 将您的
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
中添加操作将不起作用。
请使用以下方法启用位置设置:
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
}